diff --git a/README.md b/README.md index c15561292..048381aa9 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,4 @@ Grails Datastore API === -[Grails][Grails] is a framework used to build web applications with the [Groovy][Groovy] programming language. This project provides the plumbings for the GORM API both for Hibernate and for new implementations of GORM ontop of NoSQL datastores. -[Grails]: http://grails.org/ -[Groovy]: http://groovy.codehaus.org/ - - -Getting Started ---- - -For further information on the project see the comprehensive [developer guide][Developer Guide]. -[Developer Guide]: http://springsource.github.com/grails-data-mapping/ - -License ---- - -Grails and Groovy are licensed under the terms of the [Apache License, Version 2.0][Apache License, Version 2.0]. -[Apache License, Version 2.0]: http://www.apache.org/licenses/LICENSE-2.0.html +This repository has moved to https://github.com/grails/grails-data-mapping \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 8d0bd1cf4..000000000 --- a/build.gradle +++ /dev/null @@ -1,425 +0,0 @@ -project.ext { - springVersion = "3.2.3.RELEASE" - grailsVersion = "2.3.0" - slf4jVersion = "1.7.2" - groovyVersion = System.getProperty('groovyVersion') ?: '2.1.5' -} - -def groovyMajorVersion = groovyVersion[0..2] -def spockDependency = "org.spockframework:spock-core:0.7-groovy-2.0" - -def groovyProjects() { - subprojects.findAll { project -> isGroovyProject(project) } -} - -def isGroovyProject(project) { - def isGrailsPlugin = project.name.contains("grails-plugins") - def isDocumentation = project.name.contains("documentation") - !isGrailsPlugin && !isDocumentation -} - -configurations { - all*.exclude group: "commons-logging" -} - -apply plugin: 'idea' -apply plugin: 'project-report' - - -ext { - isCiBuild = project.hasProperty("isCiBuild") -} -allprojects { - repositories { - if(!isCiBuild) { - mavenLocal() - } - mavenCentral() - maven { url "http://repo.grails.org/grails/core" } - } - - configurations { - all { - resolutionStrategy { -// def cacheHours = isCiBuild ? 1 : 24 -// cacheDynamicVersionsFor cacheHours, 'hours' -// cacheChangingModulesFor cacheHours, 'hours' - } - } - } -} - -task wrapper(type: Wrapper) { - gradleVersion = '1.5' -} - -subprojects { - ext { - releaseType = "RELEASE" -// releaseType = "BUILD-SNAPSHOT" - // releaseType = "RC2" - isCiBuild = project.hasProperty("isCiBuild") - isBuildSnapshot = releaseType == "BUILD-SNAPSHOT" - } - - version = "2.0.1.${releaseType}" - group = "org.grails" - - - def isStandardGroovyMavenProject = isGroovyProject(project) - - if (isStandardGroovyMavenProject) { - apply plugin: 'groovy' - apply plugin: 'eclipse' - apply plugin: 'maven' - apply plugin: 'idea' - apply plugin: 'signing' - sourceCompatibility = "1.6" - targetCompatibility = "1.6" - -/* apply from: "file:${rootDir}/clover.gradle"*/ - - install.doLast { - def gradleArtifactCache = new File(gradle.gradleUserHomeDir, "cache") - configurations.archives.artifacts.findAll { it.type == "jar" && !it.classifier }.each { artifact -> - - // Gradle's cache layout is internal and may change in future versions, this is written for gradle 1.0-milestone-3 - def artifactInCache = file("${gradleArtifactCache}/${project.group}/${project.name}/jars/${project.name}-${version}.jar") - if (artifactInCache.parentFile.mkdirs()) { - artifactInCache.withOutputStream { destination -> artifact.file.withInputStream { destination << it } } - } - } - } - } - - def isGormDatasource = project.name.startsWith("grails-datastore-gorm-") && - !project.name.endsWith("tck") && - !project.name.endsWith("plugin-support") && - project.name != 'grails-datastore-gorm-hibernate-core'&& - project.name != 'grails-datastore-gorm-rest-client' - def isDocumentationProject = project.name.startsWith("grails-documentation") - - dependencies { - if (isStandardGroovyMavenProject) { - groovy group: 'org.codehaus.groovy', name: 'groovy-all', version: groovyVersion - - testCompile 'junit:junit:4.8.2' - testCompile (spockDependency) { - transitive = false - } - } - - if (project.name == "grails-datastore-gorm-tck") { - compile spockDependency - } - } - - if (isDocumentationProject) { - configurations { - documentation - } - dependencies { - documentation group: 'org.grails', name: 'grails-docs', version: '2.0.0' - project(":grails-datastore-core") - documentation "org.slf4j:jcl-over-slf4j:$slf4jVersion" - documentation "org.slf4j:slf4j-api:$slf4jVersion" - documentation "org.slf4j:slf4j-simple:$slf4jVersion" - } - task docs << { - ant.taskdef (name: 'docs', classname : 'grails.doc.ant.DocPublisherTask') { - classpath { - configurations.documentation.resolve().each { f -> - pathelement(location:f) - } - } - - } - ant.docs(src:"src/docs", dest:destinationDir, properties:"src/docs/doc.properties") - } - docs.ext.destinationDir = "${buildDir}/docs" - - - task clean << { - ant.delete(dir:buildDir) - } - } - - if (isGormDatasource) { - dependencies { - testCompile project(":grails-datastore-gorm-tck") - } - - // We need to test against the TCK. Gradle cannot find/run tests from jars - // without a lot of plumbing, so here we copy the class files from the TCK - // project into this project's test classes dir so Gradle can find the test - // classes and run them. See grails.gorm.tests.GormDatastoreSpec for on the TCK. - - // helper, used below. - def toBaseClassRelativePathWithoutExtension = { String base, String classFile -> - if (classFile.startsWith(base)) { - def sansClass = classFile[0 .. classFile.size() - ".class".size() - 1] - def dollarIndex = sansClass.indexOf('$') - def baseClass = dollarIndex > 0 ? sansClass[0..dollarIndex - 1] : sansClass - def relative = baseClass - base - '/' - relative - } - else { - null - } - } - - test { - maxHeapSize = '2048m' - } - test.doFirst { - def tckClassesDir = project(":grails-datastore-gorm-tck").sourceSets.main.output.classesDir - def thisProjectsTests = // surely there is a less hardcoded way to do this - copy { - from tckClassesDir - into sourceSets.test.output.classesDir - include "**/*.class" - exclude { details -> - // Do not copy across any TCK class (or nested classes of that class) - // If there is a corresponding source file in the particular modules - // test source tree. Allows a module to override a test/helper. - - def candidatePath = details.file.absolutePath - def relativePath = toBaseClassRelativePathWithoutExtension(tckClassesDir.absolutePath, candidatePath) - - if (relativePath == null) { - throw new IllegalStateException("$candidatePath does not appear to be in the TCK") - } - - project.file("src/test/groovy/${relativePath}.groovy").exists() - } - } - } - } - - if (isStandardGroovyMavenProject) { - - task sourcesJar(type: Jar, dependsOn:classes) { - classifier = 'sources' - from sourceSets.main.allSource - } - - task javadocJar(type: Jar, dependsOn:javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir - } - - artifacts { - archives jar - archives sourcesJar - archives javadocJar - } - - signing { - sign configurations.archives - required { !isBuildSnapshot && gradle.taskGraph.hasTask(uploadArchives) } - } - - configure(install.repositories.mavenInstaller) { - pom.whenConfigured { pom -> - def dependency = pom.dependencies.find { dep -> dep.artifactId == 'slf4j-simple' } - dependency?.optional = true - } - pom.project { - licenses { - license { - name 'The Apache Software License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - distribution 'http://github.com/SpringSource/grails-data-mapping/' - } - } - } - } - - uploadArchives { - description = "Does a maven deploy of archives artifacts" - - // add a configuration with a classpath that includes our s3 maven deployer - configurations { deployerJars } - dependencies { - deployerJars "org.springframework.build.aws:org.springframework.build.aws.maven:3.0.0.RELEASE" - } - - repositories.mavenDeployer { - beforeDeployment { MavenDeployment deployment -> - signing.signPom(deployment) - } - - 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) - } - snapshotRepository(url: "http://repo.grails.org/grails/libs-snapshots-local") { - authentication(userName: project.hasProperty("artifactoryPublishUsername") ? project.artifactoryPublishUsername : null, - password: project.hasProperty("artifactoryPublishPassword") ? project.artifactoryPublishPassword : null) - } - - pom.project { - name 'Grails GORM' - packaging 'jar' - description 'GORM - Grails Data Access Framework' - delegate.url 'http://grails.org/' - - licenses { - license { - name 'The Apache Software License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - distribution 'repo' - } - } - - scm { - delegate.url 'scm:git@github.com:SpringSource/grails-data-mapping.git' - connection 'scm:git@github.com:SpringSource/grails-data-mapping.git' - developerConnection 'scm:git@github.com:SpringSource/grails-data-mapping.git' - } - - licenses { - license { - name 'The Apache Software License, Version 2.0' - delegate.url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - distribution 'repo' - } - } - - developers { - developer { - id 'graemerocher' - name 'Graeme Rocher' - } - developer { - id 'jeffscottbrown' - name 'Jeff Brown' - } - developer { - id 'burtbeckwith' - name 'Burt Beckwith' - } - } - } - } - } - } -} - -configurations { - build -} - -repositories { - mavenCentral() -} - -dependencies { - build "com.cenqua.clover:clover:3.0.2" - build "org.apache.ant:ant-junit:1.8.1" - build "org.apache.ant:ant-nodeps:1.8.1" -} - -task allDocs(dependsOn: getTasksByName("docs", true)) << { - def docTasks = getTasksByName("docs", true) - def groovydocTasks = getTasksByName("groovydoc", true) - allDocsDir = "$buildDir/docs" - mkdir allDocsDir - def stores = [] - for(task in docTasks) { - def dir = task.destinationDir - def projectName = task.project.name - if (projectName.endsWith("core")) { - mkdir "$allDocsDir/manual" - fileTree { from dir }.copy { into "$allDocsDir/manual" } - def groovydocTask = groovydocTasks.find { it.project.name.endsWith "core" } - if (groovydocTask != null) { - mkdir "$allDocsDir/api" - groovydocTask.actions.each { it.execute(groovydocTask) } - - fileTree { from groovydocTask.destinationDir }.copy { into "$allDocsDir/api"} - } - } - else { - def storeName = projectName["grails-documentation-".size()..-1] - stores << storeName - def docsDir = "$allDocsDir/$storeName" - mkdir docsDir - def groovydocTask = groovydocTasks.find { it.project.name == "grails-datastore-$storeName" } - if (groovydocTask == null) groovydocTask = groovydocTasks.find { it.project.name == "grails-datastore-gorm-$storeName" } - if (groovydocTask != null) { - mkdir "$docsDir/api" - groovydocTask.actions.each { it.execute(groovydocTask) } - fileTree { from groovydocTask.destinationDir }.copy { into "$docsDir/api"} - } - mkdir "$docsDir/manual" - fileTree { from dir }.copy { into "$docsDir/manual" } - } - - def engine = new groovy.text.SimpleTemplateEngine() - def binding = [ - datastores:stores.collect { "
  • GORM for ${it[0].toUpperCase()}${it[1..-1]}
  • " }.join(System.getProperty("line.separator")) - ] - def template = engine.createTemplate(new File("src/docs/resources/core.template")).make(binding) - new File("$allDocsDir/index.html").text = template.toString() - - for(store in stores) { - def index = "$allDocsDir/$store/index.html" - def storeName = "${store[0].toUpperCase()}${store[1..-1]}".toString() - binding = [ - datastore:storeName - ] - template = engine.createTemplate(new File("src/docs/resources/datastore.template")).make( binding ) - new File(index).text = template.toString() - } - } -} - -task test(dependsOn: getTasksByName("test", true)) << { - def reportsDir = "${buildDir}/reports" - - // Aggregate the test results - ant.taskdef( - name: 'junitreport2', - classname: "org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator", - classpath: configurations.build.asPath - ) - - def testReportsDir = new File("${reportsDir}/tests") - if (testReportsDir.exists()) { - testReportsDir.deleteDir() - } - testReportsDir.mkdirs() - - ant.junitreport2(todir: testReportsDir) { - subprojects.each { - def testResultsDir = "${it.buildDir}/test-results" - if (new File(testResultsDir).exists()) { - fileset(dir: testResultsDir) { - include(name: "TEST-*.xml") - } - } - } - report(todir: testReportsDir) - } - - // Aggregate the coverage results - if (project.hasProperty("withClover")) { - def db = "clover/clover.db" - def mergedDb = "${buildDir}/${db}" - def cloverReportsDir = "${reportsDir}/clover" - ant.taskdef(resource: "cloverlib.xml", classpath: configurations.build.asPath) - ant."clover-merge"(initstring: mergedDb) { - subprojects.each { - def projectCloverDb = "${it.buildDir}/${db}" - if (new File(projectCloverDb).exists()) { - cloverdb(initstring: projectCloverDb) - } - } - } - ant."clover-report"(initstring: mergedDb) { - current(outfile:"${cloverReportsDir}/clover.xml") - } - ant."clover-html-report"(initstring: mergedDb, outdir:"${cloverReportsDir}/html") - } -} diff --git a/clover.gradle b/clover.gradle deleted file mode 100644 index cd39032b4..000000000 --- a/clover.gradle +++ /dev/null @@ -1,94 +0,0 @@ -apply plugin: "groovy" - -def cloverConvention = new CloverPluginConvention(project) -project.convention.plugins.clover = cloverConvention - -class CloverPluginConvention { - def classesBackupDir - def licenseFile - - def clover(Closure close) { - close.delegate = this - close.run() - } - - CloverPluginConvention(Project project) { - classesBackupDir = "${project.sourceSets.main.classesDir}-bak" - licenseFile = "/Developer/grails-dev/core/inconsequential/clover.license" - } -} - -dependencies { - testRuntime "com.cenqua.clover:clover:3.0.2" -} - -test.doFirst { - if (project.hasProperty("withClover")) { - ant.taskdef(name: 'groovyc', classname:"org.codehaus.groovy.ant.Groovyc", classpath:configurations.testRuntime.asPath) - ant.taskdef(resource:"cloverlib.xml", classpath:configurations.testRuntime.asPath) - ant.property(name:"clover.license.path", value:cloverConvention.licenseFile) - - ant."clover-clean"() - - ant.'clover-setup'(initString: "${buildDir}/clover/clover.db", tmpDir: "${buildDir}/clover/tmp") { - ["java", "groovy"].each { source -> - ["main", "test"].each { type -> - sourceSets."$type"."$source".srcDirs.each { - if (it.exists()) { - ant.fileset(dir: it) { - include(name: "**/*.groovy") - include(name: "**/*.java") - } - } - } - } - } - } - - //move original classes - ant.move(file:sourceSets.main.classesDir, tofile:cloverConvention.classesBackupDir) - - //compile instrumented classes - sourceSets.main.classesDir.mkdirs() - ant.groovyc( - destdir:sourceSets.main.classesDir, - fork: true, - verbose: true - ) { - classpath { - pathElement path:configurations.testCompile.asPath - } - javac(source:sourceCompatibility, target: targetCompatibility) { - classpath { - pathElement path:configurations.testRuntime.asPath - } - } - - ["java", "groovy"].each { source -> - sourceSets.main."$source".srcDirs.each { - if (it.exists()) { - src(path: it) - } - } - } - } - - //copy resources - ant.copy(todir:sourceSets.main.classesDir) { - fileset(dir:cloverConvention.classesBackupDir, excludes:"**/*.class") - } - } -} - -test.doLast { - if (project.hasProperty("withClover") && new File(cloverConvention.classesBackupDir).exists()) { - // restore original classes - ant.delete(file: sourceSets.main.classesDir) - ant.move(file:cloverConvention.classesBackupDir, tofile:sourceSets.main.classesDir) - - ant."clover-report" { - current(outfile:"${reportsDir}/clover/clover.xml") - } - ant."clover-html-report"(outdir:"${reportsDir}/clover/html"); - } -} \ No newline at end of file diff --git a/clover.license b/clover.license deleted file mode 100644 index b5536cf8e..000000000 --- a/clover.license +++ /dev/null @@ -1,5 +0,0 @@ -pmqOPPevJRxewUAoSwGTXaKrPNwRSFgqNRUUNwpFTlvnMC -mi2KC0BWSj8iuzoLZUtK<49L2K70p6Dqxa0wTtoVPIQuB2 -rqRoTuoqpmNOnopnoOpTUOmonooOQQRnoRUUTvSwvxuvPP -nmQnmqmUUnottnouummmmmUUnottnouummmmmUU7oXfipU -Unmmmm diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index e69de29bb..000000000 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index b46aef33a..000000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 046a49c8f..000000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Sat Apr 13 14:57:47 EDT 2013 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=http\://services.gradle.org/distributions/gradle-1.5-bin.zip diff --git a/gradlew b/gradlew deleted file mode 100755 index 91a7e269e..000000000 --- a/gradlew +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index aec99730b..000000000 --- a/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/grails-datastore-appengine/build.gradle b/grails-datastore-appengine/build.gradle deleted file mode 100644 index 17e9a8425..000000000 --- a/grails-datastore-appengine/build.gradle +++ /dev/null @@ -1,14 +0,0 @@ -repositories { - mavenRepo urls:'http://maven-gae-plugin.googlecode.com/svn/repository/' -} - -dependencies { - compile project(":grails-datastore-core") - compile "com.google.appengine:appengine-api-1.0-sdk:1.3.4" - compile "com.google.appengine:appengine-api-stubs:1.3.4" - - testCompile "com.google.appengine:appengine-tools-api:1.3.4" - testCompile "com.google.appengine:appengine-testing:1.3.4" - testCompile "com.google.appengine:appengine-local-runtime:1.3.4" - testRuntime "com.google.appengine:appengine-api-labs:1.3.4" -} diff --git a/grails-datastore-appengine/src/main/java/org/grails/datastore/mapping/appengine/AppEngineDatastore.java b/grails-datastore-appengine/src/main/java/org/grails/datastore/mapping/appengine/AppEngineDatastore.java deleted file mode 100644 index c26ba8bb2..000000000 --- a/grails-datastore-appengine/src/main/java/org/grails/datastore/mapping/appengine/AppEngineDatastore.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.grails.datastore.mapping.appengine; - -import java.util.Map; - -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext; - -/** - * @author Graeme Rocher - * @author Guillaume Laforge - * @since 1.0 - */ -public class AppEngineDatastore extends AbstractDatastore { - - // hard coded value of "gae" used for the keyspace since GAE manages spaces automatically - public AppEngineDatastore() { - super(new KeyValueMappingContext("gae")); - } - - @Override - protected Session createSession(@SuppressWarnings("hiding") Map connectionDetails) { - return new AppEngineSession(this, getMappingContext()); - } -} diff --git a/grails-datastore-appengine/src/main/java/org/grails/datastore/mapping/appengine/AppEngineSession.java b/grails-datastore-appengine/src/main/java/org/grails/datastore/mapping/appengine/AppEngineSession.java deleted file mode 100644 index fe2907a81..000000000 --- a/grails-datastore-appengine/src/main/java/org/grails/datastore/mapping/appengine/AppEngineSession.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.grails.datastore.mapping.appengine; - -import com.google.appengine.api.datastore.*; -import org.grails.datastore.mapping.appengine.engine.AppEngineEntityPersister; -import org.grails.datastore.mapping.core.AbstractSession; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.keyvalue.KeyValueSession; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.transactions.Transaction; - -import java.util.*; - -/** - * Google App Engine session to the datastore - * - * @author Graeme Rocher - * @author Guillaume Laforge - * - * @since 1.0 - */ -public class AppEngineSession extends AbstractSession implements KeyValueSession { - protected DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService(); - private AppEngineTransaction transaction; - - /** - * Create a new Google App Engine session to the datastore. - * - * @param mappingContext The Mapping Context - */ - public AppEngineSession(Datastore ds,MappingContext mappingContext) { - super(ds, mappingContext); - } - - public Key store(String table, Map object) { - Entity entity = new Entity(table); - Set keySet = object.keySet(); - for (Object aKeySet : keySet) { - String propertyName = (String) aKeySet; - Object value = object.get(propertyName); - entity.setProperty(propertyName, value); - } - return datastoreService.put(entity); - } - - public Map retrieve(Key key) { - try { - Entity entity = datastoreService.get(key); - return entity.getProperties(); - } catch (EntityNotFoundException e) { - return null; - } - } - - public List> retrieve(Key... keys) { - List keysList = new ArrayList(); - keysList.addAll(Arrays.asList(keys)); - - List> results = new ArrayList>(); - - Map keyEntityMap = datastoreService.get(keysList); - Set keySet = keyEntityMap.keySet(); - for (com.google.appengine.api.datastore.Key aKeySet : keySet) { - Entity value = keyEntityMap.get(aKeySet); - results.add(value.getProperties()); - } - - return results; - } - - public void delete(Key... keys) { - datastoreService.delete(Arrays.asList(keys)); - } - - /** - * @return always true, always connected to the Google App Engine datastore - */ - public boolean isConnected() { - return true; - } - - /** - * Start a new transaction. - * - * @return a started transaction - */ - @Override - protected Transaction beginTransactionInternal() { - AppEngineTransaction engineTransaction = new AppEngineTransaction(DatastoreServiceFactory.getDatastoreService().beginTransaction()); - this.transaction = engineTransaction; - return engineTransaction; - } - - public DatastoreService getNativeInterface() { - return datastoreService; - } - - @Override - protected Persister createPersister(Class cls, MappingContext mappingContext) { - PersistentEntity entity = mappingContext.getPersistentEntity(cls.getName()); - if (entity != null) { - return new AppEngineEntityPersister(mappingContext, entity,this, datastoreService); - } - return null; - } -} diff --git a/grails-datastore-appengine/src/main/java/org/grails/datastore/mapping/appengine/AppEngineTransaction.java b/grails-datastore-appengine/src/main/java/org/grails/datastore/mapping/appengine/AppEngineTransaction.java deleted file mode 100644 index 612068999..000000000 --- a/grails-datastore-appengine/src/main/java/org/grails/datastore/mapping/appengine/AppEngineTransaction.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.grails.datastore.mapping.appengine; - -import com.google.appengine.api.datastore.Transaction; - -/** - * @author Guillaume Laforge - */ -public class AppEngineTransaction implements org.grails.datastore.mapping.transactions.Transaction { - private com.google.appengine.api.datastore.Transaction transaction; - - public AppEngineTransaction(com.google.appengine.api.datastore.Transaction transaction) { - this.transaction = transaction; - } - - public void commit() { - transaction.commit(); - } - - public void rollback() { - transaction.rollback(); - } - - public com.google.appengine.api.datastore.Transaction getNativeTransaction() { - return transaction; - } - - public boolean isActive() { - return transaction.isActive(); - } - - public void setTimeout(int timeout) { - throw new UnsupportedOperationException("Transaction timeouts not supported on AppEngine"); - } -} diff --git a/grails-datastore-appengine/src/main/java/org/grails/datastore/mapping/appengine/engine/AppEngineEntityPersister.java b/grails-datastore-appengine/src/main/java/org/grails/datastore/mapping/appengine/engine/AppEngineEntityPersister.java deleted file mode 100644 index d5e1c8bb3..000000000 --- a/grails-datastore-appengine/src/main/java/org/grails/datastore/mapping/appengine/engine/AppEngineEntityPersister.java +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright (C) 2010 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.mapping.appengine.engine; - -import com.google.appengine.api.datastore.*; -import org.springframework.core.convert.converter.Converter; -import org.springframework.core.convert.converter.ConverterRegistry; -import org.grails.datastore.mapping.appengine.AppEngineSession; -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.engine.PropertyValueIndexer; -import org.grails.datastore.mapping.keyvalue.engine.AbstractKeyValueEntityPesister; -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.Association; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; - -/** - * Implementation of the {@link org.grails.datastore.mapping.engine.EntityPersister} abstract - * class for AppEngine - * - * @author Graeme Rocher - * @since 1.0 - */ -public class AppEngineEntityPersister extends AbstractKeyValueEntityPesister { - protected DatastoreService datastoreService; - protected String entityFamily; - - public AppEngineEntityPersister(MappingContext context, final PersistentEntity entity, AppEngineSession conn, DatastoreService datastoreService) { - super(context, entity, conn); - this.datastoreService = datastoreService; - this.entityFamily = getFamily(entity, entity.getMapping()); - ConverterRegistry conversionService = context.getConverterRegistry(); - - conversionService.addConverter(new Converter() { - public com.google.appengine.api.datastore.Key convert(Object source) { - if (source instanceof com.google.appengine.api.datastore.Key) { - return (com.google.appengine.api.datastore.Key)source; - } - else if (source instanceof Long) { - return KeyFactory.createKey(entityFamily, (Long) source); - } - else { - return KeyFactory.createKey(entityFamily,source.toString()); - } - } - }); - } - - @Override - protected Object getEntryValue(Entity nativeEntry, String property) { - return nativeEntry.getProperty(property); - } - - @Override - protected void setEntryValue(Entity nativeEntry, String propKey, Object value) { - nativeEntry.setProperty(propKey, value); - } - - @Override - protected Entity retrieveEntry(PersistentEntity persistentEntity, String family, Serializable nativekey) { - com.google.appengine.api.datastore.Key nativeKey = inferNativeKey(family, nativekey); - return getEntity(nativeKey); - } - - private Entity getEntity(com.google.appengine.api.datastore.Key nativeKey) { - try { - return datastoreService.get(nativeKey); - } catch (EntityNotFoundException e) { - return null; - } - } - - @Override - protected Entity createNewEntry(String family) { - return new Entity(family); - } - - @Override - protected com.google.appengine.api.datastore.Key storeEntry(PersistentEntity persistentEntity, Key storeId, Entity nativeEntry) { - return this.datastoreService.put(nativeEntry); - } - - @Override - protected void updateEntry(PersistentEntity persistentEntity, com.google.appengine.api.datastore.Key key, Entity entry) { - if (entry != null) { - Entity existing = getEntity(key); - final Map props = entry.getProperties(); - for (String name : props.keySet()) { - existing.setProperty(name, props.get(name)); - } - datastoreService.put(existing); - } - } - - @Override - protected void deleteEntry(String family, Key key) { - datastoreService.delete(key); - } - - @Override - public AssociationIndexer getAssociationIndexer(Entity nativeEntry, Association association) { - return null; // TODO: Support one-to-many associations in GAE - } - - @Override - public PropertyValueIndexer getPropertyIndexer(PersistentProperty property) { - // TODO: GAE natively supports creating indices so not sure implementing this will be useful - return null; - } - - @Override - protected Key generateIdentifier(PersistentEntity persistentEntity, Entity entity) { - return datastoreService.put(entity); - } - - @Override - protected com.google.appengine.api.datastore.Key inferNativeKey(String family, Object identifier) { - if (identifier instanceof Long) { - identifier = KeyFactory.createKey(family,(Long) identifier); - } - else if (!(identifier instanceof com.google.appengine.api.datastore.Key)) { - identifier = KeyFactory.createKey(family, identifier.toString()); - } - return (com.google.appengine.api.datastore.Key) identifier; - } - - @Override - protected void deleteEntries(String family, List keys) { - this.datastoreService.delete(keys.toArray(new com.google.appengine.api.datastore.Key[keys.size()])); - } - - public org.grails.datastore.mapping.query.Query createQuery() { - return null; // TODO: Implement querying for GAE - } -} 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 725fbaf53..000000000 --- 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-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/AppEngineDatastoreTest.java b/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/AppEngineDatastoreTest.java deleted file mode 100644 index f369ef0a3..000000000 --- a/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/AppEngineDatastoreTest.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.grails.datastore.mapping.appengine; - -import com.google.appengine.api.datastore.*; -import org.grails.datastore.mapping.appengine.testsupport.AppEngineDatastoreTestCase; -import org.grails.datastore.mapping.keyvalue.KeyValueSession; -import org.grails.datastore.mapping.transactions.Transaction; -import org.junit.Before; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.*; - -/** - * @author Guillaume Laforge - */ -public class AppEngineDatastoreTest extends AppEngineDatastoreTestCase { - - private DatastoreService service = DatastoreServiceFactory.getDatastoreService(); - - private Map personOne; - private Map personTwo; - - @Before - public void fixtureData() throws Exception { - - personOne = new HashMap(); - personOne.put("firstname", "Guillaume"); - personOne.put("lastname", "Laforge"); - - personTwo = new HashMap(); - personTwo.put("firstname", "Jar Jar"); - personTwo.put("lastname", "Binks"); - } - - public void testStore() { - AppEngineDatastore engineDatastore = new AppEngineDatastore(); - KeyValueSession conn = (KeyValueSession) engineDatastore.connect(null); - conn.store("persons", personOne); - conn.store("persons", personTwo); - - List results = service.prepare(new Query("persons")).asList(FetchOptions.Builder.withLimit(100)); - assertEquals(2, results.size()); - } - - public void testStoreAndRetreiveOneEntity() { - AppEngineDatastore engineDatastore = new AppEngineDatastore(); - - KeyValueSession conn = (KeyValueSession) engineDatastore.connect(null); - - Key key = (Key) conn.store("persons", personOne); - - Map result = conn.retrieve(key); - assertEquals("Guillaume", result.get("firstname")); - assertEquals("Laforge", result.get("lastname")); - } - - public void testStoreAndRetreiveTwoEntities() { - AppEngineDatastore engineDatastore = new AppEngineDatastore(); - KeyValueSession conn = (KeyValueSession) engineDatastore.connect(null); - - Key keyGuillaume = (Key) conn.store("persons", personOne); - Key keyJarJar = (Key) conn.store("persons", personTwo); - - List> result = conn.retrieve(keyGuillaume, keyJarJar); - assertEquals(2, result.size()); - } - - public void testStoreAndDelete() { - AppEngineDatastore engineDatastore = new AppEngineDatastore(); - - KeyValueSession conn = (KeyValueSession) engineDatastore.connect(null); - - Key keyGuillaume = (Key) conn.store("persons", personOne); - - Map result = conn.retrieve(keyGuillaume); - assertNotNull(result); - - conn.delete(keyGuillaume); - - Map resultAfterDeletion = conn.retrieve(keyGuillaume); - assertNull(resultAfterDeletion); - } - - public void testTransactionCommit() { - AppEngineDatastore engineDatastore = new AppEngineDatastore(); - KeyValueSession connection = (KeyValueSession) engineDatastore.connect(new HashMap()); - - // start a transaction - Transaction transaction = connection.beginTransaction(); - - // add a new person in the store - Key keyGuillaume = (Key) connection.store("persons", personOne); - - // commit the transaction - transaction.commit(); - - Map result = connection.retrieve(keyGuillaume); - // if the transaction was committed successfully, we should find a result in the store - assertNotNull(result); - } - - public void testTransactionRollback() { - AppEngineDatastore engineDatastore = new AppEngineDatastore(); - KeyValueSession connection = (KeyValueSession) engineDatastore.connect(new HashMap()); - - Transaction transaction = connection.beginTransaction(); - - // add a new person in the store - Key keyGuillaume = (Key) connection.store("persons", personOne); - - transaction.rollback(); - - Map result = connection.retrieve(keyGuillaume); - // as the transaction was rollbacked, we shouldn't find a result in the store - assertNull(result); - - } -} diff --git a/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/EntityPersisterTests.groovy b/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/EntityPersisterTests.groovy deleted file mode 100644 index 32b2ae229..000000000 --- a/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/EntityPersisterTests.groovy +++ /dev/null @@ -1,59 +0,0 @@ -package org.grails.datastore.mapping.appengine - -import com.google.appengine.api.datastore.Key -import org.grails.datastore.mapping.appengine.testsupport.AppEngineDatastoreTestCase -import org.grails.datastore.mapping.core.Session - -/** - * @author Graeme Rocher - * @since 1.1 - */ -class EntityPersisterTests extends AppEngineDatastoreTestCase { - - - - void testPersistObject() { - AppEngineDatastore ds = new AppEngineDatastore() - - Session conn = ds.connect(null) - - ds.getMappingContext().addPersistentEntity(TestEntity) - - TestEntity t = new TestEntity() - t.name = "bob" - t.age = 45 - conn.persist(t) - - assert t.id != null - - def key = t.id - t = conn.retrieve(TestEntity, key) - - assert t != null - assert "bob" == t.name - assert 45 == t.age - - t.age = 55 - - conn.persist(t) - - def t2 = conn.retrieve(TestEntity, key) - assert t != null - assert t.id == t2.id - assert "bob" == t2.name - assert 55 == t2.age - - - conn.delete(key) - - t = conn.retrieve(TestEntity, key) - - assert t == null - - } -} -class TestEntity { - Key id - String name - Integer age -} diff --git a/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/OneToOneAssociationTests.groovy b/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/OneToOneAssociationTests.groovy deleted file mode 100644 index 5da66c749..000000000 --- a/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/OneToOneAssociationTests.groovy +++ /dev/null @@ -1,46 +0,0 @@ -package org.grails.datastore.mapping.appengine - -import com.google.appengine.api.datastore.Key -import grails.persistence.Entity -import org.junit.Test -import org.grails.datastore.mapping.appengine.testsupport.AppEngineDatastoreTestCase -import org.grails.datastore.mapping.core.Session - -/** - * @author Graeme Rocher - * @since 1.1 - */ -class OneToOneAssociationTests extends AppEngineDatastoreTestCase { - @Test - void testPersistOneToOneAssociation() { - def ds = new AppEngineDatastore() - ds.mappingContext.addPersistentEntity(Person) - Session conn = ds.connect(null) - - - def p = new Person(name:"Bob") - p.address = new Address(number:"20", postCode:"39847") - - conn.persist(p) - - p = conn.retrieve(Person, p.id) - - assert p != null - assert "Bob" == p.name - assert p.address != null - assert "20" == p.address.number - - } -} -@Entity -class Person { - Key id - String name - Address address -} -@Entity -class Address { - Key id - String number - String postCode -} diff --git a/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/testsupport/AppEngineDatastoreTestCase.java b/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/testsupport/AppEngineDatastoreTestCase.java deleted file mode 100644 index 077fd6314..000000000 --- a/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/testsupport/AppEngineDatastoreTestCase.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.grails.datastore.mapping.appengine.testsupport; - -import com.google.appengine.api.datastore.dev.LocalDatastoreService; -import com.google.appengine.tools.development.ApiProxyLocal; -import com.google.appengine.tools.development.ApiProxyLocalFactory; -import com.google.appengine.tools.development.LocalServerEnvironment; -import com.google.apphosting.api.ApiProxy; -import org.junit.AfterClass; -import org.junit.BeforeClass; - -import java.io.File; - -/** - * Base test case class for datastore tests taken from the - * Google App Engine testing documentation. - * - * @author Guillaume Laforge - */ -public abstract class AppEngineDatastoreTestCase { - - @BeforeClass - public static void setUp() throws Exception { - ApiProxy.setEnvironmentForCurrentThread(new TestEnvironment()); - ApiProxyLocalFactory factory = new ApiProxyLocalFactory(); - ApiProxyLocal proxyLocal = factory.create(new LocalServerEnvironment() { - public File getAppDir() { - return new File("."); - } - - public String getAddress() { - return "localhost"; - } - - public int getPort() { - return 8080; - } - - public void waitForServerToStart() throws InterruptedException { - //To change body of implemented methods use File | Settings | File Templates. - } - }); - proxyLocal.setProperty(LocalDatastoreService.NO_STORAGE_PROPERTY, Boolean.TRUE.toString()); - ApiProxy.setDelegate(proxyLocal); - } - - @AfterClass - public static void tearDown() throws Exception { - ApiProxyLocal proxy = (ApiProxyLocal) ApiProxy.getDelegate(); - LocalDatastoreService datastoreService = (LocalDatastoreService) proxy.getService(LocalDatastoreService.PACKAGE); - datastoreService.clearProfiles(); - // not strictly necessary to null these out but there's no harm either - ApiProxy.setDelegate(null); - ApiProxy.setEnvironmentForCurrentThread(null); - } -} \ No newline at end of file diff --git a/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/testsupport/TestEnvironment.java b/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/testsupport/TestEnvironment.java deleted file mode 100644 index ab6864e74..000000000 --- a/grails-datastore-appengine/src/test/groovy/org/grails/datastore/mapping/appengine/testsupport/TestEnvironment.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.grails.datastore.mapping.appengine.testsupport; - -import java.util.HashMap; -import java.util.Map; - -import com.google.apphosting.api.ApiProxy; - -/** - * Test environment stub taken from the - * Google App Engine testing documentation. - * - * @author Guillaume Laforge - */ -public class TestEnvironment implements ApiProxy.Environment { - public String getAppId() { - return "test"; - } - - public String getVersionId() { - return "1.0"; - } - - public String getEmail() { - throw new UnsupportedOperationException(); - } - - public boolean isLoggedIn() { - throw new UnsupportedOperationException(); - } - - public boolean isAdmin() { - throw new UnsupportedOperationException(); - } - - public String getAuthDomain() { - throw new UnsupportedOperationException(); - } - - public String getRequestNamespace() { - return ""; - } - - public Map getAttributes() { - Map map = new HashMap(); - map.put("com.google.appengine.server_url_key", "http://localhost:8080"); - return map; - } -} \ No newline at end of file diff --git a/grails-datastore-cassandra/build.gradle b/grails-datastore-cassandra/build.gradle deleted file mode 100644 index 09deb5370..000000000 --- a/grails-datastore-cassandra/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ -repositories { - mavenRepo urls:'http://eaio.com/maven2' -} - -dependencies { - compile project(":grails-datastore-core") - compile 'com.eaio.uuid:uuid:3.2' - compile 'me.prettyprint:hector:0.6.0-15' - compile 'org.apache.cassandra:cassandra:0.6.0' - compile 'org.apache.cassandra:cassandra-javautils:1.0.0' - compile 'libthrift:libthrift:917130' - - runtime 'org.perf4j:perf4j:0.9.12' - runtime 'org.cliffc.high_scale_lib:high-scale-lib:1.0.0' - runtime 'com.reardencommerce:clhm-production:1.0.0' - runtime 'commons-collections:commons-collections:3.2' - runtime 'commons-lang:commons-lang:2.4' -} diff --git a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/CassandraDatastore.java b/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/CassandraDatastore.java deleted file mode 100644 index 3823244fc..000000000 --- a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/CassandraDatastore.java +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (C) 2010 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.mapping.cassandra; - -import java.util.Map; - -import me.prettyprint.cassandra.service.CassandraClient; -import me.prettyprint.cassandra.service.CassandraClientPool; -import me.prettyprint.cassandra.service.CassandraClientPoolFactory; - -import org.springframework.dao.DataAccessResourceFailureException; -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.keyvalue.mapping.KeyValueMappingContext; -import org.grails.datastore.mapping.model.MappingContext; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public class CassandraDatastore extends AbstractDatastore { - public static final String DEFAULT_KEYSPACE = "Keyspace1"; - private CassandraClientPool connectionPool; - - public CassandraDatastore(MappingContext mappingContext) { - super(mappingContext); - this.connectionPool = CassandraClientPoolFactory.INSTANCE.get(); - } - - public CassandraDatastore() { - this(new KeyValueMappingContext(DEFAULT_KEYSPACE)); - } - - @Override - protected Session createSession(@SuppressWarnings("hiding") Map connectionDetails) { - final CassandraClient client; - try { - client = connectionPool.borrowClient("localhost", 9160); - return new CassandraSession(this, getMappingContext(), connectionPool, client); - } catch (Exception e) { - throw new DataAccessResourceFailureException("Failed to obtain Cassandra client session: " + e.getMessage(), e); - } - } -} diff --git a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/CassandraSession.java b/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/CassandraSession.java deleted file mode 100644 index 3f3542245..000000000 --- a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/CassandraSession.java +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (C) 2010 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.mapping.cassandra; - -import me.prettyprint.cassandra.service.CassandraClient; -import me.prettyprint.cassandra.service.CassandraClientPool; - -import org.springframework.dao.DataAccessResourceFailureException; -import org.grails.datastore.mapping.cassandra.engine.CassandraEntityPersister; -import org.grails.datastore.mapping.core.AbstractSession; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.transactions.Transaction; -import org.springframework.transaction.TransactionSystemException; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public class CassandraSession extends AbstractSession { - private CassandraClient cassandraClient; - private CassandraClientPool connectionPool; - - public CassandraSession(Datastore ds, MappingContext context, CassandraClientPool connectionPool, - CassandraClient client) { - super(ds, context); - this.connectionPool = connectionPool; - this.cassandraClient = client; - } - - @Override - protected Persister createPersister(Class cls, MappingContext mappingContext) { - PersistentEntity entity = mappingContext.getPersistentEntity(cls.getName()); - if (entity != null) { - return new CassandraEntityPersister(mappingContext, entity, this, cassandraClient); - } - return null; - } - - public boolean isConnected() { - return !cassandraClient.isReleased(); - } - - @Override - public void disconnect() { - try { - connectionPool.releaseClient(cassandraClient); - } - catch (Exception e) { - throw new DataAccessResourceFailureException( - "Failed to release Cassandra client session: " + e.getMessage(), e); - } - finally { - super.disconnect(); - } - } - - @Override - protected Transaction beginTransactionInternal() { - throw new TransactionSystemException("Transactions are not supported by Cassandra"); - } - - public CassandraClient getNativeInterface() { - return cassandraClient; - } -} diff --git a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/engine/CassandraAssociationIndexer.java b/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/engine/CassandraAssociationIndexer.java deleted file mode 100644 index 142c60697..000000000 --- a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/engine/CassandraAssociationIndexer.java +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright (C) 2010 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.mapping.cassandra.engine; - -import static me.prettyprint.cassandra.utils.StringUtils.bytes; -import static me.prettyprint.cassandra.utils.StringUtils.string; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import me.prettyprint.cassandra.service.CassandraClient; -import me.prettyprint.cassandra.service.Keyspace; - -import org.apache.cassandra.thrift.Column; -import org.apache.cassandra.thrift.ColumnParent; -import org.apache.cassandra.thrift.SlicePredicate; -import org.apache.cassandra.thrift.SliceRange; -import org.grails.datastore.mapping.cassandra.util.HectorCallback; -import org.grails.datastore.mapping.cassandra.util.HectorTemplate; -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.reflect.NameUtils; - -/** - * AssociationIndexer for Cassandra one-to-many associations - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("hiding") -public class CassandraAssociationIndexer implements AssociationIndexer { - - private static final byte[] ZERO_LENGTH_BYTE_ARRAY = new byte[0]; - - private CassandraClient cassandraClient; - private Association association; - private String keyspace; - private String columnFamily; - - public CassandraAssociationIndexer(CassandraClient cassandraClient, Association association, String keyspace) { - this.cassandraClient = cassandraClient; - this.association = association; - this.keyspace = keyspace; - this.columnFamily = getDefaultColumnFamilyName(association); - } - - protected String getDefaultColumnFamilyName(Association association) { - return association.getOwner().getName() + NameUtils.capitalize(association.getName()); - } - - public void index(final Serializable primaryKey, final List foreignKeys) { - - HectorTemplate ht = new HectorTemplate(cassandraClient); - ht.execute(keyspace, new HectorCallback(){ - - public Object doInHector(Keyspace keyspace) { - Map> cfmap = new HashMap>(); - final long time = System.currentTimeMillis() * 1000; - - List columns = new ArrayList(); - for (Serializable foreignKey : foreignKeys) { - byte[] keyInBytes = bytes(foreignKey.toString()); - final Column column = new Column(keyInBytes,keyInBytes,time); - columns.add(column); - } - cfmap.put(columnFamily, columns); - keyspace.batchInsert(primaryKey.toString(),cfmap, null); - return null; - } - }); - } - - public void index(Serializable primaryKey, Serializable foreignKey) { - List list = new ArrayList(); list.add(foreignKey); - index(primaryKey, list); - } - - public List query(final Serializable primaryKey) { - HectorTemplate ht = new HectorTemplate(cassandraClient); - return (List) ht.execute(keyspace, new HectorCallback() { - public Object doInHector(Keyspace keyspace) { - SlicePredicate predicate = new SlicePredicate(); - predicate.setSlice_range(new SliceRange(ZERO_LENGTH_BYTE_ARRAY,ZERO_LENGTH_BYTE_ARRAY, false, Integer.MAX_VALUE)); - ColumnParent cp = new ColumnParent(); - cp.setColumn_family(columnFamily); - - final List columns = keyspace.getSlice(primaryKey.toString(), cp, predicate); - if (columns== null || columns.isEmpty()) { - return Collections.emptyList(); - } - - List keys = new ArrayList(); - for (Column column : columns) { - keys.add(string(column.getName())); - } - return keys; - } - }); - } - - public PersistentEntity getIndexedEntity() { - return association.getAssociatedEntity(); - } -} diff --git a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/engine/CassandraEntityPersister.java b/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/engine/CassandraEntityPersister.java deleted file mode 100644 index 4590dc8c3..000000000 --- a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/engine/CassandraEntityPersister.java +++ /dev/null @@ -1,228 +0,0 @@ -/* Copyright (C) 2010 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.mapping.cassandra.engine; - -import static me.prettyprint.cassandra.utils.StringUtils.bytes; -import static me.prettyprint.cassandra.utils.StringUtils.string; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import me.prettyprint.cassandra.model.HectorException; -import me.prettyprint.cassandra.service.CassandraClient; -import me.prettyprint.cassandra.service.Keyspace; - -import org.apache.cassandra.thrift.Column; -import org.apache.cassandra.thrift.ColumnParent; -import org.apache.cassandra.thrift.SlicePredicate; -import org.apache.cassandra.thrift.SliceRange; -import org.apache.cassandra.thrift.SuperColumn; -import org.springframework.dao.DataAccessResourceFailureException; -import org.grails.datastore.mapping.cassandra.CassandraDatastore; -import org.grails.datastore.mapping.cassandra.CassandraSession; -import org.grails.datastore.mapping.cassandra.uuid.UUIDUtil; -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.engine.PropertyValueIndexer; -import org.grails.datastore.mapping.keyvalue.engine.AbstractKeyValueEntityPesister; -import org.grails.datastore.mapping.keyvalue.engine.KeyValueEntry; -import org.grails.datastore.mapping.model.ClassMapping; -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.Association; -import org.grails.datastore.mapping.query.Query; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public class CassandraEntityPersister extends AbstractKeyValueEntityPesister { - - private CassandraClient cassandraClient; - private static final byte[] ZERO_LENGTH_BYTE_ARRAY = new byte[0]; - - public CassandraEntityPersister(MappingContext context, PersistentEntity entity, - CassandraSession conn, CassandraClient cassandraClient) { - super(context, entity, conn); - this.cassandraClient = cassandraClient; - } - - @Override - protected void deleteEntry(String family, Object key) { - // TODO: Implement deletion of entities - } - - @Override - public AssociationIndexer getAssociationIndexer(KeyValueEntry nativeEntry, Association association) { - return new CassandraAssociationIndexer(cassandraClient, association, getKeyspaceName()); - } - - @Override - public PropertyValueIndexer getPropertyIndexer(PersistentProperty property) { - return null; // TODO: Support querying in cassandra - } - - @Override - protected KeyValueEntry createNewEntry(String family) { - return new KeyValueEntry(family); - } - - @Override - protected Object getEntryValue(KeyValueEntry nativeEntry, String property) { - return nativeEntry.get(property); - } - - @Override - protected void setEntryValue(KeyValueEntry nativeEntry, String key, Object value) { - if (value != null) { - nativeEntry.put(key, bytes(value.toString())); - } - } - - @Override - protected KeyValueEntry retrieveEntry(PersistentEntity persistentEntity, String family, Serializable nativeKey) { - final ClassMapping cm = getPersistentEntity().getMapping(); - final String keyspaceName = getKeyspace(cm, CassandraDatastore.DEFAULT_KEYSPACE); - - final Keyspace keyspace; - try { - keyspace = cassandraClient.getKeyspace(keyspaceName); - } - catch (HectorException e) { - throw new DataAccessResourceFailureException( - "Exception occurred invoking Cassandra: " + e.getMessage(), e); - } - - SuperColumn sc = getSuperColumn(keyspace, family, nativeKey); - KeyValueEntry entry = new KeyValueEntry(family); - if (sc != null) { - for (Column column : sc.getColumns()) { - entry.put(string(column.getName()), string(column.getValue())); - } - } - - if (entry.isEmpty()) { - return null; - } - - return entry; - } - - private SuperColumn getSuperColumn(Keyspace keyspace, String family, Serializable id) { - ColumnParent parent = new ColumnParent(); - parent.setColumn_family(family); - - final List result; - try { - SlicePredicate predicate = new SlicePredicate(); - predicate.setSlice_range(new SliceRange(ZERO_LENGTH_BYTE_ARRAY, ZERO_LENGTH_BYTE_ARRAY, false, 1)); - result = keyspace.getSuperSlice(id.toString(), parent, predicate); - } - catch (HectorException e) { - throw new DataAccessResourceFailureException("Exception occurred invoking Cassandra: " + e.getMessage(), e); - } - - return !result.isEmpty() ? result.get(0) : null; - } - - @Override - protected void updateEntry(PersistentEntity persistentEntity, Object id, KeyValueEntry entry) { - Keyspace keyspace = getKeyspace(); - final String family = getFamily(persistentEntity, persistentEntity.getMapping()); - SuperColumn sc = getSuperColumn(keyspace, family, (Serializable)id); - if (sc != null) { - updateSuperColumn(sc, entry); - - Map> insertMap = createInsertMap(family, sc); - - performInsertion(keyspace, id.toString(), insertMap, entry); - } - } - - @Override - protected void deleteEntries(String family, List keys) { - } - - @Override - protected Object storeEntry(PersistentEntity persistentEntity, Object storeId, KeyValueEntry nativeEntry) { - UUID uuid = (UUID)storeId; - final Keyspace keyspace = getKeyspace(); - String family = getFamily(persistentEntity, getPersistentEntity().getMapping()); - SuperColumn sc = new SuperColumn(); - sc.setName(UUIDUtil.asByteArray(uuid)); - updateSuperColumn(sc, nativeEntry); - Map> insertMap = createInsertMap(family, sc); - performInsertion(keyspace, uuid.toString(), insertMap, nativeEntry); - return uuid; - } - - @Override - protected Object generateIdentifier(PersistentEntity persistentEntity, KeyValueEntry id) { - return UUIDUtil.getTimeUUID(); - } - - private void performInsertion(Keyspace keyspace, String key, Map> insertMap, - @SuppressWarnings("unused") KeyValueEntry nativeEntry) { - try { - keyspace.batchInsert(key, null, insertMap); - } - catch (HectorException e) { - throw new DataAccessResourceFailureException( - "Exception occurred invoking Cassandra: " + e.getMessage(), e); - } - } - - private Map> createInsertMap(String family, SuperColumn sc) { - Map> insertMap = new HashMap>(); - List superColumns = new ArrayList(); - superColumns.add(sc); - insertMap.put(family, superColumns); - return insertMap; - } - - private void updateSuperColumn(SuperColumn sc, KeyValueEntry nativeEntry) { - final long time = System.currentTimeMillis() * 1000; - for (String prop : nativeEntry.keySet()) { - Column c = new Column(); - c.setName(bytes(prop)); - c.setValue((byte[])nativeEntry.get(prop)); - c.setTimestamp(time); - sc.addToColumns(c); - } - } - - private Keyspace getKeyspace() { - final String keyspaceName = getKeyspaceName(); - try { - return cassandraClient.getKeyspace(keyspaceName); - } - catch (HectorException e) { - throw new DataAccessResourceFailureException( - "Exception occurred invoking Cassandra: " + e.getMessage(), e); - } - } - - private String getKeyspaceName() { - return getKeyspace(getPersistentEntity().getMapping(), CassandraDatastore.DEFAULT_KEYSPACE); - } - - public Query createQuery() { - return null; // TODO: Implement querying for Cassandra - } -} diff --git a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/util/HectorCallback.java b/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/util/HectorCallback.java deleted file mode 100644 index 89d8c23c2..000000000 --- a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/util/HectorCallback.java +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 2010 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.mapping.cassandra.util; - -import me.prettyprint.cassandra.model.HectorException; -import me.prettyprint.cassandra.service.Keyspace; - -/** - * Wraps interaction with Hector - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface HectorCallback { - Object doInHector(Keyspace keyspace) throws HectorException; -} diff --git a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/util/HectorTemplate.java b/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/util/HectorTemplate.java deleted file mode 100644 index 1fc6c7346..000000000 --- a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/util/HectorTemplate.java +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (C) 2010 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.mapping.cassandra.util; - -import me.prettyprint.cassandra.model.HectorException; -import me.prettyprint.cassandra.service.CassandraClient; -import me.prettyprint.cassandra.service.Keyspace; - -import org.springframework.dao.DataAccessException; -import org.springframework.dao.DataAccessResourceFailureException; - -/** - * A Spring style template that wraps Cassandra data access exceptions and - * rethrows to Spring's standard exception hierarchy - * - * @author Graeme Rocher - * @since 1.0 - */ -public class HectorTemplate { - - CassandraClient cassandraClient; - - public HectorTemplate(CassandraClient cassandraClient) { - this.cassandraClient = cassandraClient; - } - - public Object execute(String keyspace, HectorCallback callable) throws DataAccessException { - final Keyspace ks; - try { - ks = cassandraClient.getKeyspace(keyspace); - } - catch (HectorException e) { - throw new DataAccessResourceFailureException( - "Exception occurred invoking Cassandra: " + e.getMessage(), e); - } - - try { - return callable.doInHector(ks); - } - catch (HectorException e) { - throw new DataAccessResourceFailureException( - "Exception occurred invoking Cassandra: " + e.getMessage(), e); - } - } -} diff --git a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/uuid/UUIDUtil.java b/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/uuid/UUIDUtil.java deleted file mode 100644 index df1c526cc..000000000 --- a/grails-datastore-cassandra/src/main/java/org/grails/datastore/mapping/cassandra/uuid/UUIDUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (C) 2010 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.mapping.cassandra.uuid; - -import java.nio.ByteBuffer; - -/** - * Utilities for creating Time based UUIDs for Cassandra - * - * Credit: http://blog.matygo.com/post/587641394/time-uuids-with-java-cassandra - * - * @author Graeme Rocher - * @since 1.0 - */ -public class UUIDUtil { - - public static java.util.UUID getTimeUUID() { - return java.util.UUID.fromString(new com.eaio.uuid.UUID().toString()); - } - - public static java.util.UUID getRandomUUID() { - return java.util.UUID.randomUUID(); - } - - public static java.util.UUID toUUID(byte[] uuid) { - ByteBuffer buffer = ByteBuffer.allocate(16); - buffer.put(uuid); - buffer.rewind(); - com.eaio.uuid.UUID u = new com.eaio.uuid.UUID(buffer.getLong(), buffer.getLong()); - return java.util.UUID.fromString(u.toString()); - } - - public static byte[] asByteArray(java.util.UUID uuid) { - ByteBuffer buffer = ByteBuffer.allocate(16); - buffer.putLong(uuid.getMostSignificantBits()); - buffer.putLong(uuid.getLeastSignificantBits()); - return buffer.array(); - } -} diff --git a/grails-datastore-cassandra/src/test/groovy/grails/persistence/Entity.java b/grails-datastore-cassandra/src/test/groovy/grails/persistence/Entity.java deleted file mode 100644 index 725fbaf53..000000000 --- a/grails-datastore-cassandra/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-cassandra/src/test/groovy/org/grails/datastore/mapping/cassandra/AbstractCassandraTest.groovy b/grails-datastore-cassandra/src/test/groovy/org/grails/datastore/mapping/cassandra/AbstractCassandraTest.groovy deleted file mode 100644 index b22b1aa75..000000000 --- a/grails-datastore-cassandra/src/test/groovy/org/grails/datastore/mapping/cassandra/AbstractCassandraTest.groovy +++ /dev/null @@ -1,56 +0,0 @@ -package org.grails.datastore.mapping.cassandra - -import org.apache.cassandra.contrib.utils.service.CassandraServiceDataCleaner -import org.apache.cassandra.service.EmbeddedCassandraService -import org.apache.cassandra.thrift.Cassandra -import org.apache.thrift.protocol.TBinaryProtocol -import org.apache.thrift.protocol.TProtocol -import org.apache.thrift.transport.TSocket -import org.apache.thrift.transport.TTransport -import org.apache.thrift.transport.TTransportException -import org.junit.BeforeClass -import org.springframework.core.io.ClassPathResource - -/** - * Test harness for Cassandra tests - * - * @author Graeme Rocher - * @since 1.0 - */ -class AbstractCassandraTest { - - protected static EmbeddedCassandraService cassandra - - @BeforeClass - static void setupCassandra() { - // Tell cassandra where the configuration files are. - // Use the test configuration file. - try { - System.setProperty("storage-config", new ClassPathResource("cassandra-conf").file.absolutePath) - new CassandraServiceDataCleaner().prepare() - cassandra = new EmbeddedCassandraService() - cassandra.init() - Thread t = new Thread(cassandra) - t.setDaemon(true) - t.start() - } - catch (Throwable e) { - e.printStackTrace() - println("Failed to setup Cassandra ${e.message}") - } - } - - /** - * Gets a session to the localhost client - * - * @return - * @throws TTransportException - */ - protected Cassandra.Client getClient() throws TTransportException { - TTransport tr = new TSocket("localhost", 9170) - TProtocol proto = new TBinaryProtocol(tr) - Cassandra.Client client = new Cassandra.Client(proto) - tr.open() - return client - } -} diff --git a/grails-datastore-cassandra/src/test/groovy/org/grails/datastore/mapping/cassandra/CassandraEntityPersisterTest.groovy b/grails-datastore-cassandra/src/test/groovy/org/grails/datastore/mapping/cassandra/CassandraEntityPersisterTest.groovy deleted file mode 100644 index 37c9048ec..000000000 --- a/grails-datastore-cassandra/src/test/groovy/org/grails/datastore/mapping/cassandra/CassandraEntityPersisterTest.groovy +++ /dev/null @@ -1,50 +0,0 @@ -package org.grails.datastore.mapping.cassandra - -import org.junit.Test -import org.grails.datastore.mapping.cassandra.uuid.UUIDUtil -import org.grails.datastore.mapping.core.Session - -/** - * @author Graeme Rocher - * @since 1.1 - */ -class CassandraEntityPersisterTest extends AbstractCassandraTest { - - @Test - void testReadWrite() { - def ds = new CassandraDatastore() - ds.mappingContext.addPersistentEntity(TestEntity) - Session conn = ds.connect(null) - - def t = conn.retrieve(TestEntity, UUIDUtil.getTimeUUID()) - - assert t == null - - t = new TestEntity(name:"Bob", age:45) - - conn.persist(t) - - assert t.id != null - - t = conn.retrieve(TestEntity, t.id) - - assert t != null - assert "Bob" == t.name - assert 45 == t.age - assert t.id != null - - - t.age = 55 - conn.persist(t) - - t = conn.retrieve(TestEntity, t.id) - - assert 55 == t.age - } -} - -class TestEntity { - UUID id - String name - int age -} diff --git a/grails-datastore-cassandra/src/test/groovy/org/grails/datastore/mapping/cassandra/OneTOManyAssociationTests.groovy b/grails-datastore-cassandra/src/test/groovy/org/grails/datastore/mapping/cassandra/OneTOManyAssociationTests.groovy deleted file mode 100644 index eff5d2087..000000000 --- a/grails-datastore-cassandra/src/test/groovy/org/grails/datastore/mapping/cassandra/OneTOManyAssociationTests.groovy +++ /dev/null @@ -1,50 +0,0 @@ -package org.grails.datastore.mapping.cassandra - -import grails.persistence.Entity - -import org.junit.Test -import org.grails.datastore.mapping.core.Session - -/** - * @author Graeme Rocher - * @since 1.1 - */ -class OneToManyAssociationTests extends AbstractCassandraTest { - @Test - void testOneToManyAssociation() { - def ds = new CassandraDatastore() - ds.mappingContext.addPersistentEntity(Author) - Session conn = ds.connect(null) - - def a = new Author(name:"Stephen King") - a.books = [new Book(title:"The Stand"), new Book(title:"It")] as Set - - conn.persist(a) - - a = conn.retrieve(Author, a.id) - - assert a != null - assert "Stephen King" == a.name - assert a.books != null - assert 2 == a.books.size() - - def b1 = a.books.find { it.title == 'The Stand'} - assert b1 != null - assert b1.id != null - assert "The Stand" == b1.title - } -} - -@Entity -class Author { - UUID id - String name - Set books - static hasMany = [books:Book] -} - -@Entity -class Book { - UUID id - String title -} diff --git a/grails-datastore-cassandra/src/test/groovy/org/grails/datastore/mapping/cassandra/OneToOneAssociationTests.groovy b/grails-datastore-cassandra/src/test/groovy/org/grails/datastore/mapping/cassandra/OneToOneAssociationTests.groovy deleted file mode 100644 index 1933b4f0d..000000000 --- a/grails-datastore-cassandra/src/test/groovy/org/grails/datastore/mapping/cassandra/OneToOneAssociationTests.groovy +++ /dev/null @@ -1,46 +0,0 @@ -package org.grails.datastore.mapping.cassandra - -import grails.persistence.Entity - -import org.junit.Test -import org.grails.datastore.mapping.core.Session - -/** - * @author Graeme Rocher - * @since 1.1 - */ -class OneToOneAssociationTests extends AbstractCassandraTest { - - @Test - void testPersistOneToOneAssociation() { - def ds = new CassandraDatastore() - ds.mappingContext.addPersistentEntity(Person) - Session conn = ds.connect() - - def p = new Person(name:"Bob") - p.address = new Address(number:"20", postCode:"39847") - - conn.persist(p) - - p = conn.retrieve(Person, p.id) - - assert p != null - assert "Bob" == p.name - assert p.address != null - assert "20" == p.address.number - } -} - -@Entity -class Person { - UUID id - String name - Address address -} - -@Entity -class Address { - UUID id - String number - String postCode -} diff --git a/grails-datastore-cassandra/src/test/resources/cassandra-conf/log4j.properties b/grails-datastore-cassandra/src/test/resources/cassandra-conf/log4j.properties deleted file mode 100644 index 46ab656e7..000000000 --- a/grails-datastore-cassandra/src/test/resources/cassandra-conf/log4j.properties +++ /dev/null @@ -1,27 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -# for production, you should probably list the root to INFO -# and the pattern to %c instead of %l. (%l is slower.) - -# output messages into a rolling log file as well as stdout -log4j.rootLogger=DEBUG,stdout - -# stdout -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%5p %d{HH:mm:ss,SSS} %m%n - diff --git a/grails-datastore-cassandra/src/test/resources/cassandra-conf/storage-conf.xml b/grails-datastore-cassandra/src/test/resources/cassandra-conf/storage-conf.xml deleted file mode 100644 index 7201705eb..000000000 --- a/grails-datastore-cassandra/src/test/resources/cassandra-conf/storage-conf.xml +++ /dev/null @@ -1,423 +0,0 @@ - - - - - - - - Test Cluster - - - false - - - true - - - - - - - - - - - - - - - - - - - - - - - - - org.apache.cassandra.locator.RackUnawareStrategy - - - 1 - - - org.apache.cassandra.locator.EndPointSnitch - - - - - - org.apache.cassandra.auth.AllowAllAuthenticator - - - org.apache.cassandra.dht.RandomPartitioner - - - - - - build/commitlog - - build/data - - - - - - 127.0.0.1 - - - - - - - 10000 - - - - 128 - - - - - - localhost - - 7000 - - - localhost - - 9160 - - false - - - - - - - - auto - - - 512 - - - 64 - - - 32 - 8 - - - 64 - - - 64 - - 256 - - 0.3 - - 60 - - - 8 - 32 - - - periodic - - 10000 - - - - - 864000 - diff --git a/grails-datastore-core/build.gradle b/grails-datastore-core/build.gradle deleted file mode 100644 index f9575554b..000000000 --- a/grails-datastore-core/build.gradle +++ /dev/null @@ -1,40 +0,0 @@ -dependencies { - compile "com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.3.1" - compile "org.springframework:spring-core:$springVersion" , { - exclude group:'commons-logging',module:'commons-logging' - } - compile "org.springframework:spring-beans:$springVersion", { - exclude group:'org.springframework', module:'spring-core' - exclude group:'commons-logging',module:'commons-logging' - } - compile "org.springframework:spring-tx:$springVersion", { - exclude group:'commons-logging',module:'commons-logging' - 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-aop' - } - compile "org.springframework:spring-context:$springVersion", { - exclude group:'commons-logging',module:'commons-logging' - exclude group:'org.springframework', module:'spring-core' - exclude group:'org.springframework', module:'spring-expression' - exclude group:'org.springframework', module:'spring-aop' - exclude group:'org.springframework', module:'spring-beans' - exclude group:'org.springframework', module:'spring-asm' - } - compile 'org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final' - compile 'org.javassist:javassist:3.17.1-GA' - compile 'javax.transaction:jta:1.1' - - compile "org.slf4j:slf4j-api:$slf4jVersion" - compile "org.slf4j:jcl-over-slf4j:$slf4jVersion" - - // we need the Grails @Entity annotation to test GORM syntax mapping - testCompile("commons-lang:commons-lang:2.4") - testCompile("org.springframework:spring-context:$springVersion") - testCompile("org.springframework:spring-web:$springVersion") - testCompile("org.grails:grails-bootstrap:$grailsVersion") { - exclude module:'gpars' - } - testCompile "org.grails:grails-core:$grailsVersion" -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/annotation/Entity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/annotation/Entity.java deleted file mode 100644 index fe4845771..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/annotation/Entity.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.grails.datastore.mapping.annotation; - -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/annotation/Id.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/annotation/Id.java deleted file mode 100644 index 675aab749..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/annotation/Id.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.grails.datastore.mapping.annotation; - -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.FIELD, ElementType.METHOD}) -public @interface Id { -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/annotation/Index.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/annotation/Index.java deleted file mode 100644 index 60be900d3..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/annotation/Index.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.grails.datastore.mapping.annotation; - -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.FIELD, ElementType.METHOD}) -public @interface Index { - -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapter.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapter.java deleted file mode 100644 index 1d29a49d4..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapter.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.grails.datastore.mapping.cache; - -import org.grails.datastore.mapping.cache.exception.CacheException; - -import java.io.Serializable; - -/** - * Third party cache adapter responsible for handling put and get cache operations - * for concrete third party cache such as infinispan or coherence. - * Each TPCacheAdapter is registered per type of PersistentEntity via {@link TPCacheAdapterRepository}. - *

    - * Current API does not yet provide bulk operations because the rest of the engine is not bulk-optimized. - *

    - * Transactional semantics: depending on the concrete third-party cache capabilities and the presence of JTA transaction - * the implementation might perform the write operations at the commit rather than when a {@link #cacheEntry(java.io.Serializable, Object)} - * is called. - *

    - * Concurrency: each TPCacheAdapter must be thread-safe. - * - * @author Roman Stepanenko - */ -public interface TPCacheAdapter { - /** - * Stores a cached entry in a synchronous manner. - *

    - * Transactional semantics: depending on the concrete third-party cache capabilities and the presence of JTA transaction, - * for network optimization reasons the implementation might perform the actual cache cluster update operations at the commit - * rather than when a {@link #cacheEntry(java.io.Serializable, Object)} is called. - *

    - * In cases when there is no transaction or no transactional support by the implementation, if there are any problems - * storing the entry the caller is notified about it via exception in the calling thread; also, if this method returns - * successfully it means that the logistics of putting the specified value in the cache are fully done. - * @param key the entry key - * @param entry the entry - * @throws CacheException runtime exception indicating any cache-related problems - */ - void cacheEntry(Serializable key, T entry) throws CacheException; - - /** - * Returns the stored value for the specified key. - * @param key the entry key - * @return the entry - * @throws CacheException runtime exception indicating any cache-related problems - */ - T getCachedEntry(Serializable key) throws CacheException; -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapterRepository.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapterRepository.java deleted file mode 100644 index fd7c71d24..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapterRepository.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.grails.datastore.mapping.cache; - -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * A repository of {@link TPCacheAdapter}s. - * - * @author Roman Stepanenko - */ -public interface TPCacheAdapterRepository { - /** - * Returns {@link TPCacheAdapter} for the specified {@link PersistentEntity}. - * @param entity the entity - * @return null if no {@link TPCacheAdapter} is found for the specified entity - */ - TPCacheAdapter getTPCacheAdapter(PersistentEntity entity); - - /** - * Sets {@link TPCacheAdapter} for the specified {@link PersistentEntity}. - * If the specified entity had another cache adapter before, the old one is ignored after this call. - * @param entity the entity - * @param cacheAdapter the adapter - */ - void setTPCacheAdapter(PersistentEntity entity, TPCacheAdapter cacheAdapter); - - /** - * Sets {@link TPCacheAdapter} for the specified java class of {@link PersistentEntity}. - * If the specified entity had another cache adapter before, the old one is ignored after this call. - * @param entityJavaClass equivalent to {@link PersistentEntity#getJavaClass()} - * @param cacheAdapter the adapter - */ - void setTPCacheAdapter(@SuppressWarnings("rawtypes") Class entityJavaClass, TPCacheAdapter cacheAdapter); - - /** - * Sets {@link TPCacheAdapter} for the specified FQN java class of {@link PersistentEntity}. - * If the specified entity had another cache adapter before, the old one is ignored after this call. - * @param entityJavaClassFQN equivalent to {@link PersistentEntity#getJavaClass().getName()} - * @param cacheAdapter the adapter - */ - void setTPCacheAdapter(String entityJavaClassFQN, TPCacheAdapter cacheAdapter); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/exception/CacheException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/exception/CacheException.java deleted file mode 100644 index 5c89a5995..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/exception/CacheException.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.grails.datastore.mapping.cache.exception; - -/** - * Top-level exception used to report problems with third-party cache operations - * @author Roman Stepanenko - */ -public class CacheException extends RuntimeException{ - private static final long serialVersionUID = 1; - - public CacheException() { - } - - public CacheException(String message) { - super(message); - } - - public CacheException(String message, Throwable cause) { - super(message, cause); - } - - public CacheException(Throwable cause) { - super(cause); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/HashMapTPCacheAdapter.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/HashMapTPCacheAdapter.java deleted file mode 100644 index e60012a48..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/HashMapTPCacheAdapter.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.grails.datastore.mapping.cache.impl; - -import org.grails.datastore.mapping.cache.TPCacheAdapter; -import org.grails.datastore.mapping.cache.exception.CacheException; - -import java.io.Serializable; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Simple implementation of {@link org.grails.datastore.mapping.cache.TPCacheAdapter} backed by a local hash map. - * - * @author Roman Stepanenko - */ -public class HashMapTPCacheAdapter implements TPCacheAdapter { - public void cacheEntry(Serializable key, T entry) throws CacheException { - cache.put(key, entry); - } - - public T getCachedEntry(Serializable key) throws CacheException { - return cache.get(key); - } - - private ConcurrentHashMap cache = new ConcurrentHashMap(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/TPCacheAdapterRepositoryImpl.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/TPCacheAdapterRepositoryImpl.java deleted file mode 100644 index 9719366d9..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/TPCacheAdapterRepositoryImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.grails.datastore.mapping.cache.impl; - -import org.grails.datastore.mapping.cache.TPCacheAdapter; -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; -import org.grails.datastore.mapping.model.PersistentEntity; - -import java.util.concurrent.ConcurrentHashMap; - -/** - * Simple implementation of {@link TPCacheAdapterRepository} - * - * @author Roman Stepanenko - */ -public class TPCacheAdapterRepositoryImpl implements TPCacheAdapterRepository { - public TPCacheAdapter getTPCacheAdapter(PersistentEntity entity) { - if (entity == null) { - return null; - } - - return adapters.get(entity.getJavaClass().getName()); - } - - public void setTPCacheAdapter(PersistentEntity entity, TPCacheAdapter cacheAdapter) { - setTPCacheAdapter(entity.getJavaClass(), cacheAdapter); - } - - public void setTPCacheAdapter(@SuppressWarnings("rawtypes") Class entityJavaClass, TPCacheAdapter cacheAdapter) { - setTPCacheAdapter(entityJavaClass.getName(), cacheAdapter); - } - - public void setTPCacheAdapter(String entityJavaClassFQN, TPCacheAdapter cacheAdapter) { - adapters.put(entityJavaClassFQN, cacheAdapter); - } - - private ConcurrentHashMap> adapters = new ConcurrentHashMap>(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/AbstractPersistentCollection.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/AbstractPersistentCollection.java deleted file mode 100644 index 7ed7a80b0..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/AbstractPersistentCollection.java +++ /dev/null @@ -1,247 +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.mapping.collection; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.dirty.checking.DirtyCheckable; -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Abstract base class for persistent collections. - * - * @author Burt Beckwith - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class AbstractPersistentCollection implements PersistentCollection { - - private boolean initialized; - private Serializable associationKey; - private Session session; - private AssociationIndexer indexer; - private Collection keys; - private Class childType; - private boolean dirty = false; - - protected final Collection collection; - - protected AbstractPersistentCollection(Class childType, Session session, Collection collection) { - this.childType = childType; - this.collection = collection; - this.session = session; - } - - protected AbstractPersistentCollection(Collection keys, Class childType, - Session session, Collection collection) { - this.session = session; - this.keys = keys; - this.childType = childType; - this.collection = collection; - } - - protected AbstractPersistentCollection(Serializable associationKey, Session session, - AssociationIndexer indexer, Collection collection) { - this.session = session; - this.associationKey = associationKey; - this.indexer = indexer; - this.collection = collection; - } - - /* Collection methods */ - - public Iterator iterator() { - initialize(); - - final Iterator iterator = collection.iterator(); - return new Iterator() { - public boolean hasNext() { - return iterator.hasNext(); - } - - public Object next() { - return iterator.next(); - } - - public void remove() { - iterator.remove(); - markDirty(); - } - }; - } - - public int size() { - initialize(); - return collection.size(); - } - - public boolean isEmpty() { - initialize(); - return collection.isEmpty(); - } - - public boolean contains(Object o) { - initialize(); - return collection.contains(o); - } - - public boolean add(Object o) { - initialize(); - boolean added = collection.add(o); - if (added) { - markDirty(); - } - return added; - } - - public boolean remove(Object o) { - initialize(); - boolean remove = collection.remove(o); - if (remove) { - markDirty(); - } - return remove; - } - - public void clear() { - initialize(); - collection.clear(); - markDirty(); - } - - @Override - public boolean equals(Object o) { - initialize(); - return collection.equals(o); - } - - @Override - public int hashCode() { - initialize(); - return collection.hashCode(); - } - - @Override - public String toString() { - initialize(); - return collection.toString(); - } - - public boolean removeAll(Collection c) { - initialize(); - boolean changed = collection.removeAll(c); - if (changed) { - markDirty(); - } - return changed; - } - - public Object[] toArray() { - initialize(); - return collection.toArray(); - } - - public Object[] toArray(Object[] a) { - initialize(); - return collection.toArray(a); - } - - public boolean containsAll(Collection c) { - initialize(); - return collection.containsAll(c); - } - - public boolean addAll(Collection c) { - initialize(); - boolean changed = collection.addAll(c); - if (changed) { - markDirty(); - } - return changed; - } - - public boolean retainAll(Collection c) { - initialize(); - boolean changed = collection.retainAll(c); - if (changed) { - markDirty(); - } - return changed; - } - - /* PersistentCollection methods */ - - public boolean isInitialized() { - return initialized; - } - - public void initialize() { - if (initialized) { - return; - } - - initialized = true; - - if (associationKey == null) { - if (keys != null) { - addAll(session.retrieveAll(childType, keys)); - } - } - else { - List results = indexer.query(associationKey); - PersistentEntity entity = indexer.getIndexedEntity(); - - // This should really only happen for unit testing since entities are - // mocked selectively and may not always be registered in the indexer. In this - // case, there can't be any results to be added to the collection. - if( entity != null ) { - addAll(session.retrieveAll(entity.getJavaClass(), results)); - } - } - } - - public boolean isDirty() { - return dirty || checkCollectionElements(); - } - - protected boolean checkCollectionElements() { - if(isInitialized()) { - for(Object o : collection) { - if( o instanceof DirtyCheckable) { - DirtyCheckable dirtyCheckable = (DirtyCheckable) o; - if(dirtyCheckable.hasChanged()) { - this.dirty = true; - return true; - } - } - } - } - return false; - } - - public void resetDirty() { - dirty = false; - } - - /* misc methods */ - - public void markDirty() { - dirty = true; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentCollection.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentCollection.java deleted file mode 100644 index e72599632..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentCollection.java +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 2010 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.mapping.collection; - -import java.util.Collection; - -/** - * A lazy loaded collection. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public interface PersistentCollection extends Collection { - - /** - * Check whether the collection has been loaded. - * @return true if the collection has been initialized - */ - boolean isInitialized(); - - /** - * Initializes the collection if it hasn't already been initialized. - */ - void initialize(); - - /** - * Check whether the collection has been modified. - * @return true if the collection is initialized and has been changed since initialization - */ - boolean isDirty(); - - /** - * Mark the collection as no longer dirty. - */ - void resetDirty(); - - /** - * Mark the collection as dirty. - */ - void markDirty(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentList.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentList.java deleted file mode 100644 index 947e157bd..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentList.java +++ /dev/null @@ -1,163 +0,0 @@ -/* Copyright (C) 2010 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.mapping.collection; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.ListIterator; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.AssociationIndexer; - -/** - * A lazy loaded list. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class PersistentList extends AbstractPersistentCollection implements List { - - private final List list; - - public PersistentList(Class childType, Session session, List collection) { - super(childType, session, collection); - this.list = collection; - } - - public PersistentList(Collection keys, Class childType, Session session) { - super(keys, childType, session, new ArrayList()); - list = (List)collection; - } - - public PersistentList(Serializable associationKey, Session session, AssociationIndexer indexer) { - super(associationKey, session, indexer, new ArrayList()); - list = (List)collection; - } - - public int indexOf(Object o) { - initialize(); - return list.indexOf(o); - } - - public int lastIndexOf(Object o) { - initialize(); - return list.lastIndexOf(o); - } - - public Object get(int index) { - initialize(); - return list.get(index); - } - - public Object set(int index, Object element) { - initialize(); - Object replaced = list.set(index, element); - if (replaced != element) { - markDirty(); - } - return replaced; - } - - public void add(int index, Object element) { - initialize(); - list.add(index, element); - markDirty(); - } - - public Object remove(int index) { - initialize(); - int size = size(); - Object removed = list.remove(index); - if (size != size()) { - markDirty(); - } - return removed; - } - - public boolean addAll(int index, Collection c) { - initialize(); - boolean changed = list.addAll(index, c); - if (changed) { - markDirty(); - } - return changed; - } - - public ListIterator listIterator() { - initialize(); - return new PersistentListIterator(list.listIterator()); - } - - public ListIterator listIterator(int index) { - initialize(); - return new PersistentListIterator(list.listIterator(index)); - } - - public List subList(int fromIndex, int toIndex) { - initialize(); - return list.subList(fromIndex, toIndex); // not modification-aware - } - - private class PersistentListIterator implements ListIterator { - - private final ListIterator iterator; - - private PersistentListIterator(ListIterator iterator) { - this.iterator = iterator; - } - - public boolean hasNext() { - return iterator.hasNext(); - } - - public Object next() { - return iterator.next(); - } - - public boolean hasPrevious() { - return iterator.hasPrevious(); - } - - public Object previous() { - return iterator.previous(); - } - - public int nextIndex() { - return iterator.nextIndex(); - } - - public int previousIndex() { - return iterator.previousIndex(); - } - - public void remove() { - iterator.remove(); - markDirty(); - } - - public void set(Object e) { - iterator.set(e); - markDirty(); // assume changed - } - - public void add(Object e) { - iterator.add(e); - markDirty(); - } - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSet.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSet.java deleted file mode 100644 index d04c654e3..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSet.java +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2010 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.mapping.collection; - -import java.io.Serializable; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.AssociationIndexer; - -/** - * A lazy loaded set. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class PersistentSet extends AbstractPersistentCollection implements Set { - - public PersistentSet(Class childType, Session session, Collection collection) { - super(childType, session, collection); - } - - public PersistentSet(Collection keys, Class childType, Session session) { - super(keys, childType, session, new HashSet()); - } - - public PersistentSet(Serializable associationKey, Session session, AssociationIndexer indexer) { - super(associationKey, session, indexer, new HashSet()); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSortedSet.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSortedSet.java deleted file mode 100644 index 94c4a09b1..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSortedSet.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.grails.datastore.mapping.collection; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.AssociationIndexer; - -import java.io.Serializable; -import java.util.*; - -/** - * A lazy loaded sorted set. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({ "rawtypes", "unchecked" }) -public class PersistentSortedSet extends AbstractPersistentCollection implements SortedSet { - - public PersistentSortedSet(Class childType, Session session, SortedSet collection) { - super(childType, session, collection); - } - - public PersistentSortedSet(Collection keys, Class childType, Session session) { - super(keys, childType, session, new TreeSet()); - } - - public PersistentSortedSet(Serializable associationKey, Session session, AssociationIndexer indexer) { - super(associationKey, session, indexer, new TreeSet()); - } - - public Comparator comparator() { - return getSortedSet().comparator(); - } - - private SortedSet getSortedSet() { - initialize(); - return ((SortedSet)collection); - } - - public SortedSet subSet(Object o, Object o1) { - return getSortedSet().subSet(o,o1); - } - - public SortedSet headSet(Object o) { - return getSortedSet().headSet(o); - } - - public SortedSet tailSet(Object o) { - return getSortedSet().tailSet(o); - } - - public Object first() { - return getSortedSet().first(); - } - - public Object last() { - return getSortedSet().last(); - } -} - diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/column/ColumnDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/column/ColumnDatastore.java deleted file mode 100644 index 05ea1b797..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/column/ColumnDatastore.java +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (C) 2010 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.mapping.column; - -import org.grails.datastore.mapping.core.Datastore; - -/** - * @author Guillaume Laforge - */ -public interface ColumnDatastore extends Datastore {} \ No newline at end of file diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/AbstractGormMappingFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/AbstractGormMappingFactory.java deleted file mode 100644 index 3eec5cdbd..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/AbstractGormMappingFactory.java +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright (C) 2010 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.mapping.config; - -import groovy.lang.Closure; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.grails.datastore.mapping.config.groovy.MappingConfigurationBuilder; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.IdentityMapping; -import org.grails.datastore.mapping.model.MappingFactory; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.springframework.beans.BeanUtils; - -/** - * Abstract GORM implementation that uses the GORM MappingConfigurationBuilder to configure entity mappings. - * - * @author Graeme Rocher - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class AbstractGormMappingFactory extends MappingFactory { - - protected Map> entityToPropertyMap = new HashMap>(); - private Closure defaultMapping; - - @Override - public R createMappedForm(PersistentEntity entity) { - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass()); - R family = BeanUtils.instantiate(getEntityMappedFormType()); - MappingConfigurationBuilder builder = new MappingConfigurationBuilder(family, getPropertyMappedFormType()); - - if (defaultMapping != null) { - builder.evaluate(defaultMapping); - } - List values = cpf.getStaticPropertyValuesFromInheritanceHierarchy(GormProperties.MAPPING, Closure.class); - for (int i = values.size(); i > 0; i--) { - Closure value = values.get(i - 1); - builder.evaluate(value); - } - values = cpf.getStaticPropertyValuesFromInheritanceHierarchy(GormProperties.CONSTRAINTS, Closure.class); - for (int i = values.size(); i > 0; i--) { - Closure value = values.get(i - 1); - builder.evaluate(value); - } - entityToPropertyMap.put(entity, builder.getProperties()); - return family; - } - - public void setDefaultMapping(Closure defaultMapping) { - this.defaultMapping = defaultMapping; - } - - protected abstract Class getPropertyMappedFormType(); - - protected abstract Class getEntityMappedFormType(); - - @Override - public IdentityMapping createIdentityMapping(ClassMapping classMapping) { - Map props = entityToPropertyMap.get(classMapping.getEntity()); - if (props != null) { - T property = props.get(IDENTITY_PROPERTY); - IdentityMapping customIdentityMapping = getIdentityMappedForm(classMapping,property); - if (customIdentityMapping != null) { - return customIdentityMapping; - } - } - return super.createIdentityMapping(classMapping); - } - - protected IdentityMapping getIdentityMappedForm(ClassMapping classMapping, T property) { - return null; - } - - @Override - public T createMappedForm(PersistentProperty mpp) { - Map properties = entityToPropertyMap.get(mpp.getOwner()); - if (properties != null && properties.containsKey(mpp.getName())) { - return properties.get(mpp.getName()); - } - else if (properties != null) { - Property property = properties.get(IDENTITY_PROPERTY); - if (property != null && mpp.getName().equals(property.getName())) { - return (T) property; - } - } - - T defaultMapping = properties != null ? properties.get("*") : null; - if (defaultMapping != null) { - try { - return (T) defaultMapping.clone(); - } catch (CloneNotSupportedException e) { - return BeanUtils.instantiate(getPropertyMappedFormType()); - } - } - else { - return BeanUtils.instantiate(getPropertyMappedFormType()); - } - } -} 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 deleted file mode 100644 index ce70c1669..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Entity.java +++ /dev/null @@ -1,49 +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.grails.datastore.mapping.config; - -/** - * Base class for classes returned from {@link org.grails.datastore.mapping.model.ClassMapping#getMappedForm()} - * - * @author Graeme Rocher - * @since 1.1.9 - */ -public class Entity { - - private boolean stateless = false; - private boolean autoTimestamp = true; - - /** - * @return Whether automatic time stamps should be applied to 'lastUpdate' and 'dateCreated' properties - */ - public boolean isAutoTimestamp() { - return autoTimestamp; - } - - public void setAutoTimestamp(boolean autoTimestamp) { - this.autoTimestamp = autoTimestamp; - } - - /** - * @return Whether the entity state should be held in the session or not - */ - public boolean isStateless() { - return stateless; - } - - public void setStateless(boolean stateless) { - this.stateless = stateless; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Property.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Property.java deleted file mode 100644 index f55fd6792..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Property.java +++ /dev/null @@ -1,109 +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.mapping.config; - -import javax.persistence.FetchType; - -/** - * Base class for classes returned from {@link org.grails.datastore.mapping.model.PropertyMapping#getMappedForm()} - * - * @author Graeme Rocher - * @since 1.0 - */ -public class Property implements Cloneable{ - - private boolean index = false; - private boolean nullable = false; - private FetchType fetchStrategy = FetchType.LAZY; - private String targetName; - private String generator; - private String propertyName; - - @Override - public Property clone() throws CloneNotSupportedException { - return (Property) super.clone(); - } - - /** - * The target to map to, could be a database column, document attribute, or hash key - * - * @return The target name - */ - public String getTargetName() { - return targetName; - } - - public void setTargetName(String targetName) { - this.targetName = targetName; - } - - /* - * @return The name of the property this property mapping relates to - */ - public String getName() { - return propertyName; - } - - public void setName(String propertyName) { - this.propertyName = propertyName; - } - - /** - * @return Whether this property is index - */ - public boolean isIndex() { - return index; - } - - /** - * Whether this property is index - * @param index Sets whether to index the property or not - */ - public void setIndex(boolean index) { - this.index = index; - } - - public FetchType getFetchStrategy() { - return fetchStrategy; - } - - public void setFetchStrategy(FetchType fetchStrategy) { - this.fetchStrategy = fetchStrategy; - } - - public boolean isNullable() { - return nullable; - } - - public void setNullable(boolean nullable) { - this.nullable = nullable; - } - - /** - * Set the id generator name or class. - * @param generator name or class - */ - public void setGenerator(String generator) { - this.generator = generator; - } - - /** - * Get the id generator. - * @return the name or class - */ - public String getGenerator() { - return generator; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/groovy/MappingConfigurationBuilder.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/groovy/MappingConfigurationBuilder.groovy deleted file mode 100644 index 0309e321e..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/groovy/MappingConfigurationBuilder.groovy +++ /dev/null @@ -1,85 +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.mapping.config.groovy - -import org.grails.datastore.mapping.reflect.NameUtils -import org.springframework.beans.MutablePropertyValues -import org.springframework.validation.DataBinder - -/** - * @author Graeme Rocher - * @since 1.0 - */ -class MappingConfigurationBuilder { - - public static final String VERSION_KEY = 'VERSION_KEY' - - Object target - Map properties = [:] - Class propertyClass - - MappingConfigurationBuilder(target, Class propertyClass) { - this.target = target - this.propertyClass = propertyClass - propertyClass.metaClass.propertyMissing = { String name, val -> } - } - - def invokeMethod(String name, args) { - if (args.size() == 0) { - return - } - - if ('version'.equals(name) && args.length == 1 && args[0] instanceof Boolean) { - properties[VERSION_KEY] = args[0] - return - } - - def setterName = NameUtils.getSetterName(name) - if (target.respondsTo(setterName)) { - target[name] = args.size() == 1 ? args[0] : args - } - else { - if (args[0] instanceof Map) { - - def instance - if (properties['*']) { - instance = properties['*'].clone() - } - else { - instance = properties[name] ?: propertyClass.newInstance() - } - - def binder = new DataBinder(instance) - binder.bind(new MutablePropertyValues(args[0])) - properties[name] = instance - } - } - } - - void evaluate(Closure callable) { - if (!callable) { - return - } - - def originalDelegate = callable.delegate - try { - callable.delegate = this - callable.resolveStrategy = Closure.DELEGATE_FIRST - callable.call() - } finally { - callable.delegate = originalDelegate - } - } -} 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.java deleted file mode 100644 index 20d6bee54..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/ConfigUtils.java +++ /dev/null @@ -1,33 +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.mapping.config.utils; - -import java.util.Map; - -import org.grails.datastore.mapping.model.types.conversion.DefaultConversionService; -import org.springframework.core.convert.ConversionService; - -/** - * Used to ease reading of configuration. - */ -public class ConfigUtils { - - private static ConversionService conversionService = new DefaultConversionService(); - - public static T read(Class type, String key, Map config, T defaultValue) { - String value = config.get(key); - return value == null ? defaultValue : conversionService.convert(value, type); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractAttributeStoringSession.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractAttributeStoringSession.java deleted file mode 100644 index 7ff14d2b2..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractAttributeStoringSession.java +++ /dev/null @@ -1,131 +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.mapping.core; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.grails.datastore.mapping.transactions.SessionHolder; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -public abstract class AbstractAttributeStoringSession implements Session { - - protected Map> attributes = new ConcurrentHashMap>(); - protected Map sessionPropertyMap = new ConcurrentHashMap(); - private boolean connected = true; - - public void setAttribute(Object entity, String attributeName, Object value) { - if (entity == null) { - return; - } - - int id = System.identityHashCode(entity); - Map attrs = attributes.get(id); - if (attrs == null) { - attrs = new ConcurrentHashMap(); - attributes.put(id, attrs); - } - - if (attributeName != null && value != null) { - attrs.put(attributeName, value); - } - if (attributeName != null && value == null) { - attrs.remove(attributeName); - } - } - - public Object getAttribute(Object entity, String attributeName) { - if (entity == null) { - return null; - } - - final Map attrs = attributes.get(System.identityHashCode(entity)); - if (attrs == null || attributeName == null) { - return null; - } - - return attrs.get(attributeName); - } - - protected void removeAttributesForEntity(Object entity) { - if (entity == null) { - return; - } - attributes.remove(System.identityHashCode(entity)); - } - - /** - * Set a property on this session. Note that properties are not cleared out when a session is cleared. - * - * @param property The property name. - * @param value The property value. - */ - @Override - public Object setSessionProperty(String property, Object value) { - return sessionPropertyMap.put(property, value); - } - - /** - * Get the value of a property of the session. - * - * @param property The name of the property. - * @return The value. - */ - @Override - public Object getSessionProperty(String property) { - return sessionPropertyMap.get(property); - } - - /** - * Clear a property in a session. - * - * @param property The property name. - * @return The property value, if there was one (or null). - */ - @Override - public Object clearSessionProperty(String property) { - return sessionPropertyMap.remove(property); - } - - /** - * Performs clear up. Subclasses should always call into this super - * implementation. - */ - public void disconnect() { - connected = false; - try { - clear(); - attributes.clear(); - } - finally { - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(getDatastore()); - if (sessionHolder != null) { - sessionHolder.removeSession(this); - if (sessionHolder.isEmpty()) { - try { - TransactionSynchronizationManager.unbindResource(getDatastore()); - } catch (IllegalStateException e) { - // ignore session disconnected by a another thread - } - } - } - } - } - - public boolean isConnected() { - return connected; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractDatastore.java deleted file mode 100644 index a8b5b3372..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractDatastore.java +++ /dev/null @@ -1,236 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -import java.util.Collections; -import java.util.Map; - -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.convert.converter.ConverterRegistry; -import org.grails.datastore.mapping.config.Property; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.PropertyMapping; -import org.grails.datastore.mapping.model.types.BasicTypeConverterRegistrar; -import org.grails.datastore.mapping.transactions.SessionHolder; -import org.grails.datastore.mapping.validation.ValidatingEventListener; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.util.Assert; -import org.springframework.validation.Errors; - -/** - * Abstract Datastore implementation that deals with binding the Session to thread locale upon creation. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class AbstractDatastore implements Datastore, StatelessDatastore, DisposableBean { - - private ApplicationContext applicationContext; - - private static final SoftThreadLocalMap ERRORS_MAP = new SoftThreadLocalMap(); - private static final SoftThreadLocalMap VALIDATE_MAP = new SoftThreadLocalMap(); - - protected MappingContext mappingContext; - protected Map connectionDetails = Collections.emptyMap(); - protected TPCacheAdapterRepository cacheAdapterRepository; - - public AbstractDatastore() {} - - public AbstractDatastore(MappingContext mappingContext) { - this(mappingContext, null, null); - } - - public AbstractDatastore(MappingContext mappingContext, Map connectionDetails, - ConfigurableApplicationContext ctx) { - this(mappingContext, connectionDetails, ctx, null); - } - - public AbstractDatastore(MappingContext mappingContext, Map connectionDetails, - ConfigurableApplicationContext ctx, TPCacheAdapterRepository cacheAdapterRepository) { - this.mappingContext = mappingContext; - this.connectionDetails = connectionDetails != null ? connectionDetails : Collections.emptyMap(); - setApplicationContext(ctx); - this.cacheAdapterRepository = cacheAdapterRepository; - } - - public void destroy() throws Exception { - ERRORS_MAP.remove(); - VALIDATE_MAP.remove(); - } - - public void setApplicationContext(ApplicationContext ctx) { - applicationContext = ctx; - if (ctx != null && registerValidationListener()) { - Assert.isInstanceOf(ConfigurableApplicationContext.class, applicationContext, - "ApplicationContext must be an instanceof ConfigurableApplicationContext"); - ((ConfigurableApplicationContext)ctx).addApplicationListener(new ValidatingEventListener(this)); - } - } - - protected boolean registerValidationListener() { - return true; - } - - public void setConnectionDetails(Map connectionDetails) { - this.connectionDetails = connectionDetails; - } - - public Session connect() { - return connect(connectionDetails); - } - - public final Session connect(Map connDetails) { - Session session = createSession(connDetails); - publishSessionCreationEvent(session); - return session; - } - - private void publishSessionCreationEvent(Session session) { - ApplicationEventPublisher applicationEventPublisher = getApplicationEventPublisher(); - if(applicationEventPublisher != null) { - applicationEventPublisher.publishEvent(new SessionCreationEvent(session)); - } - } - - @Override - public Session connectStateless() { - Session session = createStatelessSession(connectionDetails); - publishSessionCreationEvent(session); - return session; - } - - - /** - * Creates the native session - * - * @param connectionDetails The session details - * @return The session object - */ - protected abstract Session createSession(Map connectionDetails); - - /** - * Creates the native stateless session - * - * @param connectionDetails The session details - * @return The session object - */ - protected Session createStatelessSession(Map connectionDetails) { - return createSession(connectionDetails); - } - - - public Session getCurrentSession() throws ConnectionNotFoundException { - return DatastoreUtils.doGetSession(this, false); - } - - public boolean hasCurrentSession() { - return TransactionSynchronizationManager.hasResource(this); - } - - /** - * Static way to retrieve the session - * @return The session instance - * @throws ConnectionNotFoundException If no session has been created - */ - public static Session retrieveSession() throws ConnectionNotFoundException { - return retrieveSession(Datastore.class); - } - - /** - * Static way to retrieve the session - * @param datastoreClass The type of datastore - * @return The session instance - * @throws ConnectionNotFoundException If no session has been created - */ - public static Session retrieveSession(Class datastoreClass) throws ConnectionNotFoundException { - final Map resourceMap = TransactionSynchronizationManager.getResourceMap(); - Session session = null; - - if (resourceMap != null && !resourceMap.isEmpty()) { - for (Object key : resourceMap.keySet()) { - if (datastoreClass.isInstance(key)) { - SessionHolder sessionHolder = (SessionHolder) resourceMap.get(key); - if (sessionHolder != null) { - session = sessionHolder.getSession(); - } - } - } - } - - if (session == null) { - throw new ConnectionNotFoundException("No datastore session found. Call Datastore.connect(..) before calling Datastore.getCurrentSession()"); - } - return session; - } - - public MappingContext getMappingContext() { - return mappingContext; - } - - public ConfigurableApplicationContext getApplicationContext() { - return (ConfigurableApplicationContext)applicationContext; - } - - public ApplicationEventPublisher getApplicationEventPublisher() { - return getApplicationContext(); - } - - public Errors getObjectErrors(final Object o) { - return getValidationErrorsMap().get(System.identityHashCode(o)); - } - - public void setObjectErrors(Object object, Errors errors) { - getValidationErrorsMap().put(System.identityHashCode(object), errors); - } - - public void setSkipValidation(final Object o, final boolean skip) { - VALIDATE_MAP.get().put(System.identityHashCode(o), skip); - } - - public boolean skipValidation(final Object o) { - final Object skipValidation = VALIDATE_MAP.get().get(System.identityHashCode(o)); - return skipValidation instanceof Boolean && (Boolean) skipValidation; - } - - public static Map getValidationErrorsMap() { - return ERRORS_MAP.get(); - } - - public static Map getValidationSkipMap() { - return VALIDATE_MAP.get(); - } - - protected void initializeConverters(MappingContext mappingContext) { - final ConverterRegistry conversionService = mappingContext.getConverterRegistry(); - BasicTypeConverterRegistrar registrar = new BasicTypeConverterRegistrar(); - registrar.register(conversionService); - } - - protected boolean isIndexed(PersistentProperty property) { - PropertyMapping pm = property.getMapping(); - final Property keyValue = pm.getMappedForm(); - return keyValue != null && keyValue.isIndex(); - } - - public boolean isSchemaless() { - return false; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractSession.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractSession.java deleted file mode 100644 index 79b05195a..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractSession.java +++ /dev/null @@ -1,839 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -import java.io.Serializable; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - -import javax.persistence.FlushModeType; - -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; -import org.grails.datastore.mapping.collection.PersistentCollection; -import org.grails.datastore.mapping.config.Entity; -import org.grails.datastore.mapping.core.impl.PendingInsert; -import org.grails.datastore.mapping.core.impl.PendingOperation; -import org.grails.datastore.mapping.core.impl.PendingOperationExecution; -import org.grails.datastore.mapping.core.impl.PendingUpdate; -import org.grails.datastore.mapping.dirty.checking.DirtyCheckable; -import org.grails.datastore.mapping.dirty.checking.DirtyCheckingSupport; -import org.grails.datastore.mapping.engine.EntityPersister; -import org.grails.datastore.mapping.engine.NativeEntryEntityPersister; -import org.grails.datastore.mapping.engine.NonPersistentTypeException; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.grails.datastore.mapping.transactions.Transaction; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.dao.InvalidDataAccessResourceUsageException; -import org.springframework.transaction.NoTransactionException; -import org.springframework.util.Assert; - -import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap.Builder; -import com.googlecode.concurrentlinkedhashmap.EvictionListener; - -/** - * Abstract implementation of the {@link org.grails.datastore.mapping.core.Session} interface that uses - * a list of {@link org.grails.datastore.mapping.engine.Persister} instances - * to save, update and delete instances - * - * @author Graeme Rocher - * @since 1.0 - * @param - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class AbstractSession extends AbstractAttributeStoringSession implements SessionImplementor { - - private static final EvictionListener> EXCEPTION_THROWING_INSERT_LISTENER = - new EvictionListener>() { - public void onEviction(PersistentEntity key, Collection value) { - throw new DataAccessResourceFailureException("Maximum number (5000) of insert operations to flush() exceeded. Flush the session periodically to avoid this error for batch operations."); - } - }; - - private static final EvictionListener> EXCEPTION_THROWING_UPDATE_LISTENER = - new EvictionListener>() { - public void onEviction(PersistentEntity key, Collection value) { - throw new DataAccessResourceFailureException("Maximum number (5000) of update operations to flush() exceeded. Flush the session periodically to avoid this error for batch operations."); - } - }; - - protected Map persisters = new ConcurrentHashMap(); - private MappingContext mappingContext; - protected ConcurrentLinkedQueue lockedObjects = new ConcurrentLinkedQueue(); - private Transaction transaction; - private Datastore datastore; - private FlushModeType flushMode = FlushModeType.AUTO; - protected Map> firstLevelCache = new ConcurrentHashMap>(); - protected Map> firstLevelEntryCache = new ConcurrentHashMap>(); - protected Map> firstLevelEntryCacheDirtyCheck = new ConcurrentHashMap>(); - protected Map firstLevelCollectionCache = new ConcurrentHashMap(); - - protected TPCacheAdapterRepository cacheAdapterRepository; - - private Map> pendingInserts = - new Builder>() - .listener(EXCEPTION_THROWING_INSERT_LISTENER) - .maximumWeightedCapacity(5000).build(); - - private Map> pendingUpdates = - new Builder>() - .listener(EXCEPTION_THROWING_UPDATE_LISTENER) - .maximumWeightedCapacity(5000).build(); - - protected Collection pendingDeletes = new ConcurrentLinkedQueue(); - protected Collection postFlushOperations = new ConcurrentLinkedQueue(); - private boolean exceptionOccurred; - protected ApplicationEventPublisher publisher; - - protected boolean stateless = false; - - public AbstractSession(Datastore datastore, MappingContext mappingContext, - ApplicationEventPublisher publisher) { - this(datastore, mappingContext, publisher, false); - } - - public AbstractSession(Datastore datastore, MappingContext mappingContext, - ApplicationEventPublisher publisher, boolean stateless) { - this.mappingContext = mappingContext; - this.datastore = datastore; - this.publisher = publisher; - this.stateless = stateless; - } - - public AbstractSession(Datastore datastore, MappingContext mappingContext, - ApplicationEventPublisher publisher, TPCacheAdapterRepository cacheAdapterRepository) { - this(datastore, mappingContext, publisher, false); - this.cacheAdapterRepository = cacheAdapterRepository; - } - - public AbstractSession(Datastore datastore, MappingContext mappingContext, - ApplicationEventPublisher publisher, TPCacheAdapterRepository cacheAdapterRepository, boolean stateless) { - this(datastore, mappingContext, publisher, stateless); - this.cacheAdapterRepository = cacheAdapterRepository; - } - - @Override - public boolean isStateless() { - return this.stateless; - } - - public void addPostFlushOperation(Runnable runnable) { - if (runnable != null && !postFlushOperations.contains(runnable)) { - postFlushOperations.add(runnable); - } - } - - public void addPendingInsert(PendingInsert insert) { - - Collection inserts = pendingInserts.get(insert.getEntity()); - if (inserts == null) { - inserts = new ConcurrentLinkedQueue(); - pendingInserts.put(insert.getEntity(), inserts); - } - - inserts.add(insert); - } - - public void addPendingUpdate(PendingUpdate update) { - Collection inserts = pendingUpdates.get(update.getEntity()); - if (inserts == null) { - inserts = new ConcurrentLinkedQueue(); - pendingUpdates.put(update.getEntity(), inserts); - } - - inserts.add(update); - } - - public Object getCachedEntry(PersistentEntity entity, Serializable key) { - if(isStateless(entity)) return null; - return getCachedEntry(entity, key, false); - } - - public Object getCachedEntry(PersistentEntity entity, Serializable key, boolean forDirtyCheck) { - if(isStateless(entity)) return null; - if (key == null) { - return null; - } - - return getEntryCache(entity.getJavaClass(), forDirtyCheck).get(key); - } - - public void cacheEntry(PersistentEntity entity, Serializable key, Object entry) { - if(isStateless(entity)) return; - if (key == null || entry == null) { - return; - } - - cacheEntry(key, entry, getEntryCache(entity.getJavaClass(), true), true); - cacheEntry(key, entry, getEntryCache(entity.getJavaClass(), false), false); - } - - public boolean isStateless(PersistentEntity entity) { - Entity mappedForm = entity != null ? entity.getMapping().getMappedForm() : null; - return isStateless() || (mappedForm != null && mappedForm.isStateless()); - } - - protected void cacheEntry(Serializable key, Object entry, Map entryCache, boolean forDirtyCheck) { - if(isStateless()) return; - entryCache.put(key, entry); - } - - public Collection getCachedCollection(PersistentEntity entity, Serializable key, String name) { - if(isStateless(entity)) return null; - if (key == null || name == null) { - return null; - } - - return firstLevelCollectionCache.get( - new CollectionKey(entity.getJavaClass(), key, name)); - } - - public void cacheCollection(PersistentEntity entity, Serializable key, Collection collection, String name) { - if(isStateless(entity)) return; - if (key == null || collection == null || name == null) { - return; - } - - firstLevelCollectionCache.put( - new CollectionKey(entity.getJavaClass(), key, name), - collection); - } - - public Map> getPendingInserts() { - return pendingInserts; - } - - public Map> getPendingUpdates() { - return pendingUpdates; - } - - public Collection getPendingDeletes() { - return pendingDeletes; - } - - public FlushModeType getFlushMode() { - return flushMode; - } - - public void setFlushMode(FlushModeType flushMode) { - this.flushMode = flushMode; - } - - public Datastore getDatastore() { - return datastore; - } - - public MappingContext getMappingContext() { - return mappingContext; - } - - public void flush() { - if (exceptionOccurred) { - throw new InvalidDataAccessResourceUsageException( - "Do not flush() the Session after an exception occurs"); - } - - boolean hasInserts = hasUpdates(); - if (!hasInserts) { - return; - } - - flushPendingInserts(pendingInserts); - pendingInserts.clear(); - - flushPendingUpdates(pendingUpdates); - pendingUpdates.clear(); - - executePendings(pendingDeletes); - - handleDirtyCollections(); - firstLevelCollectionCache.clear(); - - executePendings(postFlushOperations); - - postFlush(hasInserts); - } - - public boolean isDirty(Object instance) { - - if (instance == null) { - return false; - } - - - EntityPersister persister = (EntityPersister) getPersister(instance); - if(persister == null) { - return false; - } - - if(instance instanceof DirtyCheckable) { - return ((DirtyCheckable)instance).hasChanged() || DirtyCheckingSupport.areAssociationsDirty(this, persister.getPersistentEntity(), instance); - } - - if (!(persister instanceof NativeEntryEntityPersister)) { - return false; - } - - Serializable id = persister.getObjectIdentifier(instance); - if (id == null) { - // not persistent - return false; - } - - Object entry = getCachedEntry(persister.getPersistentEntity(), id, false); - Object instance2 = getCachedInstance(instance.getClass(), id); - return instance != instance2 || ((NativeEntryEntityPersister) persister).isDirty(instance, entry); - } - - @Override - public Serializable getObjectIdentifier(Object instance) { - Persister persister = getPersister(instance); - if(persister != null) { - return persister.getObjectIdentifier(instance); - } - return null; - } - - private void handleDirtyCollections() { - for (Map.Entry entry : firstLevelCollectionCache.entrySet()) { - Collection collection = entry.getValue(); - if (!(collection instanceof PersistentCollection)) { - continue; - } - PersistentCollection persistentCollection = (PersistentCollection)collection; - if (!persistentCollection.isDirty()) { - continue; - } - - //TODO once an instance is flushed, its collections need to be non-dirty - CollectionKey key = entry.getKey(); - Object owner = getInstanceCache(key.clazz).get(key.key); - boolean d = isDirty(owner); - } - } - - /** - * The default implementation of flushPendingUpdates is to iterate over each update operation - * and execute them one by one. This may be suboptimal for stores that support batch update - * operations. Subclasses can override this method to implement batch update more efficiently. - * - * @param updates - */ - protected void flushPendingUpdates(Map> updates) { - for (Collection pending : updates.values()) { - flushPendingOperations(pending); - } - } - - /** - * The default implementation of flushPendingInserts is to iterate over each insert operations - * and execute them one by one. This may be suboptimal for stores that support batch insert - * operations. Subclasses can override this method to implement batch insert more efficiently. - * - * @param inserts The insert operations - */ - protected void flushPendingInserts(Map> inserts) { - for (Collection pending : inserts.values()) { - flushPendingOperations(pending); - } - } - - private void flushPendingOperations(Collection operations) { - for (Object o : operations) { - PendingOperation pendingOperation = (PendingOperation) o; - try { - PendingOperationExecution.executePendingOperation(pendingOperation); - } catch (RuntimeException e) { - setFlushMode(FlushModeType.COMMIT); - exceptionOccurred = true; - throw e; - } - } - } - - private boolean hasUpdates() { - return !pendingInserts.isEmpty() || !pendingUpdates.isEmpty() || !pendingDeletes.isEmpty(); - } - - protected void postFlush(boolean hasUpdates) { - // do nothing - } - - private void executePendings(Collection pendings) { - try { - for (Runnable pending : pendings) { - pending.run(); - } - } catch (RuntimeException e) { - setFlushMode(FlushModeType.COMMIT); - exceptionOccurred = true; - throw e; - } - pendings.clear(); - } - - public void clear() { - clearMaps(firstLevelCache); - clearMaps(firstLevelEntryCache); - clearMaps(firstLevelEntryCacheDirtyCheck); - firstLevelCollectionCache.clear(); - pendingInserts.clear(); - pendingUpdates.clear(); - pendingDeletes.clear(); - attributes.clear(); - exceptionOccurred = false; - } - - private void clearMaps(Map> mapOfMaps) { - for (Map cache : mapOfMaps.values()) { - cache.clear(); - } - } - - public final Persister getPersister(Object o) { - if (o == null) return null; - Class cls; - if (o instanceof Class) { - cls = (Class) o; - } - else if (o instanceof PersistentEntity) { - cls = ((PersistentEntity)o).getJavaClass(); - } - else { - cls = o.getClass(); - } - Persister p = persisters.get(cls); - if (p == null) { - p = createPersister(cls, getMappingContext()); - if (p != null) { - if(!isStateless(((EntityPersister)p).getPersistentEntity())) { - firstLevelCache.put(cls, new ConcurrentHashMap()); - } - persisters.put(cls, p); - } - } - return p; - } - - protected abstract Persister createPersister(Class cls, MappingContext mappingContext); - - public boolean contains(Object o) { - if (o == null || isStateless()) { - return false; - } - - return getInstanceCache(o.getClass()).containsValue(o); - } - - public boolean isCached(Class type, Serializable key) { - PersistentEntity entity = getMappingContext().getPersistentEntity(type.getName()); - if (type == null || key == null || isStateless(entity)) { - return false; - } - - return getInstanceCache(type).containsKey(key); - } - - public void cacheInstance(Class type, Serializable key, Object instance) { - if (type == null || key == null || instance == null) { - return; - } - if(isStateless(getMappingContext().getPersistentEntity(type.getName()))) return; - getInstanceCache(type).put(key, instance); - } - - public Object getCachedInstance(Class type, Serializable key) { - if(isStateless()) return null; - if (type == null || key == null) { - return null; - } - if(isStateless(getMappingContext().getPersistentEntity(type.getName()))) return null; - return getInstanceCache(type).get(key); - } - - public void clear(Object o) { - if (o == null || isStateless()) { - return; - } - - final Map cache = firstLevelCache.get(o.getClass()); - if (cache != null) { - Persister persister = getPersister(o); - Serializable key = persister.getObjectIdentifier(o); - if (key != null) { - cache.remove(key); - } - } - removeAttributesForEntity(o); - } - - public void attach(Object o) { - if (o == null) { - return; - } - - EntityPersister p = (EntityPersister) getPersister(o); - if (p == null) { - return; - } - - Serializable identifier = p.getObjectIdentifier(o); - if (identifier != null) { - cacheObject(identifier, o); - } - } - - protected void cacheObject(Serializable identifier, Object o) { - if (identifier == null || o == null) { - return; - } - cacheInstance(o.getClass(), identifier, o); - } - - public Serializable persist(Object o) { - Assert.notNull(o, "Cannot persist null object"); - Persister persister = getPersister(o); - if (persister == null) { - throw new NonPersistentTypeException("Object [" + o + - "] cannot be persisted. It is not a known persistent type."); - } - - final Serializable key = persister.persist(o); - cacheObject(key, o); - return key; - } - - @Override - public Serializable insert(Object o) { - Assert.notNull(o, "Cannot persist null object"); - Persister persister = getPersister(o); - if (persister == null) { - throw new NonPersistentTypeException("Object [" + o + - "] cannot be persisted. It is not a known persistent type."); - } - - final Serializable key = persister.insert(o); - cacheObject(key, o); - return key; - } - - public void refresh(Object o) { - Assert.notNull(o, "Cannot persist null object"); - Persister persister = getPersister(o); - if (persister == null) { - throw new NonPersistentTypeException("Object [" + o + - "] cannot be refreshed. It is not a known persistent type."); - } - - final Serializable key = persister.refresh(o); - cacheObject(key, o); - } - - public Object retrieve(Class type, Serializable key) { - if (key == null || type == null) { - return null; - } - - Persister persister = getPersister(type); - if (persister == null) { - throw new NonPersistentTypeException("Cannot retrieve object with key [" + key + - "]. The class [" + type.getName() + "] is not a known persistent type."); - } - - final PersistentEntity entity = getMappingContext().getPersistentEntity(type.getName()); - if (entity != null) { - key = (Serializable) getMappingContext().getConversionService().convert( - key, entity.getIdentity().getType()); - } - - Object o = getInstanceCache(type).get(key); - if (o == null) { - o = persister.retrieve(key); - if (o != null) { - cacheObject(key, o); - } - } - return o; - } - - public Object proxy(Class type, Serializable key) { - if (key == null || type == null) { - return null; - } - - Persister persister = getPersister(type); - if (persister == null) { - throw new NonPersistentTypeException("Cannot retrieve object with key [" + key + - "]. The class [" + type.getName() + "] is not a known persistent type."); - } - - // only return proxy if real instance is not available. - Object o = getInstanceCache(type).get(key); - if (o == null) { - o = persister.proxy(key); - } - - return o; - } - - public void lock(Object o) { - throw new UnsupportedOperationException("Datastore ["+getClass().getName()+"] does not support locking."); - } - - public Object lock(Class type, Serializable key) { - throw new UnsupportedOperationException("Datastore ["+getClass().getName()+"] does not support locking."); - } - - public void unlock(Object o) { - if (o != null) { - lockedObjects.remove(o); - } - } - - /** - * This default implementation of the deleteAll method is unlikely to be optimal as it iterates and deletes each object. - * - * Subclasses should override to optimize for the batch operation capability of the underlying datastore - * - * @param criteria The criteria - */ - public int deleteAll(QueryableCriteria criteria) { - List list = criteria.list(); - delete(list); - return list.size(); - } - - /** - * This default implementation of updateAll is unlikely to be optimal as it iterates and updates each object one by one. - * - * Subclasses should override to optimize for the batch operation capability of the underlying datastore - * - * @param criteria The criteria - * @param properties The properties - */ - public int updateAll(QueryableCriteria criteria, Map properties) { - List list = criteria.list(); - for (Object o : list) { - BeanWrapper bean = new BeanWrapperImpl(o); - for (String property : properties.keySet()) { - bean.setPropertyValue(property, properties.get(property)); - } - } - persist(list); - return list.size(); - } - - public void delete(final Object obj) { - if (obj == null) { - return; - } - - getPendingDeletes().add(new Runnable() { - public void run() { - Persister p = getPersister(obj); - if (p == null) { - return; - } - - p.delete(obj); - clear(obj); - } - }); - } - - public void delete(final Iterable objects) { - if (objects == null) { - return; - } - - // sort the objects into sets by Persister, in case the objects are of different types. - Map toDelete = new HashMap(); - for (Object object : objects) { - if (object == null) { - continue; - } - final Persister p = getPersister(object); - if (p == null) { - continue; - } - List listForPersister = toDelete.get(p); - if (listForPersister == null) { - toDelete.put(p, listForPersister = new ArrayList()); - } - listForPersister.add(object); - } - // for each type (usually only 1 type), set up a pendingDelete of that type - for (Map.Entry entry : toDelete.entrySet()) { - final Persister p = entry.getKey(); - final List objectsForP = entry.getValue(); - pendingDeletes.add(new Runnable() { - public void run() { - p.delete(objectsForP); - for (Object o : objectsForP) { - clear(o); - } - } - }); - } - } - - public List persist(Iterable objects) { - if (objects == null) { - return Collections.emptyList(); - } - - final Iterator i = objects.iterator(); - if (!i.hasNext()) { - return Collections.emptyList(); - } - - // peek at the first object to get the persister - final Object obj = i.next(); - final Persister p = getPersister(obj); - if (p == null) { - throw new NonPersistentTypeException("Cannot persist objects. The class [" + - obj.getClass().getName() + "] is not a known persistent type."); - } - - return p.persist(objects); - } - - public List retrieveAll(Class type, Iterable keys) { - Persister p = getPersister(type); - if (p == null) { - throw new NonPersistentTypeException("Cannot retrieve objects with keys [" + keys + - "]. The class [" + type.getName() + "] is not a known persistent type."); - } - - List list = new ArrayList(); - List toRetrieve = new ArrayList(); - final Map cache = getInstanceCache(type); - for (Object key : keys) { - Serializable serializable = (Serializable) key; - Object cached = cache.get(serializable); - list.add(cached); - if (cached == null) { - toRetrieve.add(serializable); - } - } - List retrieved = p.retrieveAll(toRetrieve); - Iterator keyIterator = toRetrieve.iterator(); - Iterator retrievedIterator = retrieved.iterator(); - // now fill in the null entries (possibly with more nulls) - for (int i = 0; i < list.size(); i++) { - Object o = list.get(i); - if (o == null) { - Object next = retrievedIterator.next(); - Serializable key = keyIterator.next(); - list.set(i, next); - cacheInstance(type, key, next); - } - } - return list; - } - - public List retrieveAll(Class type, Serializable... keys) { - Persister p = getPersister(type); - if (p == null) { - throw new NonPersistentTypeException("Cannot retrieve objects with keys [" + keys + - "]. The class [" + type.getName() + "] is not a known persistent type."); - } - return retrieveAll(type, Arrays.asList(keys)); - } - - public Query createQuery(Class type) { - Persister p = getPersister(type); - if (p == null) { - throw new NonPersistentTypeException("Cannot create query. The class [" + type + - "] is not a known persistent type."); - } - - return p.createQuery(); - } - - public final Transaction beginTransaction() { - transaction = beginTransactionInternal(); - return transaction; - } - - protected abstract Transaction beginTransactionInternal(); - - public Transaction getTransaction() { - if (transaction == null) { - throw new NoTransactionException("Transaction not started. Call beginTransaction() first"); - } - return transaction; - } - - private Map getInstanceCache(Class c) { - Map cache = firstLevelCache.get(c); - if (cache == null) { - cache = new ConcurrentHashMap(); - firstLevelCache.put(c, cache); - } - return cache; - } - - private Map getEntryCache(Class c, boolean forDirtyCheck) { - Map> caches = forDirtyCheck ? firstLevelEntryCacheDirtyCheck : firstLevelEntryCache; - Map cache = caches.get(c); - if (cache == null) { - cache = new ConcurrentHashMap(); - caches.put(c, cache); - } - return cache; - } - - private static class CollectionKey { - final Class clazz; - final Serializable key; - final String collectionName; - - private CollectionKey(Class clazz, Serializable key, String collectionName) { - this.clazz = clazz; - this.key = key; - this.collectionName = collectionName; - } - - @Override - public int hashCode() { - int value = 17; - value = value * 37 + clazz.getName().hashCode(); - value = value * 37 + key.hashCode(); - value = value * 37 + collectionName.hashCode(); - return value; - } - - @Override - public boolean equals(Object obj) { - CollectionKey other = (CollectionKey)obj; - return other.clazz.getName() == clazz.getName() && - other.key.equals(key) && - other.collectionName.equals(collectionName); - } - - @Override - public String toString() { - return clazz.getName() + ':' + key + ':' + collectionName; - } - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/ConnectionNotFoundException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/ConnectionNotFoundException.java deleted file mode 100644 index d8e06e1e1..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/ConnectionNotFoundException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -/** - * Thrown when a session cannot be located. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class ConnectionNotFoundException extends RuntimeException { - - private static final long serialVersionUID = 1; - - public ConnectionNotFoundException(String s) { - super(s); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Datastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Datastore.java deleted file mode 100644 index 65b50e6d5..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Datastore.java +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.ConfigurableApplicationContext; -import org.grails.datastore.mapping.model.MappingContext; -import org.springframework.validation.Errors; - -/** - * The Datastore interface is the basic commom denominator all NoSQL databases should support: - *
      - *
    • Storing data
    • - *
    • Retrieving one or more elements at a time, identified by their keys
    • - *
    • Deleting one or more elements
    • - *
    - * - * @author Guillaume Laforge - * @author Graeme Rocher - */ -public interface Datastore { - - /** - * Connects to the datastore with the default connection details, normally provided via the datastore implementations constructor - * - * @return The session created using the default connection details. - */ - Session connect(); - - /** - * Obtains the current session (if any) - * @return The current thread bound session - * - * @throws ConnectionNotFoundException Thrown if the {@link #connect()} method has not yet been called - */ - Session getCurrentSession() throws ConnectionNotFoundException; - - /** - * Checks if there is a current session. - * @return true if there's a bound active session - */ - boolean hasCurrentSession(); - - /** - * Obtains the MappingContext object - * - * @return The MappingContext object - */ - MappingContext getMappingContext(); - - /** - * Get the application event publisher. - * @return the publisher - */ - ApplicationEventPublisher getApplicationEventPublisher(); - - /** - * Get the application context. - * @return the context - */ - ConfigurableApplicationContext getApplicationContext(); - - /** - * Get the validation errors if available. - * @param o the entity - * @return the errors or null - */ - Errors getObjectErrors(Object o); - - /** - * Register validation errors for an instance. - * @param object the instance - * @param errors the errors - */ - void setObjectErrors(Object object, Errors errors); - - /** - * Check if validation should be skipped. - * @param o the instance - * @return true to skip - */ - boolean skipValidation(Object o); - - /** - * Register that validation should be skipped or not. - * @param o the instance - * @param skip whether to skip or not - */ - void setSkipValidation(Object o, boolean skip); - - /** - * Whether the datastore is schema-less. That is it allows changes to the schema runtime, dynamic attributes etc. - * - * @return True if it does - */ - boolean isSchemaless(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreAware.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreAware.java deleted file mode 100644 index 3dab79a6b..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreAware.java +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -/** - * An interface for classes to implement that want access to the Datastore - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface DatastoreAware { - - /** - * Sets the datastore on this instance - * @param datastore The datastore - */ - void setDatastore(Datastore datastore); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreException.java deleted file mode 100644 index a20d97056..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -/** - * General exception for errors related to the configuration - * of the Datastore - * - * @author Graeme Rocher - * @since 1.0 - */ -public class DatastoreException extends RuntimeException { - - private static final long serialVersionUID = 1; - - public DatastoreException(String s) { - super(s); - } - - public DatastoreException(String s, Throwable throwable) { - super(s, throwable); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreUtils.java deleted file mode 100644 index 723f59933..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreUtils.java +++ /dev/null @@ -1,383 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -import groovy.lang.Closure; - -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.core.NamedThreadLocal; -import org.springframework.dao.DataAccessResourceFailureException; -import org.grails.datastore.mapping.transactions.SessionHolder; -import org.grails.datastore.mapping.transactions.support.SpringSessionSynchronization; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.util.Assert; - -/** - * Helper class for obtaining Datastore sessions. Based on similar work - * for Hibernate such as SessionFactoryUtils - * - * @author Juergen Hoeller - * @author Graeme Rocher - */ -@SuppressWarnings("rawtypes") -public abstract class DatastoreUtils { - - public static final Log logger = LogFactory.getLog(DatastoreUtils.class); - private static final ThreadLocal>> deferredCloseHolder = - new NamedThreadLocal>>( - "Datastore Sessions registered for deferred close"); - - /** - * Get a Datastore Session for the given Datastore. Is aware of and will - * return any existing corresponding Session bound to the current thread, for - * example when using {@link org.grails.datastore.mapping.transactions.DatastoreTransactionManager}. Will create a new - * Session otherwise, if "allowCreate" is true. - *

    This is the getSession method used by typical data access code, - * in combination with releaseSession called when done with - * the Session. - * - * @param datastore Datastore to create the session with - * @param allowCreate whether a non-transactional Session should be created - * when no transactional Session can be found for the current thread - * @return the Datastore Session - * @throws org.springframework.dao.DataAccessResourceFailureException if the Session couldn't be created - * @throws IllegalStateException if no thread-bound Session found and - * "allowCreate" is false - */ - public static Session getSession(Datastore datastore, boolean allowCreate) - throws DataAccessResourceFailureException, IllegalStateException { - - try { - return doGetSession(datastore, allowCreate); - } - catch (Exception ex) { - throw new DataAccessResourceFailureException("Could not open Datastore Session", ex); - } - } - - /** - * Get a Datastore Session for the given Datastore. Is aware of and will - * return any existing corresponding Session bound to the current thread, for - * example when using {@link org.grails.datastore.mapping.transactions.DatastoreTransactionManager}. Will create a new - * Session otherwise, if "allowCreate" is true. - * - * @param datastore Datastore to create the session with - * Session on transaction synchronization (may be null) - * @param allowCreate whether a non-transactional Session should be created - * when no transactional Session can be found for the current thread - * @return the Datastore Session - * @throws IllegalStateException if no thread-bound Session found and - * "allowCreate" is false - */ - public static Session doGetSession(Datastore datastore, boolean allowCreate) { - - Assert.notNull(datastore, "No Datastore specified"); - - SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(datastore); - - if (sessionHolder != null && !sessionHolder.isEmpty()) { - // pre-bound Datastore Session - Session session; - if (TransactionSynchronizationManager.isSynchronizationActive() && - sessionHolder.doesNotHoldNonDefaultSession()) { - // Spring transaction management is active -> - // register pre-bound Session with it for transactional flushing. - session = sessionHolder.getValidatedSession(); - if (session != null && !sessionHolder.isSynchronizedWithTransaction()) { - logger.debug("Registering Spring transaction synchronization for existing Datastore Session"); - TransactionSynchronizationManager.registerSynchronization( - new SpringSessionSynchronization(sessionHolder, datastore, false)); - sessionHolder.setSynchronizedWithTransaction(true); - - } - if (session != null) { - return session; - } - } - else { - session = sessionHolder.getValidatedSession(); - if (session != null) { - return session; - } - } - } - - logger.debug("Opening Datastore Session"); - Session session = datastore.connect(); - - // Use same Session for further Datastore actions within the transaction. - // Thread object will get removed by synchronization at transaction completion. - if (TransactionSynchronizationManager.isSynchronizationActive()) { - // We're within a Spring-managed transaction, possibly from JtaTransactionManager. - logger.debug("Registering Spring transaction synchronization for new Datastore Session"); - SessionHolder holderToUse = sessionHolder; - if (holderToUse == null) { - holderToUse = new SessionHolder(session); - } - else { - holderToUse.addSession(session); - } - TransactionSynchronizationManager.registerSynchronization( - new SpringSessionSynchronization(holderToUse, datastore, true)); - holderToUse.setSynchronizedWithTransaction(true); - if (holderToUse != sessionHolder) { - TransactionSynchronizationManager.bindResource(datastore, holderToUse); - } - } - - // Check whether we are allowed to return the Session. - if (!allowCreate && !isSessionTransactional(session, datastore)) { - closeSession(session); - throw new IllegalStateException("No Datastore Session bound to thread, " + - "and configuration does not allow creation of non-transactional one here"); - } - - return session; - } - - /** - * Return whether the given Datastore Session is transactional, that is, - * bound to the current thread by Spring's transaction facilities. - * @param session the Datastore Session to check - * @param datastore Datastore that the Session was created with - * (may be null) - * @return whether the Session is transactional - */ - public static boolean isSessionTransactional(Session session, Datastore datastore) { - if (datastore == null) { - return false; - } - SessionHolder sessionHolder = - (SessionHolder) TransactionSynchronizationManager.getResource(datastore); - return (sessionHolder != null && sessionHolder.containsSession(session)); - } - - /** - * Perform actual closing of the Session, - * catching and logging any cleanup exceptions thrown. - * @param session The Session instance - */ - public static void closeSession(Session session) { - if (session == null) { - return; - } - - logger.debug("Closing Datastore Session"); - try { - session.disconnect(); - } - catch (Throwable ex) { - logger.debug("Unexpected exception on closing Datastore Session", ex); - } - } - - /** - * Close the given Session, created via the given factory, - * if it is not managed externally (i.e. not bound to the thread). - * @param session the Datastore Session to close (may be null) - * @param datastore Datastore that the Session was created with - * (may be null) - */ - public static void releaseSession(Session session, Datastore datastore) { - if (session == null) { - return; - } - // Only close non-transactional Sessions. - if (!isSessionTransactional(session, datastore)) { - closeSessionOrRegisterDeferredClose(session, datastore); - } - } - - /** - * Process all Datastore Sessions that have been registered for deferred close - * for the given SessionFactory. - * @param datastore the Datastore to process deferred close for - * @see #initDeferredClose - * @see #releaseSession - */ - public static void processDeferredClose(Datastore datastore) { - Assert.notNull(datastore, "No Datastore specified"); - Map> holderMap = deferredCloseHolder.get(); - if (holderMap == null || !holderMap.containsKey(datastore)) { - throw new IllegalStateException("Deferred close not active for Datastore [" + datastore + "]"); - } - logger.debug("Processing deferred close of Datastore Sessions"); - Set sessions = holderMap.remove(datastore); - for (Session session : sessions) { - closeSession(session); - } - if (holderMap.isEmpty()) { - deferredCloseHolder.set(null); - } - } - - /** - * Initialize deferred close for the current thread and the given Datastore. - * Sessions will not be actually closed on close calls then, but rather at a - * {@link #processDeferredClose} call at a finishing point (like request completion). - * - * @param datastore the Datastore to initialize deferred close for - * @see #processDeferredClose - * @see #releaseSession - */ - public static void initDeferredClose(Datastore datastore) { - Assert.notNull(datastore, "No Datastore specified"); - logger.debug("Initializing deferred close of Datastore Sessions"); - Map> holderMap = deferredCloseHolder.get(); - if (holderMap == null) { - holderMap = new HashMap>(); - deferredCloseHolder.set(holderMap); - } - holderMap.put(datastore, new LinkedHashSet(4)); - } - - /** - * Close the given Session or register it for deferred close. - * @param session the Datastore Session to close - * @param datastore Datastore that the Session was created with - * (may be null) - * @see #initDeferredClose - * @see #processDeferredClose - */ - public static void closeSessionOrRegisterDeferredClose(Session session, Datastore datastore) { - Map> holderMap = deferredCloseHolder.get(); - if (holderMap != null && datastore != null && holderMap.containsKey(datastore)) { - logger.debug("Registering Datastore Session for deferred close"); - holderMap.get(datastore).add(session); - } - else { - closeSession(session); - } - } - - /** - * Execute the closure in the current session if it exists, or create a new one and close it otherwise. - * @param datastore the datastore - * @param c the closure to execute - * @return the return value from the closure - */ - public static Object doWithSession(final Datastore datastore, final Closure c) { - boolean existing = datastore.hasCurrentSession(); - Session session = existing ? datastore.getCurrentSession() : bindSession(datastore.connect()); - try { - return c.call(session); - } - finally { - if (!existing) { - TransactionSynchronizationManager.unbindResource(session.getDatastore()); - closeSessionOrRegisterDeferredClose(session, datastore); - } - } - } - - /** - * Execute the callback in the current session if it exists, or create a new one and close it otherwise. - * @param the return type - * @param datastore the datastore - * @param callback the callback to execute - * @return the return value from the callback - */ - public static T execute(final Datastore datastore, final SessionCallback callback) { - boolean existing = datastore.hasCurrentSession(); - Session session = existing ? datastore.getCurrentSession() : bindSession(datastore.connect()); - try { - return callback.doInSession(session); - } - finally { - if (!existing) { - TransactionSynchronizationManager.unbindResource(session.getDatastore()); - closeSessionOrRegisterDeferredClose(session, datastore); - } - } - } - - /** - * Execute the callback in the current session if it exists, or create a new one and close it otherwise. - * @param datastore the datastore - * @param callback the callback to execute - */ - public static void execute(final Datastore datastore, final VoidSessionCallback callback) { - boolean existing = datastore.hasCurrentSession(); - Session session = existing ? datastore.getCurrentSession() : bindSession(datastore.connect()); - try { - callback.doInSession(session); - } - finally { - if (!existing) { - TransactionSynchronizationManager.unbindResource(datastore); - closeSessionOrRegisterDeferredClose(session, datastore); - } - } - } - - /** - * Bind the session to the thread with a SessionHolder keyed by its Datastore. - * @param session the session - * @return the session (for method chaining) - */ - public static Session bindSession(final Session session) { - TransactionSynchronizationManager.bindResource(session.getDatastore(), new SessionHolder(session)); - return session; - } - - /** - * Adds the session to the current SessionHolder's list of sessions, making it the current session. - * If there's no current session, calls bindSession. - * @param session the session - * @return the session - */ - public static Session bindNewSession(final Session session) { - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(session.getDatastore()); - if (sessionHolder == null) { - return bindSession(session); - } - - sessionHolder.addSession(session); - return session; - } - - /** - * Unbinds and closes a session. If it's the only session in the SessionHolder, unbinds - * the SessionHolder, otherwise just removes the session from the holder's list. - * @param session the session - */ - public static void unbindSession(final Session session) { - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(session.getDatastore()); - if (sessionHolder == null) { - logger.warn("Cannot unbind session, there's no SessionHolder registered"); - return; - } - - if (!sessionHolder.containsSession(session)) { - logger.warn("Cannot unbind session, it's not registered in a SessionHolder"); - return; - } - - if (sessionHolder.size() > 1) { - sessionHolder.removeSession(session); - } - else { - TransactionSynchronizationManager.unbindResource(session.getDatastore()); - } - - closeSessionOrRegisterDeferredClose(session, session.getDatastore()); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/EntityCreationException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/EntityCreationException.java deleted file mode 100644 index 665db05da..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/EntityCreationException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -/** - * Thrown when there was an error creating an entity. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class EntityCreationException extends RuntimeException { - - private static final long serialVersionUID = 1; - - public EntityCreationException(String msg) { - super(msg); - } - - public EntityCreationException(String msg, Throwable throwable) { - super(msg, throwable); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/IdentityGenerationException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/IdentityGenerationException.java deleted file mode 100644 index b9bccca5c..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/IdentityGenerationException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -/** - * Thrown when an identity cannot be generated. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class IdentityGenerationException extends RuntimeException { - - private static final long serialVersionUID = 1; - - public IdentityGenerationException(String msg) { - super(msg); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/OptimisticLockingException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/OptimisticLockingException.java deleted file mode 100644 index 83c26842b..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/OptimisticLockingException.java +++ /dev/null @@ -1,46 +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.mapping.core; - -import org.springframework.dao.OptimisticLockingFailureException; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Indicates an optimistic locking violation during an update. - * - * @author Burt Beckwith - * @since 1.0 - */ -public class OptimisticLockingException extends OptimisticLockingFailureException { - - private static final long serialVersionUID = 1; - - private final Object key; - private final PersistentEntity persistentEntity; - - public OptimisticLockingException(final PersistentEntity persistentEntity, final Object key) { - super("The instance was updated by another user while you were editing"); - this.key = key; - this.persistentEntity = persistentEntity; - } - - public PersistentEntity getPersistentEntity() { - return persistentEntity; - } - - public Object getKey() { - return key; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Session.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Session.java deleted file mode 100644 index 344794e45..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Session.java +++ /dev/null @@ -1,309 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; - -import javax.persistence.FlushModeType; - -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.grails.datastore.mapping.transactions.Transaction; - -/** - * The Session represents the active interaction with a datastore. - * - * @author Graeme Rocher - * @author Guillaume Laforge - * - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public interface Session { - - /** - * Associates an attribute with the given persistent entity. Attributes will - * be cleared out when the Session is closed or cleared. - * - * @param entity The persistent instance (must be associated with this Session) - * @param attributeName The attribute name - * @param value The value - */ - void setAttribute(Object entity, String attributeName, Object value); - - /** - * Obtains an attribute for the given entity - * - * @param entity The entity - * @param attributeName The attribute - * @return The attribute value - */ - Object getAttribute(Object entity, String attributeName); - - /** - * Set a property on this session. Note that properties are not cleared out when a session is cleared. - * @param property The property name. - * @param value The property value. - * @return The previous property value, if there was one (or null). - */ - Object setSessionProperty(String property, Object value); - - /** - * Get the value of a property of the session. - * @param property The name of the property. - * @return The value. - */ - Object getSessionProperty(String property); - - /** - * Clear a property in a session. - * @param property The property name. - * @return The property value, if there was one (or null). - */ - Object clearSessionProperty(String property); - - /** - * @return true if connected to the datastore - */ - boolean isConnected(); - - /** - * Disconnects from the datastore. - */ - void disconnect(); - - /** - * Starts a transaction - * @return The transaction - */ - Transaction beginTransaction(); - - /** - * Obtains the MappingContext instance - * - * @return The MappingContext - */ - MappingContext getMappingContext(); - - /** - * Stores and object and returns its key - * - * @param o The object - * @return The the generated key - */ - Serializable persist(Object o); - - /** - * Forces an insert - * - * @param o The object - * @return The id - */ - Serializable insert(Object o); - - /** - * Refreshes the given objects state - * @param o The object to refresh - */ - void refresh(Object o); - - /** - * Attaches an object the current session - * @param o The object to attach - */ - void attach(Object o); - - /** - * Flushes any pending changes to the datastore - */ - void flush(); - - /** - * Clears any pending changes to the datastore - */ - void clear(); - - /** - * Clear a specific object - * @param o The object to clear - */ - void clear(Object o); - - /** - * Whether the object is contained within the first level cache - * @param o The object to check - * @return true if it is - */ - boolean contains(Object o); - - /** - * The flush mode, defaults to FlushModeType.AUTO - * - * @param flushMode The FlushModeType - */ - void setFlushMode(FlushModeType flushMode); - - /** - * Obtains the current FlushModeType - * @return The FlushModeType instance - */ - FlushModeType getFlushMode(); - - /** - * Obtains a write lock on the given object - * - * @param o The object to lock - */ - void lock(Object o); - - /** - * Releases a lock, if not called all locked objects should be released by {@link #disconnect()} - * - * @param o The object to unlock - */ - void unlock(Object o); - - /** - * Persists several objects returning their identifiers in the order specified by the Iterable - * - * @param objects The Objects - * @return The identifiers - */ - List persist(Iterable objects); - - /** - * Retrieves an individual object - * - * @param type The type - * @param key The key - * @return The object - */ - T retrieve(Class type, Serializable key); - - /** - * Retrieves a proxy for the given key - * - * @param type The type - * @param key The key - * @return The object - */ - T proxy(Class type, Serializable key); - - /** - * Retrieves an individual object, using a write lock to prevent loss of updates - * - * @param type The type - * @param key The key - * @return The object - */ - T lock(Class type, Serializable key); - - /** - * Deletes one or many objects - * - * @param objects The objects to delete - */ - void delete(Iterable objects); - - /** - * Deletes a single object - * @param obj The object to delete - */ - void delete(Object obj); - - /** - * Deletes all objects matching the given criteria - * - * @param criteria The criteria - * @return The total number of records deleted - */ - int deleteAll(QueryableCriteria criteria); - - /** - * Updates all objects matching the given criteria and property values - * @param criteria The criteria - * @param properties The properties - * @return The total number of records updated - */ - int updateAll(QueryableCriteria criteria, Map properties); - - /** - * Retrieves several objects for the specified keys - * @param type The type - * @param keys The keys - * @return A list of objects - */ - List retrieveAll(Class type, Iterable keys); - - /** - * Retrieves several objects for the specified keys - * @param type The type - * @param keys The keys - * @return A list of objects - */ - List retrieveAll(Class type, Serializable...keys); - - /** - * Creates a query instance for the give type - * - * @param type The type - * @return The query - */ - Query createQuery(Class type); - - /** - * @return The native interface to the datastore - */ - Object getNativeInterface(); - - /** - * The persister for the given object - * @param o The object - * @return The persister - */ - Persister getPersister(Object o); - - /** - * Obtains the current transaction instance - * @return The Transaction instance - */ - Transaction getTransaction(); - - /** - * The Datastore that created this Session - * @return The Datastore instance - */ - Datastore getDatastore(); - - /** - * Check if the instance has been modified since loading. - * @param instance the instance - * @return true if one or more fields have changed - */ - boolean isDirty(Object instance); - - /** - * Obtains the identifier for the instance - * @param instance The instance - * @return The identifier or null if it cannot be established - */ - Serializable getObjectIdentifier(Object instance); - - -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCallback.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCallback.java deleted file mode 100644 index 0e683b218..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCallback.java +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -import org.grails.datastore.mapping.core.Session; - -/** - * @author Burt Beckwith - * @param - */ -public interface SessionCallback { - T doInSession(Session session); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCreationEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCreationEvent.java deleted file mode 100644 index e8b4ef69d..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCreationEvent.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.grails.datastore.mapping.core; - -import org.springframework.context.ApplicationEvent; - -/** - * Event fired when a session is created. This can be used to customize the session. - */ -public class SessionCreationEvent extends ApplicationEvent { - - private final Session session; - - public SessionCreationEvent(Session session) { - super(session.getDatastore()); - this.session = session; - } - - /** - * @return The session that has just been created. - */ - public Session getSession() { - return session; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionImplementor.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionImplementor.java deleted file mode 100644 index 46aca683c..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionImplementor.java +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Map; - -import org.grails.datastore.mapping.core.impl.PendingInsert; -import org.grails.datastore.mapping.core.impl.PendingUpdate; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Methods for the implementation of the {@link Session} interface to implement. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public interface SessionImplementor { - - /** - * @return Whether the session is stateless - */ - boolean isStateless(); - - /** - * @return Whether the session is stateless - */ - boolean isStateless(PersistentEntity entity); - - /** - * Adds a pending insert operation - * - * @param insert The pending insert operation - */ - void addPendingInsert(PendingInsert insert); - - /** - * Adds a pending update operation - * @param update The pending update operation - */ - void addPendingUpdate(PendingUpdate update); - - /** - * @return The pending insert operations - */ - Map> getPendingInserts(); - - /** - * @return The pending updates - */ - Map> getPendingUpdates(); - - /** - * @return The pending deletes - */ - Collection getPendingDeletes(); - - /** - * Caches a native entry - * @param entity The entity - * @param key The key - * @param entry The native entry - */ - void cacheEntry(PersistentEntity entity, Serializable key, T entry); - - /** - * Obtains a cached entry - * @param entity The entity - * @param key The key - * @return The cached entry - */ - T getCachedEntry(PersistentEntity entity, Serializable key); - /** - * Obtains a cached entry - * @param entity The entity - * @param key The key - * @param forDirtyCheck Whether to obtain for purposes for dirty checking - * @return The cached entry - */ - T getCachedEntry(PersistentEntity entity, Serializable key, boolean forDirtyCheck); - - /** - * Caches an instance - * @param type The type - * @param key The key - * @param instance The instance - */ - void cacheInstance(Class type, Serializable key, Object instance); - - /** - * Get the cached instance if it exists. - * @param type the object type - * @param key the object key - * @return the instance or null - */ - Object getCachedInstance(Class type, Serializable key); - - /** - * Whether an object with the specified key is contained within the first level cache. - * @param type the object type - * @param key The key to check - * @return true if it is - */ - boolean isCached(Class type, Serializable key); - - /** - * Obtains a cached collection - * - * @param entity The entity - * @param key The key - * @param name The name - * @return The cached collection or null - */ - Collection getCachedCollection(PersistentEntity entity, Serializable key, String name); - - /** - * Caches a collection - * - * @param entity The entity - * @param key The key - * @param collection The collection - * @param name The name of the collection - */ - void cacheCollection(PersistentEntity entity, Serializable key, Collection collection, String name); - - /** - * Adds an operation to be executed after a flush - * @param runnable The runnable - */ - void addPostFlushOperation(Runnable runnable); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SoftThreadLocalMap.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SoftThreadLocalMap.java deleted file mode 100644 index 9b0c31707..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SoftThreadLocalMap.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.grails.datastore.mapping.core; - -import org.springframework.util.ConcurrentReferenceHashMap; - -/** - * Creates a InheritableThreadLocal with an intial value of a Map. - * - * @author Graeme Rocher - */ -public class SoftThreadLocalMap extends InheritableThreadLocal { - - /** - * Creates an initial value of a Map. - */ - @Override - protected ConcurrentReferenceHashMap initialValue() { - return new ConcurrentReferenceHashMap(); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/StatelessDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/StatelessDatastore.java deleted file mode 100644 index 74cc62be3..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/StatelessDatastore.java +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.core; - -/** - * For Datastores that support stateless connectivity - * - * @author Graeme Rocher - * @since 2.3 - */ -public interface StatelessDatastore extends Datastore{ - - /** - * Connect and return a stateless session - * @return The session - */ - Session connectStateless(); -} - diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/VoidSessionCallback.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/VoidSessionCallback.java deleted file mode 100644 index 2c1a00c63..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/VoidSessionCallback.java +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core; - -import org.grails.datastore.mapping.core.Session; - -/** - * @author Burt Beckwith - */ -public interface VoidSessionCallback { - void doInSession(Session session); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsert.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsert.java deleted file mode 100644 index 9bcf27634..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsert.java +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core.impl; - -import org.grails.datastore.mapping.engine.EntityAccess; - -/** - * An insert that is pending execution in a flush() operation - * - * @param The native entry to persist - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface PendingInsert extends Runnable, PendingOperation{ - /** - * @return The EntityAccess object for the entity to be inserted - */ - EntityAccess getEntityAccess(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsertAdapter.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsertAdapter.java deleted file mode 100644 index 8aa013548..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsertAdapter.java +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core.impl; - -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Provides default implementation for most of the methods in the {@link PendingInsert} interafce - * - * @param The native entry to persist - * - * @author Graeme Rocher - * @since 1.0 - */ -public abstract class PendingInsertAdapter extends PendingOperationAdapter implements PendingInsert{ - - private EntityAccess entityAccess; - - private boolean vetoed; - - public PendingInsertAdapter(PersistentEntity entity, K nativeKey, E nativeEntry, EntityAccess ea) { - super(entity, nativeKey, nativeEntry); - this.entityAccess = ea; - } - - public boolean isVetoed() { - return vetoed; - } - - public void setVetoed(boolean vetoed) { - this.vetoed = vetoed; - } - - public EntityAccess getEntityAccess() { - return entityAccess; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperation.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperation.java deleted file mode 100644 index 4a324fa25..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperation.java +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core.impl; - -import java.util.List; - -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * An operation that is pending execution. - * - * @author Graeme Rocher - * - * @param The native entity type (examples could be Row, Document etc.) - * @param The native key - */ -public interface PendingOperation extends Runnable { - - /** - * @return Whether the operation has been vetoed - */ - boolean isVetoed(); - - /** - * @return The {@link PersistentEntity} being inserted - */ - PersistentEntity getEntity(); - - /** - * @return The native key to insert - */ - K getNativeKey(); - - /** - * @return The native entry to persist - */ - E getNativeEntry(); - - /** - * Operations to be executed directly prior to this operation - * @return The operations to execute prior - */ - List> getPreOperations(); - - /** - * Adds an operation to executed prior to other operations - * @param preOperation The prior operation - */ - void addPreOperation(PendingOperation preOperation); - - /** - * Operations to be executed directly following this operation - * @return The operations to cascade to - */ - List> getCascadeOperations(); - - /** - * Adds an operation that should be executed after this operation - * - * @param pendingOperation The pending operation - */ - void addCascadeOperation(PendingOperation pendingOperation); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationAdapter.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationAdapter.java deleted file mode 100644 index 6e5d46797..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationAdapter.java +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core.impl; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Base implementation of the {@link PendingOperation} interface. - * - * @author Graeme Rocher - * - * @param The native entity type (examples could be Row, Document etc.) - * @param The native key - */ -public abstract class PendingOperationAdapter implements PendingOperation { - - protected PersistentEntity entity; - protected K nativeKey; - protected E nativeEntry; - private List> pendingOperations = new LinkedList>(); - private List> preOperations = new LinkedList>(); - private boolean vetoed; - - public PendingOperationAdapter(PersistentEntity entity, K nativeKey, E nativeEntry) { - this.entity = entity; - this.nativeKey = nativeKey; - this.nativeEntry = nativeEntry; - } - - public boolean isVetoed() { - return vetoed; - } - - public void setVetoed(boolean vetoed) { - this.vetoed = vetoed; - } - - public List> getPreOperations() { - return Collections.unmodifiableList(preOperations); - } - - public void addPreOperation(PendingOperation preOperation) { - preOperations.add(preOperation); - } - - public List> getCascadeOperations() { - return Collections.unmodifiableList(pendingOperations); - } - - public void addCascadeOperation(PendingOperation pendingOperation) { - pendingOperations.add(pendingOperation); - } - - public K getNativeKey() { - return nativeKey; - } - - public PersistentEntity getEntity() { - return entity; - } - - public E getNativeEntry() { - return nativeEntry; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationExecution.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationExecution.java deleted file mode 100644 index d0ca9e868..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationExecution.java +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core.impl; - -import java.util.List; - -/** - * Provides a default implementation to execute a pending operation. - * - * @author Graeme Rocher - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class PendingOperationExecution { - - public static void executePendingOperation(PendingOperation pendingOperation) { - List preOperations = pendingOperation.getPreOperations(); - for (PendingOperation preOperation : preOperations) { - preOperation.run(); - } - pendingOperation.run(); - if(!pendingOperation.isVetoed()) { - List cascadeOperations = pendingOperation.getCascadeOperations(); - for (PendingOperation cascadeOperation : cascadeOperations) { - cascadeOperation.run(); - } - } - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdate.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdate.java deleted file mode 100644 index 5862b3af7..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdate.java +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core.impl; - -import org.grails.datastore.mapping.engine.EntityAccess; - -/** - * An update that is pending execution in a flush() operation - * - * @param The native entry to persist - * @param The native key - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface PendingUpdate extends Runnable, PendingOperation{ - /** - * @return The EntityAccess object for the entity to be inserted - */ - EntityAccess getEntityAccess(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdateAdapter.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdateAdapter.java deleted file mode 100644 index a998b4563..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdateAdapter.java +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (C) 2010 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.mapping.core.impl; - -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Provides a default implementation for the {@link PendingUpdate} interface - * - * @param The native entry to persist - * - * @author Graeme Rocher - * @since 1.0 - */ -public abstract class PendingUpdateAdapter extends PendingOperationAdapter implements PendingUpdate{ - - private EntityAccess entityAccess; - - private boolean vetoed; - - public PendingUpdateAdapter(PersistentEntity entity, K nativeKey, E nativeEntry, EntityAccess ea) { - super(entity, nativeKey, nativeEntry); - this.entityAccess = ea; - } - - public boolean isVetoed() { - return vetoed; - } - - public void setVetoed(boolean vetoed) { - this.vetoed = vetoed; - } - - public EntityAccess getEntityAccess() { - return entityAccess; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy deleted file mode 100644 index 3cd0c165f..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package org.grails.datastore.mapping.dirty.checking - -/** - * Interface to classes that are able to track changes to their internal state. - * - * - * @author Graeme Rocher - * @since 2.0 - */ -public interface DirtyCheckable { - - /** - * Indicates that the instance should start tacking changes. Note that if the instance is dirty this will clear any previously tracked - * changes - */ - void trackChanges() - - /** - * @return True if the instance has any changes - */ - boolean hasChanged() - - /** - * @param propertyName The name of the property - * @return True if the given property has any changes - */ - boolean hasChanged(String propertyName) - - /** - * Marks this instance as dirty - */ - void markDirty() - - /** - * Marks the given property name as dirty - * @param propertyName The property name - */ - void markDirty(String propertyName) - - /** - * @return A list of the dirty property names - */ - List listDirtyPropertyNames() - - /** - * Returns the original value of the property prior to when {@link #trackChanges()} was called - * - * @param propertyName The property name - * @return The original value - */ - Object getOriginalValue(String propertyName) -} \ No newline at end of file diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSupport.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSupport.groovy deleted file mode 100644 index 029d8cda2..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSupport.groovy +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.dirty.checking - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.collection.PersistentCollection -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.model.types.Association -import org.grails.datastore.mapping.model.types.ToOne -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher - -/** - * Support methods for dirty checking - * - * @author Graeme Rocher - * @since 2.0 - */ -@CompileStatic -class DirtyCheckingSupport { - - /** - * Checks whether associations are dirty - * - * @param session The session - * @param entity The entity - * @param instance The instance - * @return True if they are - */ - static boolean areAssociationsDirty(Session session, PersistentEntity entity, Object instance) { - if(!instance) return false - - final proxyFactory = session.mappingContext.proxyFactory - final cpf = ClassPropertyFetcher.forClass(instance.getClass()) - - final associations = entity.associations - for(Association a in associations) { - final isOwner = a.isOwningSide() || (a.bidirectional && !a.inverseSide?.owningSide) - if(isOwner) { - if(a instanceof ToOne) { - final value = cpf.getPropertyValue(instance, a.name) - if(proxyFactory.isInitialized(value)) { - if(value instanceof DirtyCheckingSupport) { - DirtyCheckable dirtyCheckable = (DirtyCheckable) value - if(dirtyCheckable.hasChanged()) { - return true - } - } - } - } - else { - final value = cpf.getPropertyValue(instance, a.name) - if(value instanceof PersistentCollection) { - PersistentCollection coll = (PersistentCollection)value - if(coll.isInitialized()) { - if(coll.isDirty()) return true - } - } - } - - } - } - return false - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/DocumentDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/DocumentDatastore.java deleted file mode 100644 index 401c5d0e0..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/DocumentDatastore.java +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (C) 2010 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.mapping.document; - -import org.grails.datastore.mapping.core.Datastore; - -/** - * @author Guillaume Laforge - */ -public interface DocumentDatastore extends Datastore {} \ No newline at end of file diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/Attribute.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/Attribute.java deleted file mode 100644 index 8bb036942..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/Attribute.java +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2010 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.mapping.document.config; - -import org.grails.datastore.mapping.config.Property; - -/** - * Configures how a Java property maps to a Document attribute - * - * @author Graeme Rocher - */ -public class Attribute extends Property { - - public void setAttr(String name) { - setTargetName(name); - } - - public void setAttribute(String name) { - setTargetName(name); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/Collection.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/Collection.java deleted file mode 100644 index 9a3a6ba2a..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/Collection.java +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (C) 2010 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.mapping.document.config; - -import org.grails.datastore.mapping.config.Entity; - -/** - * Configures how an entity is mapped onto a Document collection - * - * @author Graeme Rocher - */ -public class Collection extends Entity{ - - private String name; - - /** - * The name of the collection - * @return The name of the collection - */ - public String getCollection() { - return name; - } - - /** - * Sets the name of the collection - * @param name The name of the collection - */ - public void setCollection(String name) { - this.name = name; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentMappingContext.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentMappingContext.java deleted file mode 100644 index 8f388fb94..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentMappingContext.java +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (C) 2010 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.mapping.document.config; - -import groovy.lang.Closure; -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 org.springframework.util.Assert; - -/** - * Models a {@link org.grails.datastore.mapping.model.MappingContext} for a Document store. - * - * @author Graeme Rocher - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class DocumentMappingContext extends AbstractMappingContext { - String defaultDatabaseName; - MappingFactory mappingFactory; - - private MappingConfigurationStrategy syntaxStrategy; - private Closure defaultMapping; - - public DocumentMappingContext(String defaultDatabaseName) { - Assert.notNull(defaultDatabaseName, "Argument [defaultDatabaseName] cannot be null"); - this.defaultDatabaseName = defaultDatabaseName; - mappingFactory = createDocumentMappingFactory(null); - syntaxStrategy = new GormMappingConfigurationStrategy(mappingFactory); - } - public DocumentMappingContext(String defaultDatabaseName, Closure defaultMapping) { - Assert.notNull(defaultDatabaseName, "Argument [defaultDatabaseName] cannot be null"); - this.defaultDatabaseName = defaultDatabaseName; - mappingFactory = createDocumentMappingFactory(defaultMapping); - this.defaultMapping = defaultMapping; - syntaxStrategy = new GormMappingConfigurationStrategy(mappingFactory); - } - - public Closure getDefaultMapping() { - return defaultMapping; - } - - protected MappingFactory createDocumentMappingFactory(Closure defaultMapping) { - GormDocumentMappingFactory gormDocumentMappingFactory = new GormDocumentMappingFactory(); - gormDocumentMappingFactory.setDefaultMapping(defaultMapping); - return gormDocumentMappingFactory; - } - - public String getDefaultDatabaseName() { - return defaultDatabaseName; - } - - public MappingConfigurationStrategy getMappingSyntaxStrategy() { - return syntaxStrategy; - } - - @Override - public MappingFactory getMappingFactory() { - return mappingFactory; - } - - @Override - protected PersistentEntity createPersistentEntity(Class javaClass) { - return new DocumentPersistentEntity(javaClass, this); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentPersistentEntity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentPersistentEntity.java deleted file mode 100644 index 01dafdc70..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentPersistentEntity.java +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2010 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.mapping.document.config; - -import org.grails.datastore.mapping.model.AbstractClassMapping; -import org.grails.datastore.mapping.model.AbstractPersistentEntity; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.IdentityMapping; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -public class DocumentPersistentEntity extends AbstractPersistentEntity { - - private DocumentCollectionMapping classMapping; - - public DocumentPersistentEntity(@SuppressWarnings("rawtypes") Class javaClass, MappingContext context) { - super(javaClass, context); - this.classMapping = new DocumentCollectionMapping(this, context); - } - - @SuppressWarnings("unchecked") - @Override - public ClassMapping getMapping() { - return classMapping; - } - - public class DocumentCollectionMapping extends AbstractClassMapping { - private Collection mappedForm; - - private IdentityMapping identityMapping; - public DocumentCollectionMapping(PersistentEntity entity, MappingContext context) { - super(entity, context); - this.mappedForm = (Collection) context.getMappingFactory().createMappedForm(DocumentPersistentEntity.this); - } - @Override - public Collection getMappedForm() { - return mappedForm ; - } - - @Override - public IdentityMapping getIdentifier() { - if (identityMapping == null) { - identityMapping = context.getMappingFactory().createIdentityMapping(this); - } - return identityMapping; - } - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/GormDocumentMappingFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/GormDocumentMappingFactory.java deleted file mode 100644 index d97fe3b23..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/GormDocumentMappingFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2010 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.mapping.document.config; - -import org.grails.datastore.mapping.config.AbstractGormMappingFactory; - -public class GormDocumentMappingFactory extends AbstractGormMappingFactory { - - @Override - protected Class getPropertyMappedFormType() { - return Attribute.class; - } - - @Override - protected Class getEntityMappedFormType() { - return Collection.class; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/AssociationIndexer.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/AssociationIndexer.java deleted file mode 100644 index ac5107647..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/AssociationIndexer.java +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (C) 2010 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.mapping.engine; - -import java.util.List; - -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Responsible for creating indices for associations used in queries. - * - * An instance may be specific to a particular association of a particular native instance of an entity (the parent - * of the association). - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface AssociationIndexer { - - /** - * Creates an index queryable via the primary key. This is called *before* the entity that this association - * indexer is part of is persisted, but after the native entry has been updated ready to be persisted. - * This allows the index to be placed in the native instance itself, e.g. in a document database. - * - * Usually, for a particular association type, only this OR {@link #index(Object, java.util.List)} will be - * implemented. - * @param primaryKey The primary key - * @param foreignKeys The foreign keys - */ - void preIndex(K primaryKey, List foreignKeys); - - /** - * Creates an index queryable via the primary key. This is called *after* the entity this association indexer - * is part of has been persisted. - * - * Usually, for a particular association type, only this OR {@link #preIndex(Object, java.util.List)} will be - * implemented. - * @param primaryKey The primary key - * @param foreignKeys The foreign keys - */ - void index(K primaryKey, List foreignKeys); - - /** - * Queries the given primary key and returns the foreign keys - * - * @param primaryKey The primary key - * @return The foreign keys - */ - List query(K primaryKey); - - PersistentEntity getIndexedEntity(); - - /** - * Index a single foreign key - * @param primaryKey The primaryKey - * @param foreignKey The foreignKey - */ - void index(T primaryKey, K foreignKey); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityAccess.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityAccess.java deleted file mode 100644 index dd34d35de..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityAccess.java +++ /dev/null @@ -1,141 +0,0 @@ -/* Copyright (C) 2010 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.mapping.engine; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.PropertyAccessorFactory; -import org.springframework.core.convert.ConversionService; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.IdentityMapping; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.springframework.util.ReflectionUtils; - -/** - * Class used to access properties of an entity. Also responsible for - * any conversion from source to target types. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class EntityAccess { - - private static final Set EXCLUDED_PROPERTIES = new HashSet(Arrays.asList("class", "metaClass")); - - protected Object entity; - protected BeanWrapper beanWrapper; - protected PersistentEntity persistentEntity; - - public EntityAccess(PersistentEntity persistentEntity, Object entity) { - this.entity = entity; - this.persistentEntity = persistentEntity; - beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(entity); - } - - public Object getEntity() { - return entity; - } - - public void setConversionService(ConversionService conversionService) { - beanWrapper.setConversionService(conversionService); - } - - public Object getProperty(String name) { - return beanWrapper.getPropertyValue(name); - } - - public Class getPropertyType(String name) { - return beanWrapper.getPropertyType(name); - } - - public void setProperty(String name, Object value) { - if(value == null) { - Class type = getPropertyType(name); - if(!type.isPrimitive()) { - beanWrapper.setPropertyValue(name, value); - } - } - else { - beanWrapper.setPropertyValue(name, value); - } - - } - - public Object getIdentifier() { - String idName = getIdentifierName(persistentEntity.getMapping()); - if (idName != null) { - return getProperty(idName); - } - return getProperty(persistentEntity.getIdentity().getName()); - } - - public void setIdentifier(Object id) { - String idName = getIdentifierName(persistentEntity.getMapping()); - setProperty(idName, id); - } - - protected String getIdentifierName(ClassMapping cm) { - final IdentityMapping identifier = cm.getIdentifier(); - if (identifier != null && identifier.getIdentifierName() != null) { - return identifier.getIdentifierName()[0]; - } - return null; - } - - public String getIdentifierName() { - return getIdentifierName(persistentEntity.getMapping()); - } - - public PersistentEntity getPersistentEntity() { - return persistentEntity; - } - - public void setPropertyNoConversion(String name, Object value) { - final PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(name); - if (pd == null) { - return; - } - final Method writeMethod = pd.getWriteMethod(); - if (writeMethod != null) { - ReflectionUtils.invokeMethod(writeMethod, beanWrapper.getWrappedInstance(), value); - } - } - - /** - * Refreshes the object from entity state. - */ - public void refresh() { - final PropertyDescriptor[] descriptors = beanWrapper.getPropertyDescriptors(); - for (PropertyDescriptor descriptor : descriptors) { - final String name = descriptor.getName(); - if (EXCLUDED_PROPERTIES.contains(name)) { - continue; - } - - if (!beanWrapper.isReadableProperty(name) || !beanWrapper.isWritableProperty(name)) { - continue; - } - - Object newValue = getProperty(name); - setProperty(name, newValue); - } - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityPersister.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityPersister.java deleted file mode 100644 index 5a0934144..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityPersister.java +++ /dev/null @@ -1,357 +0,0 @@ -/* Copyright (C) 2010 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.mapping.engine; - -import java.io.Serializable; -import java.sql.Timestamp; -import java.util.Date; -import java.util.List; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.event.PostDeleteEvent; -import org.grails.datastore.mapping.engine.event.PostInsertEvent; -import org.grails.datastore.mapping.engine.event.PostLoadEvent; -import org.grails.datastore.mapping.engine.event.PostUpdateEvent; -import org.grails.datastore.mapping.engine.event.PreDeleteEvent; -import org.grails.datastore.mapping.engine.event.PreInsertEvent; -import org.grails.datastore.mapping.engine.event.PreLoadEvent; -import org.grails.datastore.mapping.engine.event.PreUpdateEvent; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.proxy.ProxyFactory; -import org.springframework.context.ApplicationEventPublisher; - -/** - * A {@link org.grails.datastore.mapping.engine.Persister} specifically for persisting PersistentEntity instances. - * - * @author Graeme Rocher - * @since 1.0 - */ -public abstract class EntityPersister implements Persister { - private PersistentEntity persistentEntity; - private MappingContext mappingContext; - protected Session session; - protected org.grails.datastore.mapping.proxy.ProxyFactory proxyFactory; - protected ApplicationEventPublisher publisher; - - public EntityPersister(MappingContext mappingContext, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher) { - this.persistentEntity = entity; - this.mappingContext = mappingContext; - this.session = session; - this.publisher = publisher; - } - - public Session getSession() { - return session; - } - - @SuppressWarnings("unchecked") - public Object proxy(Serializable key) { - return getProxyFactory().createProxy(session, getPersistentEntity().getJavaClass(), key); - } - - public ProxyFactory getProxyFactory() { - if (proxyFactory == null) { - proxyFactory = mappingContext.getProxyFactory(); - } - return proxyFactory; - } - - /** - * @return The MappingContext instance - */ - public MappingContext getMappingContext() { - return mappingContext; - } - - /** - * @return The PersistentEntity instance - */ - public PersistentEntity getPersistentEntity() { - return persistentEntity; - } - - @SuppressWarnings("rawtypes") - public Class getType() { - return persistentEntity.getJavaClass(); - } - - /** - * Obtains an objects identifer - * @param obj The object - * @return The identifier or null if it doesn't have one - */ - public Serializable getObjectIdentifier(Object obj) { - if (obj == null) return null; - final ProxyFactory pf = getProxyFactory(); - if (pf.isProxy(obj)) { - return pf.getIdentifier(obj); - } - return (Serializable) new EntityAccess(getPersistentEntity(), obj).getIdentifier(); - } - - @Override - public Serializable insert(Object obj) { - if (!persistentEntity.isInstance(obj)) { - final Persister persister = getSession().getPersister(obj); - if (persister == null) { - throw new IllegalArgumentException("Object [" + obj + - "] is not an instance supported by the persister for class [" + - getType().getName() + "]"); - } - - return persister.persist(obj); - } - - return persistEntity(getPersistentEntity(), obj, true); - } - - /** - * Subclasses should override to support explicit inserts - * @param entity The entity - * @param obj The object - * @param isInsert Whether it is an insert - * @return The id - */ - protected Serializable persistEntity(PersistentEntity entity, Object obj, boolean isInsert) { - return persistEntity(entity, obj); - } - - /** - * Obtains an objects identifer - * @param obj The object - */ - public void setObjectIdentifier(Object obj, Serializable id) { - new EntityAccess(getPersistentEntity(), obj).setIdentifier(id); - } - - /** - * Persists an object returning the identifier - * - * @param obj The object to persist - * @return The identifer - */ - public final Serializable persist(Object obj) { - if (!persistentEntity.isInstance(obj)) { - final Persister persister = getSession().getPersister(obj); - if (persister == null) { - throw new IllegalArgumentException("Object [" + obj + - "] is not an instance supported by the persister for class [" + - getType().getName() + "]"); - } - - return persister.persist(obj); - } - - return persistEntity(getPersistentEntity(), obj); - } - - public List persist(@SuppressWarnings("rawtypes") Iterable objs) { - return persistEntities(getPersistentEntity(), objs); - } - - public List retrieveAll(Iterable keys) { - return retrieveAllEntities(getPersistentEntity(), keys); - } - - public List retrieveAll(Serializable[] keys) { - return retrieveAllEntities(getPersistentEntity(), keys); - } - - protected abstract List retrieveAllEntities(PersistentEntity pe, Serializable[] keys); - - protected abstract List retrieveAllEntities(PersistentEntity pe, Iterable keys); - - protected abstract List persistEntities(PersistentEntity pe, @SuppressWarnings("rawtypes") Iterable objs); - - public final Object retrieve(Serializable key) { - if (key == null) { - return null; - } - - PersistentEntity entity = getPersistentEntity(); - - Object o = retrieveEntity(entity, key); - if (o == null) { - return null; - } - - return o; - } - - /** - * Retrieve a PersistentEntity for the given mappingContext and key - * - * @param pe The entity - * @param key The key - * @return The object or null if it doesn't exist - */ - protected abstract Object retrieveEntity(PersistentEntity pe, Serializable key); - - /** - * Persist the given persistent entity - * - * @param pe The PersistentEntity - * @param obj - * @return The generated key - */ - protected abstract Serializable persistEntity(PersistentEntity pe, Object obj); - - public final void delete(@SuppressWarnings("rawtypes") Iterable objects) { - if (objects == null) { - return; - } - - deleteEntities(getPersistentEntity(), objects); - } - - public void delete(Object obj) { - if (obj == null) { - return; - } - - deleteEntity(getPersistentEntity(), obj); - } - - protected abstract void deleteEntity(PersistentEntity pe, Object obj); - - protected abstract void deleteEntities(PersistentEntity pe, @SuppressWarnings("rawtypes") Iterable objects); - - protected EntityAccess createEntityAccess(PersistentEntity pe, Object obj) { - return new EntityAccess(persistentEntity, obj); - } - - protected Object newEntityInstance(PersistentEntity persistentEntity) { - Object o = persistentEntity.newInstance(); - publisher.publishEvent(new PreLoadEvent(session.getDatastore(), getPersistentEntity(), - new EntityAccess(persistentEntity, o))); - return o; - } - - /** - * Fire the beforeInsert even on an entityAccess object and return true if the operation should be cancelled - * @param persistentEntity The entity - * @param entityAccess The entity access - * @return true if the operation should be cancelled - */ - public boolean cancelInsert(final PersistentEntity persistentEntity, final EntityAccess entityAccess) { - PreInsertEvent event = new PreInsertEvent(session.getDatastore(), persistentEntity, entityAccess); - publisher.publishEvent(event); - return event.isCancelled(); - } - - public void firePostInsertEvent(final PersistentEntity persistentEntity, final EntityAccess entityAccess) { - publisher.publishEvent(new PostInsertEvent( - session.getDatastore(), persistentEntity, entityAccess)); - } - - /** - * Fire the beforeUpdate event on an entityAccess object and return true if the operation should be cancelled - * @param persistentEntity The entity - * @param entityAccess The entity access - * @return true if the operation should be cancelled - */ - public boolean cancelUpdate(final PersistentEntity persistentEntity, final EntityAccess entityAccess) { - PreUpdateEvent event = new PreUpdateEvent(session.getDatastore(), persistentEntity, entityAccess); - publisher.publishEvent(event); - return event.isCancelled(); - } - - /** - * Fire the beforeDelete event on an entityAccess object and return true if the operation should be cancelled - * @param persistentEntity The entity - * @param entityAccess The entity access - * @return true if the operation should be cancelled - */ - public boolean cancelDelete( final PersistentEntity persistentEntity, final EntityAccess entityAccess) { - PreDeleteEvent event = new PreDeleteEvent(session.getDatastore(), persistentEntity, entityAccess); - publisher.publishEvent(event); - return event.isCancelled(); - } - - /** - * Fire the beforeDelete event on an entityAccess object and return true if the operation should be cancelled - * @param persistentEntity The entity - * @param entityAccess The entity access - * @return true if the operation should be cancelled - */ - public boolean cancelLoad( final PersistentEntity persistentEntity, final EntityAccess entityAccess) { - PreDeleteEvent event = new PreDeleteEvent(session.getDatastore(), persistentEntity, entityAccess); - publisher.publishEvent(event); - return event.isCancelled(); - } - - public void firePostUpdateEvent(final PersistentEntity persistentEntity, final EntityAccess entityAccess) { - publisher.publishEvent(new PostUpdateEvent( - session.getDatastore(), persistentEntity, entityAccess)); - } - - public void firePostDeleteEvent(final PersistentEntity persistentEntity, final EntityAccess entityAccess) { - publisher.publishEvent(new PostDeleteEvent( - session.getDatastore(), persistentEntity, entityAccess)); - } - - public void firePreLoadEvent(final PersistentEntity persistentEntity, final EntityAccess entityAccess) { - publisher.publishEvent(new PreLoadEvent( - session.getDatastore(), persistentEntity, entityAccess)); - } - - public void firePostLoadEvent(final PersistentEntity persistentEntity, final EntityAccess entityAccess) { - publisher.publishEvent(new PostLoadEvent( - session.getDatastore(), persistentEntity, entityAccess)); - } - - protected boolean isVersioned(final EntityAccess ea) { - - if (!ea.getPersistentEntity().isVersioned()) { - return false; - } - - Class type = ea.getPropertyType("version"); - return Number.class.isAssignableFrom(type) || Date.class.isAssignableFrom(type); - } - - protected void incrementVersion(final EntityAccess ea) { - if (Number.class.isAssignableFrom(ea.getPropertyType("version"))) { - Number currentVersion = (Number) ea.getProperty("version"); - if (currentVersion == null) { - currentVersion = 0L; - } - ea.setProperty("version", currentVersion.longValue() + 1); - } - else { - setDateVersion(ea); - } - } - - protected void setVersion(final EntityAccess ea) { - if (Number.class.isAssignableFrom(ea.getPropertyType("version"))) { - ea.setProperty("version", 0); - } - else { - setDateVersion(ea); - } - } - - protected void setDateVersion(final EntityAccess ea) { - if (Timestamp.class.isAssignableFrom(ea.getPropertyType("version"))) { - ea.setProperty("version", new Timestamp(System.currentTimeMillis())); - } - else { - ea.setProperty("version", new Date()); - } - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/LockableEntityPersister.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/LockableEntityPersister.java deleted file mode 100644 index bbf5bc95a..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/LockableEntityPersister.java +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (C) 2010 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.mapping.engine; - -import java.io.Serializable; - -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.dao.CannotAcquireLockException; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Abstract base class for entity persisters that support locking. - * - * @author Graeme Rocher - * @since 1.0 - */ -public abstract class LockableEntityPersister extends EntityPersister { - - public static int DEFAULT_TIMEOUT = 30; - - public LockableEntityPersister(MappingContext mappingContext, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher) { - super(mappingContext, entity, session, publisher); - } - - /** - * Locks an object for the given identifier returning the locked instance - * - * @param id The identifier - * @return The locked object - * @throws CannotAcquireLockException Thrown if a lock couldn't be acquired before the default timeout elapsed - */ - public abstract Object lock(Serializable id) throws CannotAcquireLockException; - - /** - * Acquire a lock using the given identifier and timeout delay - * @param id the identifier - * @param timeout the amount of time to wait before giving up in seconds - * @return The locked object - * @throws CannotAcquireLockException - */ - public abstract Object lock(Serializable id, int timeout) throws CannotAcquireLockException; - - /** - * Return whether an object is locked or not - * @param o The object - * @return True if it is locked - */ - public abstract boolean isLocked(Object o); - - /** - * Unlocks a locked object - * @param o The object to unlock - */ - public abstract void unlock(Object o); - - @Override - @SuppressWarnings("unchecked") - public Object proxy(Serializable key) { - return getProxyFactory().createProxy(session, getPersistentEntity().getJavaClass(), key); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/NativeEntryEntityPersister.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/NativeEntryEntityPersister.java deleted file mode 100755 index cadc6ccbb..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/NativeEntryEntityPersister.java +++ /dev/null @@ -1,1812 +0,0 @@ -/* Copyright (C) 2010 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.mapping.engine; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; - -import javax.persistence.CascadeType; -import javax.persistence.FetchType; -import javax.persistence.FlushModeType; - -import org.grails.datastore.mapping.cache.TPCacheAdapter; -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; -import org.grails.datastore.mapping.collection.AbstractPersistentCollection; -import org.grails.datastore.mapping.collection.PersistentCollection; -import org.grails.datastore.mapping.collection.PersistentList; -import org.grails.datastore.mapping.collection.PersistentSet; -import org.grails.datastore.mapping.collection.PersistentSortedSet; -import org.grails.datastore.mapping.config.Property; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.core.SessionImplementor; -import org.grails.datastore.mapping.core.impl.PendingInsert; -import org.grails.datastore.mapping.core.impl.PendingInsertAdapter; -import org.grails.datastore.mapping.core.impl.PendingOperation; -import org.grails.datastore.mapping.core.impl.PendingOperationAdapter; -import org.grails.datastore.mapping.core.impl.PendingOperationExecution; -import org.grails.datastore.mapping.core.impl.PendingUpdate; -import org.grails.datastore.mapping.core.impl.PendingUpdateAdapter; -import org.grails.datastore.mapping.dirty.checking.DirtyCheckable; -import org.grails.datastore.mapping.engine.event.PreDeleteEvent; -import org.grails.datastore.mapping.engine.internal.MappingUtils; -import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.EmbeddedPersistentEntity; -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.PropertyMapping; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.model.types.Basic; -import org.grails.datastore.mapping.model.types.Custom; -import org.grails.datastore.mapping.model.types.Embedded; -import org.grails.datastore.mapping.model.types.EmbeddedCollection; -import org.grails.datastore.mapping.model.types.ManyToMany; -import org.grails.datastore.mapping.model.types.OneToMany; -import org.grails.datastore.mapping.model.types.Simple; -import org.grails.datastore.mapping.model.types.ToOne; -import org.grails.datastore.mapping.proxy.ProxyFactory; -import org.grails.datastore.mapping.query.Query; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.core.convert.ConversionService; -import org.springframework.dao.CannotAcquireLockException; - -/** - * Provides an implementation of the {@link org.grails.datastore.mapping.engine.EntityPersister} class that - * reads and writes against a native datastore type specified by the generic type parameter T - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"unused", "rawtypes", "unchecked"}) -public abstract class NativeEntryEntityPersister extends LockableEntityPersister { - protected ClassMapping classMapping; - protected TPCacheAdapterRepository cacheAdapterRepository; - - public NativeEntryEntityPersister(MappingContext mappingContext, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher) { - super(mappingContext, entity, session, publisher); - classMapping = entity.getMapping(); - } - - public NativeEntryEntityPersister(MappingContext mappingContext, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher, TPCacheAdapterRepository cacheAdapterRepository) { - super(mappingContext, entity, session, publisher); - classMapping = entity.getMapping(); - this.cacheAdapterRepository = cacheAdapterRepository; - } - - public abstract String getEntityFamily(); - - public ClassMapping getClassMapping() { - return classMapping; - } - - /** - * Subclasses should override to optimize away manual property indexing if it is not required - * - * @return True if property indexing is required (the default) - */ - protected boolean doesRequirePropertyIndexing() { return true; } - - @Override - protected void deleteEntity(PersistentEntity persistentEntity, Object obj) { - if (obj == null) { - return; - } - - EntityAccess entityAccess = createEntityAccess(persistentEntity, obj); - PreDeleteEvent event = new PreDeleteEvent(session.getDatastore(), persistentEntity, entityAccess); - publisher.publishEvent(event); - if (event.isCancelled()) { - return; - } - - final K key = readIdentifierFromObject(obj); - if (key == null) { - return; - } - - FlushModeType flushMode = session.getFlushMode(); - try { - session.setFlushMode(FlushModeType.COMMIT); - cascadeBeforeDelete(persistentEntity, entityAccess, key, obj); - deleteEntry(getEntityFamily(), key, obj); - cascadeAfterDelete(persistentEntity, entityAccess, key, obj); - } - finally { - session.setFlushMode(flushMode); - } - - firePostDeleteEvent(persistentEntity, entityAccess); - } - - protected void cascadeDeleteCollection(EntityAccess entityAccess, Association association) { - Object propValue = entityAccess.getProperty(association.getName()); - if (!(propValue instanceof Collection)) { - return; - } - Collection collection = ((Collection) propValue); - for (Iterator iter = collection.iterator(); iter.hasNext(); ) { - Object child = iter.next(); - deleteEntity(getMappingContext().getPersistentEntity(child.getClass().getName()), child); - iter.remove(); - } - } - - @Override - protected EntityAccess createEntityAccess(PersistentEntity persistentEntity, Object obj) { - EntityAccess entityAccess = new EntityAccess(persistentEntity, obj); - entityAccess.setConversionService(getMappingContext().getConversionService()); - return entityAccess; - } - - protected EntityAccess createEntityAccess(PersistentEntity persistentEntity, Object obj, final T nativeEntry) { - final NativeEntryModifyingEntityAccess ea = new NativeEntryModifyingEntityAccess(persistentEntity, obj); - ea.setConversionService(getMappingContext().getConversionService()); - ea.setNativeEntry(nativeEntry); - return ea; - } - - /** - * Deletes a single entry - * - * @param family The family - * @param key The key - * @param entry the entry - */ - protected abstract void deleteEntry(String family, K key, Object entry); - - /** - * Delete collections before owner delete. - */ - protected void cascadeBeforeDelete(PersistentEntity persistentEntity, EntityAccess entityAccess, - K key, Object instance) { - - List props = persistentEntity.getPersistentProperties(); - for (PersistentProperty prop : props) { - String propertyKey = getPropertyKey(prop); - - if (prop instanceof OneToMany) { - OneToMany oneToMany = (OneToMany)prop; - if (oneToMany.isOwningSide() && oneToMany.doesCascade(CascadeType.REMOVE)) { - if (Collection.class.isAssignableFrom(oneToMany.getType())) { - cascadeDeleteCollection(entityAccess, oneToMany); - } - } - } - else if (prop instanceof ManyToMany) { - ManyToMany manyToMany = (ManyToMany)prop; - if (manyToMany.isOwningSide() && manyToMany.doesCascade(CascadeType.REMOVE)) { - Object propValue = entityAccess.getProperty(manyToMany.getName()); - if (Collection.class.isAssignableFrom(manyToMany.getType())) { - cascadeDeleteCollection(entityAccess, manyToMany); - } - } - } - } - } - - /** - * Delete many-to-ones after owner delete. - */ - protected void cascadeAfterDelete(PersistentEntity persistentEntity, EntityAccess entityAccess, - K key, Object instance) { - - List props = persistentEntity.getPersistentProperties(); - for (PersistentProperty prop : props) { - String propertyKey = getPropertyKey(prop); - if (prop instanceof Basic) { - Object propValue = entityAccess.getProperty(prop.getName()); - } - else if (prop instanceof OneToMany) { - OneToMany oneToMany = (OneToMany)prop; - if (oneToMany.isOwningSide() && oneToMany.doesCascade(CascadeType.REMOVE)) { - if (Collection.class.isAssignableFrom(oneToMany.getType())) { - cascadeDeleteCollection(entityAccess, oneToMany); - } - } - } - else if (prop instanceof ToOne) { - ToOne association = (ToOne) prop; - if (!(prop instanceof Embedded) && !(prop instanceof EmbeddedCollection) && - association.doesCascade(CascadeType.REMOVE)) { - if (association.isOwningSide()) { - Object value = entityAccess.getProperty(association.getName()); - if (value != null) { - Persister persister = session.getPersister(value); - if (persister != null) { - persister.delete(value); - } - } - } - } - } - } - } - - @Override - protected final void deleteEntities(PersistentEntity persistentEntity, Iterable objects) { - if (objects != null) { - final Set keys = new LinkedHashSet(); - final List deleteList = new ArrayList(); - for (Object object : objects) { - K key = readIdentifierFromObject(object); - if (key != null) { - if (!keys.contains(key)) { - if (!cancelDelete(persistentEntity, createEntityAccess(persistentEntity, object))) { - // only delete if not cancelled - keys.add(key); - deleteList.add(object); - } - } - } - } - - if (!keys.isEmpty()) { - deleteEntries(getEntityFamily(), new ArrayList(keys)); - for (Object object : deleteList) { - firePostDeleteEvent(persistentEntity, createEntityAccess(persistentEntity, object)); - } - } - } - } - - protected K readIdentifierFromObject(Object object) { - EntityAccess access = createEntityAccess(getPersistentEntity(), object); - - final Object idValue = access.getIdentifier(); - Object key = null; - if (idValue != null) { - key = inferNativeKey(getEntityFamily(), idValue); - } - return (K) key; - } - - @Override - public final Object lock(Serializable id) throws CannotAcquireLockException { - return lock(id, DEFAULT_TIMEOUT); - } - - @Override - public final Object lock(Serializable id, int timeout) throws CannotAcquireLockException { - lockEntry(getPersistentEntity(), getEntityFamily(), id, timeout); - return retrieve(id); - } - - /** - * Subclasses can override to provide locking semantics - * - * @param persistentEntity The PesistentEntity instnace - * @param entityFamily The family - * @param id The identifer - * @param timeout The lock timeout in seconds - */ - protected void lockEntry(PersistentEntity persistentEntity, String entityFamily, Serializable id, int timeout) { - // do nothing, - } - - /** - * Subclasses can override to provide locking semantics - * - * @param o The object - * @return True if the object is locked - */ - @Override - public boolean isLocked(Object o) { - return false; - } - - @Override - public void unlock(Object o) { - unlockEntry(getPersistentEntity(), getEntityFamily(), (Serializable) createEntityAccess(getPersistentEntity(), o).getIdentifier()); - } - - /** - * Subclasses to override to provide locking semantics - * @param persistentEntity The persistent entity - * @param entityFamily The entity family - * @param id The identifer - */ - protected void unlockEntry(PersistentEntity persistentEntity, String entityFamily, Serializable id) { - // do nothing - } - - @Override - protected final Object retrieveEntity(PersistentEntity persistentEntity, Serializable nativeKey) { - - final Serializable key = convertToNativeKey(nativeKey); - T nativeEntry = getFromTPCache(persistentEntity, nativeKey); - if (nativeEntry == null) { - nativeEntry = retrieveEntry(persistentEntity, getEntityFamily(), key); - if (nativeEntry == null) { - return null; - } - } - - return createObjectFromNativeEntry(persistentEntity, key, nativeEntry); - } - - /** - * Subclasses should override to provide any conversion necessary to convert to a nativeKey - * - * @param nativeKey The key - * @return The native key - */ - protected Serializable convertToNativeKey(Serializable nativeKey) { - return nativeKey; - } - - public Serializable refresh(Object o) { - final PersistentEntity entity = getPersistentEntity(); - EntityAccess ea = createEntityAccess(entity, o); - - Serializable identifier = (Serializable) ea.getIdentifier(); - if (identifier == null) { - return null; - } - - final T entry = retrieveEntry(entity, getEntityFamily(), identifier); - refreshObjectStateFromNativeEntry(entity, o, identifier, entry, false); - return identifier; - } - - public Object createObjectFromNativeEntry(PersistentEntity persistentEntity, Serializable nativeKey, T nativeEntry) { - persistentEntity = discriminatePersistentEntity(persistentEntity, nativeEntry); - - cacheNativeEntry(persistentEntity, nativeKey, nativeEntry); - - Object obj = newEntityInstance(persistentEntity); - refreshObjectStateFromNativeEntry(persistentEntity, obj, nativeKey, nativeEntry, false); - return obj; - } - - public Object createObjectFromEmbeddedNativeEntry(PersistentEntity persistentEntity, T nativeEntry) { - persistentEntity = discriminatePersistentEntity(persistentEntity, nativeEntry); - Object obj = newEntityInstance(persistentEntity); - refreshObjectStateFromNativeEntry(persistentEntity, obj, null, nativeEntry, true); - return obj; - } - - protected void cacheNativeEntry(PersistentEntity persistentEntity, - Serializable nativeKey, T nativeEntry) { - SessionImplementor si = (SessionImplementor) session; - Serializable key = (Serializable) getMappingContext().getConversionService().convert( - nativeKey, persistentEntity.getIdentity().getType()); - si.cacheEntry(persistentEntity, key, nativeEntry); - } - - protected void refreshObjectStateFromNativeEntry(PersistentEntity persistentEntity, Object obj, - Serializable nativeKey, T nativeEntry) { - refreshObjectStateFromNativeEntry(persistentEntity, obj, nativeKey, nativeEntry, false); - } - protected void refreshObjectStateFromNativeEntry(PersistentEntity persistentEntity, Object obj, - Serializable nativeKey, T nativeEntry, boolean isEmbedded) { - EntityAccess ea = createEntityAccess(persistentEntity, obj, nativeEntry); - ea.setConversionService(getMappingContext().getConversionService()); - if (!(persistentEntity instanceof EmbeddedPersistentEntity)) { - String idName = ea.getIdentifierName(); - ea.setProperty(idName, nativeKey); - } - - final List props = persistentEntity.getPersistentProperties(); - for (final PersistentProperty prop : props) { - String propKey = getNativePropertyKey(prop); - if (prop instanceof Simple) { - // this magically converts most types to the correct property type, using bean converters. - ea.setProperty(prop.getName(), getEntryValue(nativeEntry, propKey)); - } - else if (prop instanceof Basic) { - Object entryValue = getEntryValue(nativeEntry, propKey); - entryValue = convertBasicEntryValue(persistentEntity, prop, entryValue); - ea.setProperty(prop.getName(), entryValue); - } - else if (prop instanceof Custom) { - handleCustom(prop, ea, nativeEntry); - } - else if (prop instanceof ToOne) { - if (prop instanceof Embedded) { - Embedded embedded = (Embedded) prop; - if(embedded.getAssociatedEntity() != null) { - - T embeddedEntry = getEmbedded(nativeEntry, propKey); - - if (embeddedEntry != null) { - Object embeddedInstance = - createObjectFromEmbeddedNativeEntry(embedded.getAssociatedEntity(), embeddedEntry); - ea.setProperty(propKey, embeddedInstance); - Association inverseSide = embedded.getInverseSide(); - if (embedded.isBidirectional() && inverseSide != null) { - // fix up the owner link - EntityAccess embeddedEa = - createEntityAccess(embedded.getAssociatedEntity(), embeddedInstance); - embeddedEa.setProperty(inverseSide.getName(), obj); - } - } - } - } - else { - ToOne association = (ToOne) prop; - - Serializable tmp = null; - if (!association.isForeignKeyInChild()) { - tmp = (Serializable) getEntryValue(nativeEntry, propKey); - } - else { - if (association.isBidirectional() && association.getAssociatedEntity() != null) { - - Query query = session.createQuery(association.getAssociatedEntity().getJavaClass()); - query.eq(association.getInverseSide().getName(), obj) - .projections().id(); - - tmp = (Serializable) query.singleResult(); - } - else { - // TODO: handle unidirectional? - } - } - - if (isEmbeddedEntry(tmp)) { - PersistentEntity associatedEntity = ((ToOne) prop).getAssociatedEntity(); - associatedEntity = discriminatePersistentEntity(associatedEntity, (T) tmp); - Object instance = newEntityInstance(associatedEntity); - refreshObjectStateFromNativeEntry(associatedEntity,instance, null, (T) tmp, false); - ea.setProperty(prop.getName(), instance); - } - else if (tmp != null && !prop.getType().isInstance(tmp)) { - PersistentEntity associatedEntity = association.getAssociatedEntity(); - if(associatedEntity != null) { - final Serializable associationKey = (Serializable) getMappingContext().getConversionService().convert( - tmp, associatedEntity.getIdentity().getType()); - if (associationKey != null) { - - PropertyMapping associationPropertyMapping = prop.getMapping(); - boolean isLazy = isLazyAssociation(associationPropertyMapping); - - final Class propType = prop.getType(); - Object value = isLazy ? - session.proxy(propType, associationKey) : - session.retrieve(propType, associationKey); - ea.setProperty(prop.getName(), value); - } - } - } - } - } - else if (prop instanceof EmbeddedCollection) { - final Object embeddedInstances = getEntryValue(nativeEntry, propKey); - EmbeddedCollection embeddedCollection = (EmbeddedCollection) prop; - loadEmbeddedCollection(embeddedCollection, ea, embeddedInstances, propKey); - Association inverseSide = embeddedCollection.getInverseSide(); - if (embeddedCollection.isBidirectional() && inverseSide != null) { - // fix up the inverse link - Object loadedInstances = ea.getProperty(embeddedCollection.getName()); - if (loadedInstances instanceof Collection) { - Collection embeddedInstancesCollection = (Collection) loadedInstances; - for (Object embeddedInstance : embeddedInstancesCollection) { - if (embeddedInstance != null) { - EntityAccess embeddedEa = - createEntityAccess(embeddedCollection.getAssociatedEntity(), embeddedInstance); - embeddedEa.setProperty(inverseSide.getName(), obj); - } - } - } - } - } - else if (prop instanceof OneToMany) { - Association association = (Association) prop; - PropertyMapping associationPropertyMapping = association.getMapping(); - - if (isEmbedded) { - List keys = loadEmbeddedCollectionKeys((Association) prop, ea, nativeEntry); - if (List.class.isAssignableFrom(association.getType())) { - ea.setPropertyNoConversion(association.getName(), - new PersistentList(keys, association.getAssociatedEntity().getJavaClass(), session)); - } - else if (Set.class.isAssignableFrom(association.getType())) { - ea.setPropertyNoConversion(association.getName(), - new PersistentSet(keys, association.getAssociatedEntity().getJavaClass(), session)); - } - } - else { - boolean isLazy = isLazyAssociation(associationPropertyMapping); - AssociationIndexer indexer = getAssociationIndexer(nativeEntry, association); - nativeKey = (Serializable) getMappingContext().getConversionService().convert( - nativeKey, getPersistentEntity().getIdentity().getType()); - if (isLazy) { - if (List.class.isAssignableFrom(association.getType())) { - ea.setPropertyNoConversion(association.getName(), - new PersistentList(nativeKey, session, indexer)); - } - else if (SortedSet.class.isAssignableFrom(association.getType())) { - ea.setPropertyNoConversion(association.getName(), - new PersistentSortedSet(nativeKey, session, indexer)); - } - else if (Set.class.isAssignableFrom(association.getType())) { - ea.setPropertyNoConversion(association.getName(), - new PersistentSet(nativeKey, session, indexer)); - } - } - else { - if (indexer != null) { - List keys = indexer.query(nativeKey); - ea.setProperty(association.getName(), - session.retrieveAll(association.getAssociatedEntity().getJavaClass(), keys)); - } - } - } - } - else if (prop instanceof ManyToMany) { - ManyToMany manyToMany = (ManyToMany) prop; - PropertyMapping associationPropertyMapping = manyToMany.getMapping(); - - boolean isLazy = isLazyAssociation(associationPropertyMapping); - nativeKey = (Serializable) getMappingContext().getConversionService().convert( - nativeKey, getPersistentEntity().getIdentity().getType()); - PersistentEntity associatedEntity = manyToMany.getAssociatedEntity(); - if(associatedEntity != null) { - - Class childType = associatedEntity.getJavaClass(); - Collection cached = ((SessionImplementor)session).getCachedCollection( - persistentEntity, nativeKey, manyToMany.getName()); - if (cached == null) { - Collection collection; - if (isLazy) { - Collection keys = getManyToManyKeys(persistentEntity, obj, nativeKey, - nativeEntry, manyToMany); - if (List.class.isAssignableFrom(manyToMany.getType())) { - collection = new PersistentList(keys, childType, session); - ea.setPropertyNoConversion(manyToMany.getName(), collection); - } - else if (Set.class.isAssignableFrom(manyToMany.getType())) { - collection = new PersistentSet(keys, childType, session); - ea.setPropertyNoConversion(manyToMany.getName(), collection); - } - else { - collection = Collections.emptyList(); - } - } - else { - AssociationIndexer indexer = getAssociationIndexer(nativeEntry, manyToMany); - if (indexer == null) { - if (List.class.isAssignableFrom(manyToMany.getType())) { - collection = Collections.emptyList(); - } - else if (Set.class.isAssignableFrom(manyToMany.getType())) { - collection = Collections.emptySet(); - } - else { - collection = Collections.emptyList(); - } - } - else { - List keys = indexer.query(nativeKey); - collection = session.retrieveAll(childType, keys); - ea.setProperty(manyToMany.getName(), collection); - } - } - ((SessionImplementor)session).cacheCollection( - persistentEntity, nativeKey, collection, manyToMany.getName()); - } - else { - ea.setProperty(manyToMany.getName(), cached); - } - } - } - } - // entity is now fully loaded. - firePostLoadEvent(persistentEntity, ea); - } - - /** - * Convert a Basic (collection-style) property native entry value taken from an entity into the target property - * type. This takes into account any generic parameter types specified on the property (e.g. Collection<Locale> - * tells us to convert elements into Locale objects). If you don't specify generic properties, collection elements - * are not modified. - * - * If the target type is known from the generic parameters, the conversion process is essentially identical to that - * used for single Simple properties. - * @param persistentEntity The persistent entity - * @param prop The property in question - * @param entryValue The value of the entry - * @return The transformed entry type. - */ - protected Object convertBasicEntryValue(PersistentEntity persistentEntity, PersistentProperty prop, Object entryValue) { - // In both cases, we use a BeanWrapper to provide all possible conversions, including those from the - // ConversionService as well as standard property editor conversions, etc. - // Enums are handled automatically, as are other standard types such as Locale, URI, Integer, etc. - if (entryValue instanceof Map) { - Map nativeMap = (Map) entryValue; - LinkedHashMap targetMap = new LinkedHashMap(); - Class propertyType = prop.getType(); - Class genericType = MappingUtils.getGenericTypeForMapProperty(persistentEntity.getJavaClass(), - prop.getName(), false); - if (genericType != null) { - ConversionService conversionService = getMappingContext().getConversionService(); - for (Object o : nativeMap.entrySet()) { - Map.Entry entry = (Map.Entry) o; - String key = (String) entry.getKey(); - Object value = entry.getValue(); - value = conversionService.convert(value, genericType); - targetMap.put(key, value); - } - } else { - // just hope they don't need converting! - targetMap.putAll(nativeMap); - } - - entryValue = targetMap; - } - else if (entryValue instanceof Collection) { - Collection collection = MappingUtils.createConcreteCollection(prop.getType()); - - Class propertyType = prop.getType(); - Class genericType = MappingUtils.getGenericTypeForProperty(persistentEntity.getJavaClass(), prop.getName()); - Collection collectionValue = (Collection) entryValue; - if (genericType != null) { - ConversionService conversionService = getMappingContext().getConversionService(); - for (Object o : collectionValue) { - o = conversionService.convert(o, genericType); - collection.add(o); - } - } - else { - // just hope they don't need converting! - collection.addAll(collectionValue); - } - - entryValue = collection; - } - return entryValue; - } - - /** - * Implementors who want to support one-to-many associations embedded should implement this method - * - * @param association The association - * @param ea - * @param nativeEntry - * - * @return A list of keys loaded from the embedded instance - */ - protected List loadEmbeddedCollectionKeys(Association association, EntityAccess ea, T nativeEntry) { - // no out of the box support - return Collections.emptyList(); - } - - protected void setEmbeddedCollectionKeys(Association association, EntityAccess embeddedEntityAccess, T embeddedEntry, List keys) { - // do nothing - } - - /** - * Tests whether a native entry is an embedded entry - * - * @param entry The native entry - * @return True if it is embedded - */ - protected boolean isEmbeddedEntry(Object entry) { - return false; - } - - /** - * Implementors who want to the ability to read embedded collections should implement this method - * - * @param embeddedCollection The EmbeddedCollection instance - * @param ea The EntityAccess instance - * @param embeddedInstances The embedded instances - * @param propertyKey The property key - */ - protected void loadEmbeddedCollection(EmbeddedCollection embeddedCollection, EntityAccess ea, - Object embeddedInstances, String propertyKey) { - // no support by default for embedded collections - } - - /** - * Implementors should override to provide support for embedded objects. - * - * @param nativeEntry The native entry to read the embedded instance from - * @param key The key - * @return The native entry of the embedded instance - */ - protected T getEmbedded(T nativeEntry, String key) { - return null; - } - - private void handleCustom(PersistentProperty prop, EntityAccess ea, T nativeEntry) { - CustomTypeMarshaller customTypeMarshaller = ((Custom) prop).getCustomTypeMarshaller(); - if (!customTypeMarshaller.supports(getSession().getDatastore())) { - return; - } - - Object value = customTypeMarshaller.read(prop, nativeEntry); - ea.setProperty(prop.getName(), value); - } - - protected Collection getManyToManyKeys(PersistentEntity persistentEntity, Object obj, - Serializable nativeKey, T nativeEntry, ManyToMany manyToMany) { - return null; - } - - protected String getNativePropertyKey(PersistentProperty prop) { - PropertyMapping pm = prop.getMapping(); - String propKey = null; - if (pm.getMappedForm()!=null) { - propKey = pm.getMappedForm().getTargetName(); - } - if (propKey == null) { - propKey = prop.getName(); - } - return propKey; - } - - /** - * Subclasses should override to customize how entities in hierarchies are discriminated - * @param persistentEntity The PersistentEntity - * @param nativeEntry The native entry - * @return The discriminated entity - */ - protected PersistentEntity discriminatePersistentEntity(PersistentEntity persistentEntity, T nativeEntry) { - return persistentEntity; - } - - private boolean isLazyAssociation(PropertyMapping associationPropertyMapping) { - if (associationPropertyMapping == null) { - return true; - } - - Property kv = associationPropertyMapping.getMappedForm(); - return kv.getFetchStrategy() == FetchType.LAZY; - } - - @Override - protected Serializable persistEntity(final PersistentEntity persistentEntity, Object obj, boolean isInsert) { - T tmp = null; - ProxyFactory proxyFactory = getProxyFactory(); - // if called internally, obj can potentially be a proxy, which won't work. - obj = proxyFactory.unwrap(obj); - final NativeEntryModifyingEntityAccess entityAccess = (NativeEntryModifyingEntityAccess) createEntityAccess(persistentEntity, obj, tmp); - - K k = readObjectIdentifier(entityAccess, persistentEntity.getMapping()); - boolean isUpdate = k != null && !isInsert; - boolean assignedId = false; - if (isUpdate && !getSession().isDirty(obj)) { - return (Serializable) k; - } - - PendingOperation pendingOperation; - - PropertyMapping mapping = persistentEntity.getIdentity().getMapping(); - SessionImplementor si = (SessionImplementor) session; - if (mapping != null) { - Property p = mapping.getMappedForm(); - assignedId = p != null && "assigned".equals(p.getGenerator()); - if (isNotUpdateForAssignedId(persistentEntity, obj, isUpdate, assignedId, si)) { - isUpdate = false; - } - } - String family = getEntityFamily(); - - if (!isUpdate) { - tmp = createNewEntry(family); - - if (!assignedId) { - k = generateIdentifier(persistentEntity, tmp); - } - - cacheNativeEntry(persistentEntity, (Serializable) k, tmp); - - pendingOperation = new PendingInsertAdapter(persistentEntity, k, tmp, entityAccess) { - public void run() { - K insertResult = executeInsert(persistentEntity, entityAccess, getNativeKey(), getNativeEntry()); - if(insertResult == null) { - setVetoed(true); - } - } - }; - - entityAccess.setProperty(entityAccess.getIdentifierName(), k); - } - else { - tmp = (T) si.getCachedEntry(persistentEntity, (Serializable) k); - if (tmp == null) { - tmp = getFromTPCache(persistentEntity, (Serializable) k); - if (tmp == null) { - tmp = retrieveEntry(persistentEntity, family, (Serializable) k); - } - } - if (tmp == null) { - tmp = createNewEntry(family); - } - - final T finalTmp = tmp; - final K finalK = k; - pendingOperation = new PendingUpdateAdapter(persistentEntity, finalK, finalTmp, entityAccess) { - public void run() { - if (cancelUpdate(persistentEntity, entityAccess)) return; - updateEntry(persistentEntity, entityAccess, getNativeKey(), getNativeEntry()); - updateTPCache(persistentEntity, finalTmp, (Serializable) finalK); - firePostUpdateEvent(persistentEntity, entityAccess); - } - }; - } - - final T e = tmp; - entityAccess.setNativeEntry(e); - - final List props = persistentEntity.getPersistentProperties(); - final Map> toManyKeys = new HashMap>(); - final Map inverseCollectionUpdates = new HashMap(); - final Map toIndex = new HashMap(); - final Map toUnindex = new HashMap(); - entityAccess.setToIndex(toIndex); - for (PersistentProperty prop : props) { - PropertyMapping pm = prop.getMapping(); - final Property mappedProperty = pm.getMappedForm(); - String key = null; - if (mappedProperty != null) { - key = mappedProperty.getTargetName(); - } - if (key == null) key = prop.getName(); - final boolean indexed = isPropertyIndexed(mappedProperty); - if ((prop instanceof Simple) || (prop instanceof Basic)) { - Object propValue = entityAccess.getProperty(prop.getName()); - - handleIndexing(isUpdate, e, toIndex, toUnindex, prop, key, indexed, propValue); - setEntryValue(e, key, propValue); - } - else if ((prop instanceof Custom)) { - CustomTypeMarshaller customTypeMarshaller = ((Custom) prop).getCustomTypeMarshaller(); - if (customTypeMarshaller.supports(getSession().getDatastore())) { - Object propValue = entityAccess.getProperty(prop.getName()); - Object customValue = customTypeMarshaller.write(prop, propValue, e); - handleIndexing(isUpdate, e, toIndex, toUnindex, prop, key, indexed, customValue); - } - } - else if (prop instanceof OneToMany) { - final OneToMany oneToMany = (OneToMany) prop; - - final Object propValue = entityAccess.getProperty(oneToMany.getName()); - if (propValue instanceof Collection) { - Collection associatedObjects = (Collection) propValue; - if (isInitializedCollection(associatedObjects)) { - PersistentEntity associatedEntity = oneToMany.getAssociatedEntity(); - if(associatedEntity != null) { - EntityPersister associationPersister = (EntityPersister) session.getPersister(associatedEntity); - if (associationPersister != null) { - PersistentCollection persistentCollection; - boolean newCollection = false; - if (associatedObjects instanceof PersistentCollection) { - persistentCollection = (PersistentCollection) associatedObjects; - } - else { - Class associationType = associatedEntity.getJavaClass(); - persistentCollection = getPersistentCollection(associatedObjects, associationType); - entityAccess.setProperty(oneToMany.getName(), persistentCollection); - persistentCollection.markDirty(); - newCollection = true; - } - if (persistentCollection.isDirty()) { - persistentCollection.resetDirty(); - List keys = associationPersister.persist(associatedObjects); - toManyKeys.put(oneToMany, keys); - if (newCollection ) { - entityAccess.setProperty(oneToMany.getName(), associatedObjects); - } - } - } - } - } - } - } - else if (prop instanceof ManyToMany) { - final ManyToMany manyToMany = (ManyToMany) prop; - - final Object propValue = entityAccess.getProperty(manyToMany.getName()); - if (propValue instanceof Collection) { - Collection associatedObjects = (Collection) propValue; - if (isInitializedCollection(associatedObjects)) { - setManyToMany(persistentEntity, obj, e, manyToMany, associatedObjects, toManyKeys); - } - } - } - else if (prop instanceof ToOne) { - ToOne association = (ToOne) prop; - if (prop instanceof Embedded) { - // For embedded properties simply set the entry value, the underlying implementation - // will have to store the embedded entity in an appropriate way (as a sub-document in a document store for example) - handleEmbeddedToOne(association, key, entityAccess, e); - } - - else if (association.doesCascade(CascadeType.PERSIST) && association.getAssociatedEntity() != null) { - final Object associatedObject = entityAccess.getProperty(prop.getName()); - if (associatedObject != null) { - Serializable associationId; - NativeEntryEntityPersister associationPersister = (NativeEntryEntityPersister) session.getPersister(associatedObject); - if (proxyFactory.isInitialized(associatedObject) && !session.contains(associatedObject) ) { - Serializable tempId = associationPersister.getObjectIdentifier(associatedObject); - if (tempId == null) { - if (association.isOwningSide()) { - tempId = session.persist(associatedObject); - } - } - associationId = tempId; - } else { - associationId = associationPersister.getObjectIdentifier(associatedObject); - } - - // handling of hasOne inverse key - if (association.isForeignKeyInChild()) { - T cachedAssociationEntry = (T) si.getCachedEntry(association.getAssociatedEntity(), associationId); - if (cachedAssociationEntry != null) { - if (association.isBidirectional()) { - Association inverseSide = association.getInverseSide(); - if (inverseSide != null) { - setEntryValue(cachedAssociationEntry, inverseSide.getName(), formulateDatabaseReference(association.getAssociatedEntity(), inverseSide, (Serializable) k)); - } else { - setEntryValue(cachedAssociationEntry, key, formulateDatabaseReference(association.getAssociatedEntity(), inverseSide, (Serializable) k)); - } - } - } - - if (association.doesCascade(CascadeType.PERSIST)) { - - if (association.isBidirectional()) { - Association inverseSide = association.getInverseSide(); - if (inverseSide != null) { - EntityAccess inverseAccess = new EntityAccess(inverseSide.getOwner(), associatedObject); - inverseAccess.setProperty(inverseSide.getName(), obj); - } - } - associationPersister.persist(associatedObject); - } - } - // handle of standard many-to-one - else { - if (associationId != null) { - if (indexed && doesRequirePropertyIndexing()) { - toIndex.put(prop, associationId); - if (isUpdate) { - Object oldValue = getEntryValue(e, key); - oldValue = oldValue != null ? convertToNativeKey((Serializable) oldValue) : oldValue; - - if (oldValue != null && !oldValue.equals(associationId)) { - toUnindex.put(prop, oldValue); - } - } - } - setEntryValue(e, key, formulateDatabaseReference(persistentEntity, association, associationId)); - - if (association.isBidirectional()) { - Association inverse = association.getInverseSide(); - if (inverse instanceof OneToMany) { - inverseCollectionUpdates.put((OneToMany) inverse, associationId); - } - // unwrap the entity in case it is a proxy, since we may need to update the reverse link. - Object inverseEntity = proxyFactory.unwrap(entityAccess.getProperty(association.getName())); - if (inverseEntity != null) { - EntityAccess inverseAccess = createEntityAccess(association.getAssociatedEntity(), inverseEntity); - Object entity = entityAccess.getEntity(); - if (inverse instanceof OneToMany) { - Collection existingValues = (Collection) inverseAccess.getProperty(inverse.getName()); - if (existingValues == null) { - existingValues = MappingUtils.createConcreteCollection(inverse.getType()); - inverseAccess.setProperty(inverse.getName(), existingValues); - } - if (!existingValues.contains(entity)) - existingValues.add(entity); - } else if (inverse instanceof ToOne) { - inverseAccess.setProperty(inverse.getName(), entity); - } - } - } - } - } - } else { - setEntryValue(e, getPropertyKey(prop), null); - } - } - } - else if (prop instanceof EmbeddedCollection) { - handleEmbeddedToMany(entityAccess, e, prop, key); - } - } - - // perform pre-indexing (updating the native entry, if supported by this persister). - updateToManyIndices(e, k, toManyKeys, true); - - if (!isUpdate) { - // if the identifier is null at this point that means that datastore could not generated an identifer - // and the identifer is generated only upon insert of the entity - - final K updateId = k; - PendingOperation postOperation = new PendingOperationAdapter(persistentEntity, k, e) { - public void run() { - updateToManyIndices(e, updateId, toManyKeys, false); - - if (doesRequirePropertyIndexing()) { - toIndex.put(persistentEntity.getIdentity(), updateId); - updatePropertyIndices(updateId, toIndex, toUnindex); - } - for (OneToMany inverseCollection : inverseCollectionUpdates.keySet()) { - final Serializable primaryKey = inverseCollectionUpdates.get(inverseCollection); - final NativeEntryEntityPersister inversePersister = (NativeEntryEntityPersister) session.getPersister(inverseCollection.getOwner()); - final AssociationIndexer associationIndexer = inversePersister.getAssociationIndexer(e, inverseCollection); - associationIndexer.index(primaryKey, updateId); - } - } - }; - pendingOperation.addCascadeOperation(postOperation); - - // If the key is still null at this point we have to execute the pending operation now to get the key - if (k == null) { - PendingOperationExecution.executePendingOperation(pendingOperation); - } - else { - si.addPendingInsert((PendingInsert) pendingOperation); - } - } - else { - final K updateId = k; - - PendingOperation postOperation = new PendingOperationAdapter(persistentEntity, k, e) { - public void run() { - updateToManyIndices(e, updateId, toManyKeys, false); - if (doesRequirePropertyIndexing()) { - updatePropertyIndices(updateId, toIndex, toUnindex); - } - } - }; - pendingOperation.addCascadeOperation(postOperation); - si.addPendingUpdate((PendingUpdate) pendingOperation); - } - return (Serializable) k; - } - - private boolean isNotUpdateForAssignedId(PersistentEntity persistentEntity, Object obj, boolean update, boolean assignedId, SessionImplementor si) { - return assignedId && update && !si.isStateless(persistentEntity) && !session.contains(obj); - } - - @Override - protected final Serializable persistEntity(final PersistentEntity persistentEntity, Object obj) { - return persistEntity(persistentEntity, obj, false); - } - - private AbstractPersistentCollection getPersistentCollection(Collection associatedObjects, Class associationType) { - if (associatedObjects instanceof Set) { - return associatedObjects instanceof SortedSet ? new PersistentSortedSet(associationType,getSession(), (SortedSet) associatedObjects) : new PersistentSet(associationType, getSession(), associatedObjects); - } - return new PersistentList(associationType,getSession(), (List) associatedObjects); - } - - private boolean isInitializedCollection(Collection associatedObjects) { - return !(associatedObjects instanceof PersistentCollection) || ((PersistentCollection) associatedObjects).isInitialized(); - } - - /** - * Formulates a database reference for the given entity, association and association id - * - * @param persistentEntity The entity being persisted - * @param association The association - * @param associationId The association id - * @return A database reference - */ - protected Object formulateDatabaseReference(PersistentEntity persistentEntity, Association association, Serializable associationId) { - return associationId; - } - - protected void handleEmbeddedToMany(EntityAccess entityAccess, T e, PersistentProperty prop, String key) { - // For embedded properties simply set the entry value, the underlying implementation - // will have to store the embedded entity in an appropriate way (as a sub-document in a document store for example) - Object embeddedInstances = entityAccess.getProperty(prop.getName()); - if (!(embeddedInstances instanceof Collection) || ((Collection)embeddedInstances).isEmpty()) { - if (embeddedInstances == null) - setEmbeddedCollection(e, key, null, null); - else { - setEmbeddedCollection(e, key, MappingUtils.createConcreteCollection(prop.getType()), new ArrayList()); - } - return; - } - - Collection instances = (Collection)embeddedInstances; - List embeddedEntries = new ArrayList(); - for (Object instance : instances) { - T entry = handleEmbeddedInstance((Association) prop, instance); - embeddedEntries.add(entry); - } - - setEmbeddedCollection(e, key, instances, embeddedEntries); - } - - protected void handleEmbeddedToOne(Association association, String key, EntityAccess entityAccess, T nativeEntry) { - Object embeddedInstance = entityAccess.getProperty(association.getName()); - if (embeddedInstance == null) { - setEmbedded(nativeEntry, key, null); - return; - } - - T embeddedEntry = handleEmbeddedInstance(association, embeddedInstance); - setEmbedded(nativeEntry, key, embeddedEntry); - } - - protected T handleEmbeddedInstance(Association association, Object embeddedInstance) { - NativeEntryEntityPersister embeddedPersister = (NativeEntryEntityPersister) session.getPersister(embeddedInstance); - - // embeddedPersister would be null if the associated entity is a EmbeddedPersistentEntity - T embeddedEntry; - if (embeddedPersister == null) { - embeddedEntry = createNewEntry(association.getName()); - } - else { - embeddedEntry = embeddedPersister.createNewEntry(embeddedPersister.getEntityFamily()); - } - - final PersistentEntity associatedEntity = embeddedPersister == null ? association.getAssociatedEntity() : embeddedPersister.getPersistentEntity(); - if (associatedEntity != null) { - final List embeddedProperties = associatedEntity.getPersistentProperties(); - final EntityAccess embeddedEntityAccess = createEntityAccess(associatedEntity, embeddedInstance); - PersistentProperty identity = associatedEntity.getIdentity(); - if (identity != null) { - Object embeddedId = embeddedEntityAccess.getProperty(identity.getName()); - if (embeddedId != null) { - setEntryValue(embeddedEntry, getPropertyKey(identity), embeddedId); - } - } - for (PersistentProperty persistentProperty : embeddedProperties) { - if (persistentProperty instanceof Simple) { - setEntryValue(embeddedEntry, getPropertyKey(persistentProperty), embeddedEntityAccess.getProperty(persistentProperty.getName())); - } - else if (persistentProperty instanceof Custom) { - CustomTypeMarshaller customTypeMarshaller = ((Custom) persistentProperty).getCustomTypeMarshaller(); - if (customTypeMarshaller.supports(getSession().getDatastore())) { - customTypeMarshaller.write(persistentProperty, embeddedEntityAccess.getProperty(persistentProperty.getName()), embeddedEntry); - } - } - else if (persistentProperty instanceof Association) { - Association inverseSide = ((Association) persistentProperty).getInverseSide(); - if (inverseSide instanceof Embedded || - inverseSide instanceof EmbeddedCollection) { - // these are the back links to the parents we might be embedded in, and don't need to be saved. - // they are recreated during a refresh. - } - else if (persistentProperty instanceof Embedded) { - Association toOne = (Association) persistentProperty; - - handleEmbeddedToOne(toOne, getPropertyKey(persistentProperty), embeddedEntityAccess, embeddedEntry); - } - else if (persistentProperty instanceof ToOne) { - Association toOne = (Association) persistentProperty; - - Object obj = embeddedEntityAccess.getProperty(toOne.getName()); - Persister persister = getSession().getPersister(obj); - if (persister != null) { - Serializable id = persister.persist(obj); - if (id != null) { - setEntryValue(embeddedEntry, getPropertyKey(toOne), formulateDatabaseReference(associatedEntity, toOne, id)); - } - } - } - else if (persistentProperty instanceof Basic) { - setEntryValue(embeddedEntry, getPropertyKey(persistentProperty), embeddedEntityAccess.getProperty(persistentProperty.getName())); - } - else if (persistentProperty instanceof EmbeddedCollection) { - handleEmbeddedToMany(embeddedEntityAccess, embeddedEntry, persistentProperty, persistentProperty.getName()); - } - else { - if (persistentProperty instanceof OneToMany) { - final OneToMany oneToMany = (OneToMany) persistentProperty; - - final Object propValue = embeddedEntityAccess.getProperty(oneToMany.getName()); - if (propValue instanceof Collection) { - Collection associatedObjects = (Collection) propValue; - List keys = session.persist(associatedObjects); - - setEmbeddedCollectionKeys(oneToMany, embeddedEntityAccess, embeddedEntry, keys); - } - } - else if (persistentProperty instanceof ManyToMany) { - final ManyToMany manyToMany = (ManyToMany) persistentProperty; - - final Object propValue = embeddedEntityAccess.getProperty(manyToMany.getName()); - if (propValue instanceof Collection) { - Collection associatedObjects = (Collection) propValue; - List keys = session.persist(associatedObjects); - setManyToMany(embeddedPersister.getPersistentEntity(), embeddedInstance, embeddedEntry, manyToMany, associatedObjects, Collections.>emptyMap()); - } - } - } - } - } - } - return embeddedEntry; - } - - private void handleIndexing(boolean update, T e, Map toIndex, - Map toUnindex, PersistentProperty prop, String key, - boolean indexed, Object propValue) { - - if (!indexed) { - return; - } - - if (update) { - final Object oldValue = getEntryValue(e, key); - - boolean unindex = oldValue == null - ? propValue != null - : !oldValue.equals(propValue); - - if (unindex) { - toUnindex.put(prop, oldValue); - } - } - - toIndex.put(prop, propValue); - } - - protected boolean isPropertyIndexed(Property mappedProperty) { - return mappedProperty != null && mappedProperty.isIndex(); - } - - protected void setManyToMany(PersistentEntity persistentEntity, Object obj, - T nativeEntry, ManyToMany manyToMany, Collection associatedObjects, - Map> toManyKeys) { - // override as necessary - } - - /** - * Implementors should override this method to provide support for embedded objects - * - * @param nativeEntry The native entry - * @param key The key - * @param embeddedEntry The embedded object - */ - protected void setEmbedded(T nativeEntry, String key, T embeddedEntry) { - // do nothing. The default is no support for embedded instances - } - - /** - * Implementors should override this method to provide support for embedded objects - * - * @param nativeEntry The native entry - * @param key The key - * @param instances the embedded instances - * @param embeddedEntries the native entries - */ - protected void setEmbeddedCollection(T nativeEntry, String key, Collection instances, List embeddedEntries) { - // do nothing. The default is no support for embedded collections - } - - /** - * Subclasses should override to provide id generation. If an identifier is only generated via an insert operation then this - * method should return null - * - * @param persistentEntity The entity - * @param entry The native entry - * @return The identifier or null if an identifier is generated only on insert - */ - protected abstract K generateIdentifier(PersistentEntity persistentEntity, T entry); - - private void updateToManyIndices(T nativeEntry, Object identifier, Map> toManyKeys, boolean preIndex) { - // now cascade onto one-to-many associations - for (Association association : toManyKeys.keySet()) { - if (association.doesCascade(CascadeType.PERSIST)) { - final AssociationIndexer indexer = getAssociationIndexer(nativeEntry, association); - if (indexer != null) { - List foreignKeys = toManyKeys.get(association); - if (preIndex) { - indexer.preIndex(identifier, foreignKeys); - } else { - indexer.index(identifier, foreignKeys); - } - } - } - } - } - - private void updatePropertyIndices(Object identifier, Map valuesToIndex, Map valuesToDeindex) { - // Here we manually create indices for any indexed properties so that queries work - for (PersistentProperty persistentProperty : valuesToIndex.keySet()) { - Object value = valuesToIndex.get(persistentProperty); - - final PropertyValueIndexer indexer = getPropertyIndexer(persistentProperty); - if (indexer != null) { - indexer.index(value, identifier); - } - } - - for (PersistentProperty persistentProperty : valuesToDeindex.keySet()) { - final PropertyValueIndexer indexer = getPropertyIndexer(persistentProperty); - Object value = valuesToDeindex.get(persistentProperty); - if (indexer != null) { - indexer.deindex(value, identifier); - } - } - } - - /** - * Obtains an indexer for a particular property - * - * @param property The property to index - * @return The indexer - */ - public abstract PropertyValueIndexer getPropertyIndexer(PersistentProperty property); - - /** - * Obtains an indexer for the given association - * - * - * @param nativeEntry The native entry - * @param association The association - * @return An indexer - */ - public abstract AssociationIndexer getAssociationIndexer(T nativeEntry, Association association); - - /** - * Reads an objects identifier using the entity access and ClassMapping instance - * @param entityAccess - * @param cm - * @return The object identifier - */ - protected K readObjectIdentifier(EntityAccess entityAccess, ClassMapping cm) { - return (K) entityAccess.getIdentifier(); - } - - /** - * Obtains the identifier name to use. Subclasses can override to provide their own strategy for looking up an identifier name - * @param cm The ClassMapping instance - * @return The identifier name - */ - protected String getIdentifierName(ClassMapping cm) { - return cm.getIdentifier().getIdentifierName()[0]; - } - - /** - * This is a rather simplistic and unoptimized implementation. Subclasses can override to provide - * batch insert capabilities to optimize the insertion of multiple entities in one go - * - * @param persistentEntity The persistent entity - * @param objs The objext to persist - * @return A list of keys - */ - @Override - protected List persistEntities(PersistentEntity persistentEntity, Iterable objs) { - List keys = new ArrayList(); - Iterable newIter = objs; - if (objs instanceof Collection) { - newIter = new ArrayList((Collection) objs); - } - for (Object obj : newIter) { - if (persistentEntity.isInstance(obj)) { - if (persistentEntity.getJavaClass().equals(obj.getClass())) { - keys.add(persist(obj)); - } - else { - // subclass persister - EntityPersister persister = (EntityPersister) getSession().getPersister(obj); - keys.add(persister.persist(obj)); - } - } - } - return keys; - } - - /** - * Simplistic default implementation of retrieveAllEntities that iterates over each key and retrieves the entities - * one-by-one. Data stores that support batch retrieval can optimize this to retrieve all entities in one go. - * - * @param persistentEntity The persist entity - * @param keys The keys - * @return A list of entities - */ - @Override - protected List retrieveAllEntities(PersistentEntity persistentEntity, Iterable keys) { - List results = new ArrayList(); - for (Serializable key : keys) { - results.add(retrieveEntity(persistentEntity, key)); - } - return results; - } - - /** - * Simplistic default implementation of retrieveAllEntities that iterates over each key and retrieves the entities - * one-by-one. Data stores that support batch retrieval can optimize this to retrieve all entities in one go. - * - * @param persistentEntity The persist entity - * @param keys The keys - * @return A list of entities - */ - @Override - protected List retrieveAllEntities(PersistentEntity persistentEntity, Serializable[] keys) { - List results = new ArrayList(); - for (Serializable key : keys) { - results.add(retrieveEntity(persistentEntity, key)); - } - return results; - } - - /** - * Used to establish the native key to use from the identifier defined by the object - * @param family The family - * @param identifier The identifier specified by the object - * @return The native key which may just be a cast from the identifier parameter to K - */ - protected Object inferNativeKey(String family, Object identifier) { - return identifier; - } - - /** - * Creates a new entry for the given family. - * - * @param family The family - * @return An entry such as a BigTable Entity, ColumnFamily etc. - */ - protected abstract T createNewEntry(String family); - - /** - * Reads a value for the given key from the native entry - * - * @param nativeEntry The native entry. Could be a ColumnFamily, a BigTable entity, a Map etc. - * @param property The property key - * @return The value - */ - protected abstract Object getEntryValue(T nativeEntry, String property); - - /** - * Sets a value on an entry - * @param nativeEntry The native entry such as a BigTable Entity, ColumnFamily etc. - * @param key The key - * @param value The value - */ - protected abstract void setEntryValue(T nativeEntry, String key, Object value); - - /** - * Reads the native form of a Key/value datastore entry. This could be - * a ColumnFamily, a BigTable Entity, a Map etc. - * - * @param persistentEntity The persistent entity - * @param family The family - * @param key The key - * @return The native form - */ - protected abstract T retrieveEntry(PersistentEntity persistentEntity, String family, Serializable key); - - /** - * Stores the native form of a Key/value datastore to the actual data store - * - * @param persistentEntity The persistent entity - * @param entityAccess The EntityAccess - * @param storeId - * @param nativeEntry The native form. Could be a a ColumnFamily, BigTable Entity etc. - * @return The native key - */ - protected abstract K storeEntry(PersistentEntity persistentEntity, EntityAccess entityAccess, - K storeId, T nativeEntry); - - /** - * Updates an existing entry to the actual datastore - * - * @param persistentEntity The PersistentEntity - * @param entityAccess The EntityAccess - * @param key The key of the object to update - * @param entry The entry - */ - protected abstract void updateEntry(PersistentEntity persistentEntity, - EntityAccess entityAccess, K key, T entry); - - /** - * Deletes one or many entries for the given list of Keys - * - * @param family The family - * @param keys The keys - */ - protected abstract void deleteEntries(String family, List keys); - - /** - * Executes an insert for the given entity, entity access, identifier and native entry. - * Any before interceptors will be triggered - * - * @param persistentEntity - * @param entityAccess - * @param id - * @param e - * @return The key - */ - protected K executeInsert(final PersistentEntity persistentEntity, - final NativeEntryModifyingEntityAccess entityAccess, - final K id, final T e) { - if (cancelInsert(persistentEntity, entityAccess)) return null; - final K newId = storeEntry(persistentEntity, entityAccess, id, e); - entityAccess.setIdentifier(newId); - updateTPCache(persistentEntity, e, (Serializable) newId); - - firePostInsertEvent(persistentEntity, entityAccess); - return newId; - } - - protected void updateTPCache(PersistentEntity persistentEntity, T e, Serializable id) { - if (cacheAdapterRepository == null) { - return; - } - - TPCacheAdapter cacheAdapter = cacheAdapterRepository.getTPCacheAdapter(persistentEntity); - if (cacheAdapter != null) { - cacheAdapter.cacheEntry(id, e); - } - } - - protected T getFromTPCache(PersistentEntity persistentEntity, Serializable id) { - if (cacheAdapterRepository == null) { - return null; - } - - TPCacheAdapter cacheAdapter = cacheAdapterRepository.getTPCacheAdapter(persistentEntity); - if (cacheAdapter != null) { - return cacheAdapter.getCachedEntry(id); - } - return null; - } - - protected class NativeEntryModifyingEntityAccess extends EntityAccess { - - T nativeEntry; - private Map toIndex; - - public NativeEntryModifyingEntityAccess(PersistentEntity persistentEntity, Object entity) { - super(persistentEntity, entity); - } - - @Override - public void setProperty(String name, Object value) { - super.setProperty(name, value); - if (nativeEntry != null) { - PersistentProperty property = persistentEntity.getPropertyByName(name); - if (property != null && (property instanceof Simple || property instanceof Basic)) { - setEntryValue(nativeEntry, name, value); - } - - if (toIndex != null && property != null) { - PropertyMapping pm = property.getMapping(); - if (pm != null && isPropertyIndexed(pm.getMappedForm())) { - if (property instanceof ToOne) { - ToOne association = (ToOne) property; - if (!association.isForeignKeyInChild()) { - NativeEntryEntityPersister associationPersister = (NativeEntryEntityPersister) session.getPersister(value); - if(associationPersister != null) { - if (value == null) { - toIndex.put(property, null); - } - else { - toIndex.put(property, associationPersister.getObjectIdentifier(value)); - } - } - } - } - else { - toIndex.put(property, value); - } - } - } - } - } - - public void setNativeEntry(T nativeEntry) { - this.nativeEntry = nativeEntry; - } - - public void setToIndex(Map toIndex) { - this.toIndex = toIndex; - } - } - - public boolean isDirty(Object instance, Object entry) { - if ((instance == null)) { - return false; - } - if (entry == null) { - return true; - } - - if(instance instanceof DirtyCheckable) { - return ((DirtyCheckable)instance).hasChanged(); - } - else { - return doManualDirtyCheck(instance, entry); - } - } - - protected boolean doManualDirtyCheck(Object instance, Object entry) { - T nativeEntry; - try { - nativeEntry = (T)entry; - } - catch (ClassCastException ignored) { - return false; - } - - EntityAccess entityAccess = createEntityAccess(getPersistentEntity(), instance, nativeEntry); - - List props = getPersistentEntity().getPersistentProperties(); - for (PersistentProperty prop : props) { - String key = getPropertyKey(prop); - - Object currentValue = entityAccess.getProperty(prop.getName()); - Object oldValue = getEntryValue(nativeEntry, key); - if (prop instanceof Simple || prop instanceof Basic || prop instanceof ToOne) { - if (!areEqual(oldValue, currentValue, key)) { - return true; - } - } - else if (prop instanceof OneToMany || prop instanceof ManyToMany) { - if (!areCollectionsEqual(oldValue, currentValue)) { - return true; - } - } - else if (prop instanceof EmbeddedCollection) { - if (currentValue != null && oldValue == null) return true; - if ((currentValue instanceof Collection) && (oldValue instanceof Collection)) { - Collection currentCollection = (Collection) currentValue; - Collection oldCollection = (Collection) oldValue; - if (currentCollection.size() != oldCollection.size()) { - return true; - } - else { - if (!areCollectionsEqual(oldValue, currentValue)) { - return true; - } - } - } - } - else if (prop instanceof Custom) { - CustomTypeMarshaller marshaller = ((Custom)prop).getCustomTypeMarshaller(); - if (!areEqual(marshaller.read(prop, entry), currentValue, key)) { - return true; - } - } - else { - throw new UnsupportedOperationException("dirty not detected for property " + prop.toString() + " " + prop.getClass().getSuperclass().toString()); - } - } - - return false; - } - - protected String getPropertyKey(PersistentProperty prop) { - PropertyMapping pm = prop.getMapping(); - Property mappedProperty = pm.getMappedForm(); - String key = null; - if (mappedProperty != null) { - key = mappedProperty.getTargetName(); - } - if (key == null) key = prop.getName(); - return key; - } - - protected boolean areCollectionsEqual(Object oldValue, Object currentValue) { - if (oldValue == currentValue) { - // same or both null - return true; - } - - if (currentValue instanceof PersistentCollection) { - return !((PersistentCollection)currentValue).isDirty(); - } - - return replaceNullOrUninitialized(oldValue, currentValue).equals( - replaceNullOrUninitialized(currentValue, oldValue)); - } - - private Object replaceNullOrUninitialized(Object c, Object other) { - if (c == null) { - if (other instanceof Set) { - return Collections.emptySet(); - } - return Collections.emptyList(); - } - - if (c instanceof PersistentCollection && !((PersistentCollection)c).isInitialized()) { - if (c instanceof Set) { - return Collections.emptySet(); - } - return Collections.emptyList(); - } - - return c; - } - - protected boolean areEqual(Object oldValue, Object currentValue, String propName) { - if (oldValue == currentValue) { - return true; - } - - if (oldValue == null || currentValue == null) { - return false; - } - - if ("version".equals(propName)) { - // special case where comparing int and long would fail artifically - if (oldValue instanceof Number && currentValue instanceof Number) { - oldValue = ((Number)oldValue).longValue(); - currentValue = ((Number)currentValue).longValue(); - } - else { - oldValue = oldValue.toString(); - currentValue = currentValue.toString(); - } - } - - Class oldValueClass = oldValue.getClass(); - if (!oldValueClass.isArray()) { - if (oldValue instanceof Float) { - return Float.floatToIntBits((Float)oldValue) == Float.floatToIntBits((Float)currentValue); - } - if (oldValue instanceof Double) { - return Double.doubleToLongBits((Double)oldValue) == Double.doubleToLongBits((Double)currentValue); - } - return oldValue.equals(currentValue); - } - - // check arrays - - if (oldValue.getClass() != currentValue.getClass()) { - // different dimension - return false; - } - - if (oldValue instanceof long[]) { - return Arrays.equals((long[])oldValue, (long[])currentValue); - } - - if (oldValue instanceof int[]) { - return Arrays.equals((int[])oldValue, (int[])currentValue); - } - - if (oldValue instanceof short[]) { - return Arrays.equals((short[])oldValue, (short[])currentValue); - } - - if (oldValue instanceof char[]) { - return Arrays.equals((char[])oldValue, (char[])currentValue); - } - - if (oldValue instanceof byte[]) { - return Arrays.equals((byte[])oldValue, (byte[])currentValue); - } - - if (oldValue instanceof double[]) { - return Arrays.equals((double[])oldValue, (double[])currentValue); - } - - if (oldValue instanceof float[]) { - return Arrays.equals((float[])oldValue, (float[])currentValue); - } - - if (oldValue instanceof boolean[]) { - return Arrays.equals((boolean[])oldValue, (boolean[])currentValue); - } - - return Arrays.equals((Object[])oldValue, (Object[])currentValue); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/NonPersistentTypeException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/NonPersistentTypeException.java deleted file mode 100644 index 716f4bc6a..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/NonPersistentTypeException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2010 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.mapping.engine; - -/** - * Thrown when an object cannot be persisted. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class NonPersistentTypeException extends RuntimeException { - - private static final long serialVersionUID = 1; - - public NonPersistentTypeException(String s) { - super(s); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/Persister.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/Persister.java deleted file mode 100644 index bd0c84c5d..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/Persister.java +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright (C) 2010 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.mapping.engine; - -import java.io.Serializable; -import java.util.List; - -import org.grails.datastore.mapping.query.Query; - -/** - * A Persister is responsible for persisting and retrieving an object. - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface Persister { - - /** - * The type this persister persists - * - * @return The class this persisters persists - */ - @SuppressWarnings("rawtypes") - Class getType(); - - /** - * Persist an object using the given mapping context - * - * @param obj The object - * @return A generated Key - */ - Serializable persist(Object obj); - - /** - * Persists a number of objects at the same time and - * returns their keys in the order specified by the objs parameter - * - * @param objs The objects - * @return A list of keys - */ - List persist(@SuppressWarnings("rawtypes") Iterable objs); - - /** - * Retrieves an object for the given context and Key - * - * @param key The key - * - * @return The object in question - */ - Object retrieve(Serializable key); - - /** - * Creates a proxy for the given key - * - * @param key The key - * @return The proxy - */ - Object proxy(Serializable key); - - /** - * Deletes one or many objects - * @param objects The objects to delete. Must all be of the same type or an exception will be thrown. - */ - void delete(@SuppressWarnings("rawtypes") Iterable objects); - - /** - * Batch retrieve several objects in one go - * - * @param keys The keys - * @return The objects in a list in the same order as the specified keys - */ - List retrieveAll(Iterable keys); - - /** - * Deletes a single object - * @param obj The object - */ - void delete(Object obj); - - /** - * Creates a query for the entity - * - * @return The Query object - */ - Query createQuery(); - - /** - * Batch retrieve several objects in one go - * - * @param keys The keys - * @return The objects in a list in the same order as the specified keys - */ - List retrieveAll(Serializable[] keys); - - /** - * Refreshes the given objects state - * @param o The object to refresh - * @return The objects id - */ - Serializable refresh(Object o); - - /** - * Get the identifier for the given object, if it has one. - * @param o The object. - * @return The object's id. - */ - Serializable getObjectIdentifier(Object o); - - /** - * Forces an insert of an object rather than trying to guess if it is an insert or an update - * @param o The object - * @return The id - */ - Serializable insert(Object o); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/PropertyValueIndexer.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/PropertyValueIndexer.java deleted file mode 100644 index 2e025771f..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/PropertyValueIndexer.java +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (C) 2010 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.mapping.engine; - -import java.util.List; - -/** - * Responsible for creating indices for property values used in queries. - * - * This interface is designed for usage in datastores that don't automatically - * create indices and require the application to create the indices manually. - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface PropertyValueIndexer { - - /** - * Creates an index for the given value to the specified key - * - * @param value The value - * @param primaryKey The key - */ - void index(Object value, K primaryKey); - - /** - * Queries the given value and returns the keys - * - * @param value The value to query by - * - * @return The primary keys - */ - List query(Object value); - - /** - * Queries the given value and returns the keys - * - * @param value The value to query by - * @param offset The offset position to start from - * @param max The maximum number of records - * @return The primary keys - */ - List query(Object value, int offset, int max); - - /** - * @param value The indexed value - * @return The name of the index - */ - String getIndexName(Object value); - - /** - * Removes the index for the given value and key - * @param value The value - * @param primaryKey The key - */ - void deindex(Object value, K primaryKey); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEvent.java deleted file mode 100644 index f9ea9a6eb..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEvent.java +++ /dev/null @@ -1,91 +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.mapping.engine.event; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.context.ApplicationEvent; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * @author Burt Beckwith - */ -@SuppressWarnings("serial") -public abstract class AbstractPersistenceEvent extends ApplicationEvent { - - private final PersistentEntity entity; - private final Object entityObject; - private final EntityAccess entityAccess; - private boolean cancelled; - private List excludedListenerNames = new ArrayList(); - private Serializable nativeEvent; - - protected AbstractPersistenceEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { - super(source); - this.entity = entity; - this.entityAccess = entityAccess; - this.entityObject = entityAccess.getEntity(); - } - - protected AbstractPersistenceEvent(final Datastore source, final Object entity) { - super(source); - entityObject = entity; - this.entity = null; - this.entityAccess = null; - } - - public Object getEntityObject() { - return entityObject; - } - - public PersistentEntity getEntity() { - return entity; - } - - public EntityAccess getEntityAccess() { - return entityAccess; - } - - public void cancel() { - cancelled = true; - } - - public boolean isCancelled() { - return cancelled; - } - - public void addExcludedListenerName(final String name) { - excludedListenerNames.add(name); - } - - public boolean isListenerExcluded(final String name) { - return excludedListenerNames.contains(name); - } - - public void setNativeEvent(final Serializable nativeEvent) { - this.nativeEvent = nativeEvent; - } - - public Serializable getNativeEvent() { - return nativeEvent; - } - - public abstract EventType getEventType(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEventListener.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEventListener.java deleted file mode 100644 index 1b7c46fa6..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEventListener.java +++ /dev/null @@ -1,62 +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.mapping.engine.event; - -import org.springframework.context.ApplicationEvent; -import org.grails.datastore.mapping.core.Datastore; - -/** - * @author Burt Beckwith - */ -public abstract class AbstractPersistenceEventListener implements PersistenceEventListener { - - protected Datastore datastore; - - protected AbstractPersistenceEventListener(final Datastore datastore) { - this.datastore = datastore; - } - - /** - * {@inheritDoc} - * @see org.springframework.context.ApplicationListener#onApplicationEvent( - * org.springframework.context.ApplicationEvent) - */ - public final void onApplicationEvent(ApplicationEvent e) { - if(e instanceof AbstractPersistenceEvent) { - - AbstractPersistenceEvent event = (AbstractPersistenceEvent)e; - if (event.isCancelled()) { - return; - } - - if (event.isListenerExcluded(getClass().getName())) { - return; - } - onPersistenceEvent(event); - } - - } - - protected abstract void onPersistenceEvent(AbstractPersistenceEvent event); - - public int getOrder() { - return DEFAULT_ORDER; - } - - public boolean supportsSourceType(final Class sourceType) { - // ensure that this listener only handles its events (e.g. if Mongo and Redis are both installed) - return datastore.getClass().isAssignableFrom(sourceType); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/EventType.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/EventType.java deleted file mode 100644 index 0ceb62657..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/EventType.java +++ /dev/null @@ -1,31 +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.mapping.engine.event; - -/** - * @author Burt Beckwith - */ -public enum EventType { - PreDelete, - PreInsert, - PreLoad, - PreUpdate, - PostDelete, - PostInsert, - PostLoad, - PostUpdate, - SaveOrUpdate, - Validation -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PersistenceEventListener.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PersistenceEventListener.java deleted file mode 100644 index 30ee5597b..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PersistenceEventListener.java +++ /dev/null @@ -1,24 +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.mapping.engine.event; - -import org.springframework.context.event.SmartApplicationListener; - -/** - * @author Burt Beckwith - */ -public interface PersistenceEventListener extends SmartApplicationListener { - int DEFAULT_ORDER = Integer.MAX_VALUE / 2; -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostDeleteEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostDeleteEvent.java deleted file mode 100644 index e52ff0d28..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostDeleteEvent.java +++ /dev/null @@ -1,41 +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.mapping.engine.event; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * @author Burt Beckwith - */ -public class PostDeleteEvent extends AbstractPersistenceEvent { - - private static final long serialVersionUID = 1; - - public PostDeleteEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { - super(source, entity, entityAccess); - } - - public PostDeleteEvent(final Datastore source, final Object entity) { - super(source, entity); - } - - @Override - public EventType getEventType() { - return EventType.PostDelete; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostInsertEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostInsertEvent.java deleted file mode 100644 index afae0aa41..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostInsertEvent.java +++ /dev/null @@ -1,41 +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.mapping.engine.event; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * @author Burt Beckwith - */ -public class PostInsertEvent extends AbstractPersistenceEvent { - - private static final long serialVersionUID = 1; - - public PostInsertEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { - super(source, entity, entityAccess); - } - - public PostInsertEvent(final Datastore source, final Object entity) { - super(source, entity); - } - - @Override - public EventType getEventType() { - return EventType.PostInsert; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostLoadEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostLoadEvent.java deleted file mode 100644 index 9fd339f4e..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostLoadEvent.java +++ /dev/null @@ -1,41 +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.mapping.engine.event; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * @author Burt Beckwith - */ -public class PostLoadEvent extends AbstractPersistenceEvent { - - private static final long serialVersionUID = 1; - - public PostLoadEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { - super(source, entity, entityAccess); - } - - public PostLoadEvent(final Datastore source, final Object entity) { - super(source, entity); - } - - @Override - public EventType getEventType() { - return EventType.PostLoad; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostUpdateEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostUpdateEvent.java deleted file mode 100644 index 0b51e11ba..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostUpdateEvent.java +++ /dev/null @@ -1,41 +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.mapping.engine.event; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * @author Burt Beckwith - */ -public class PostUpdateEvent extends AbstractPersistenceEvent { - - private static final long serialVersionUID = 1; - - public PostUpdateEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { - super(source, entity, entityAccess); - } - - public PostUpdateEvent(final Datastore source, final Object entity) { - super(source, entity); - } - - @Override - public EventType getEventType() { - return EventType.PostUpdate; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreDeleteEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreDeleteEvent.java deleted file mode 100644 index 5c049125b..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreDeleteEvent.java +++ /dev/null @@ -1,41 +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.mapping.engine.event; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * @author Burt Beckwith - */ -public class PreDeleteEvent extends AbstractPersistenceEvent { - - private static final long serialVersionUID = 1; - - public PreDeleteEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { - super(source, entity, entityAccess); - } - - public PreDeleteEvent(final Datastore source, final Object entity) { - super(source, entity); - } - - @Override - public EventType getEventType() { - return EventType.PreDelete; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreInsertEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreInsertEvent.java deleted file mode 100644 index ee1959918..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreInsertEvent.java +++ /dev/null @@ -1,41 +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.mapping.engine.event; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * @author Burt Beckwith - */ -public class PreInsertEvent extends AbstractPersistenceEvent { - - private static final long serialVersionUID = 1; - - public PreInsertEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { - super(source, entity, entityAccess); - } - - public PreInsertEvent(final Datastore source, final Object entity) { - super(source, entity); - } - - @Override - public EventType getEventType() { - return EventType.PreInsert; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreLoadEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreLoadEvent.java deleted file mode 100644 index b7f0c1357..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreLoadEvent.java +++ /dev/null @@ -1,41 +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.mapping.engine.event; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * @author Burt Beckwith - */ -public class PreLoadEvent extends AbstractPersistenceEvent { - - private static final long serialVersionUID = 1; - - public PreLoadEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { - super(source, entity, entityAccess); - } - - public PreLoadEvent(final Datastore source, final Object entity) { - super(source, entity); - } - - @Override - public EventType getEventType() { - return EventType.PreLoad; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreUpdateEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreUpdateEvent.java deleted file mode 100644 index ee171bee9..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreUpdateEvent.java +++ /dev/null @@ -1,41 +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.mapping.engine.event; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * @author Burt Beckwith - */ -public class PreUpdateEvent extends AbstractPersistenceEvent { - - private static final long serialVersionUID = 1; - - public PreUpdateEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { - super(source, entity, entityAccess); - } - - public PreUpdateEvent(final Datastore source, final Object entity) { - super(source, entity); - } - - @Override - public EventType getEventType() { - return EventType.PreUpdate; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/SaveOrUpdateEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/SaveOrUpdateEvent.java deleted file mode 100644 index f3cb4dca7..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/SaveOrUpdateEvent.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.grails.datastore.mapping.engine.event; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * @author Burt Beckwith - */ -public class SaveOrUpdateEvent extends AbstractPersistenceEvent { - - private static final long serialVersionUID = 1; - - public SaveOrUpdateEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { - super(source, entity, entityAccess); - } - - public SaveOrUpdateEvent(final Datastore source, final Object entity) { - super(source, entity); - } - - @Override - public EventType getEventType() { - return EventType.SaveOrUpdate; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/ValidationEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/ValidationEvent.java deleted file mode 100644 index f2d4db334..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/ValidationEvent.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.grails.datastore.mapping.engine.event; - -import java.util.List; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * @author Burt Beckwith - */ -public class ValidationEvent extends AbstractPersistenceEvent { - - private static final long serialVersionUID = 1; - - private List validatedFields; - - public ValidationEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { - super(source, entity, entityAccess); - } - - public ValidationEvent(final Datastore source, final Object entity) { - super(source, entity); - } - - public List getValidatedFields() { - return validatedFields; - } - - public void setValidatedFields(final List fields) { - validatedFields = fields; - } - - @Override - public EventType getEventType() { - return EventType.Validation; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/internal/MappingUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/internal/MappingUtils.java deleted file mode 100644 index 03016604c..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/internal/MappingUtils.java +++ /dev/null @@ -1,137 +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.mapping.engine.internal; - -import java.lang.reflect.Field; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Queue; -import java.util.SortedSet; -import java.util.TreeSet; - -import org.grails.datastore.mapping.config.Property; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.PropertyMapping; - -/** - * Utility methods for mapping logic. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class MappingUtils { - - public static String getTargetKey(PersistentProperty property) { - PropertyMapping mapping = property.getMapping(); - String targetName; - - if (mapping != null && mapping.getMappedForm() != null) { - String tmp = mapping.getMappedForm().getTargetName(); - targetName = tmp != null ? tmp : property.getName(); - } - else { - targetName = property.getName(); - } - return targetName; - } - - /** - * Creates a concrete collection for the supplied interface - * @param interfaceType The interface - * @return ArrayList for List, TreeSet for SortedSet, LinkedHashSet for Set etc. - */ - public static Collection createConcreteCollection(Class interfaceType) { - Collection elements; - if (interfaceType.equals(List.class)) { - elements = new ArrayList(); - } - else if (interfaceType.equals(SortedSet.class)) { - elements = new TreeSet(); - } - else if (interfaceType.equals(Queue.class)) { - elements = new ArrayDeque(); - } - else { - elements = new LinkedHashSet(); - } - return elements; - } - - /** - * Get a declared field, searching super classes for the field if it is not found in the class. - * @param javaClass The class to search. - * @param propertyName The name of the field. - * @return The field, or null if it couldn't be found. - */ - public static Field getDeclaredField(Class javaClass, String propertyName) { - while (javaClass != null) { - Field[] declaredFields = javaClass.getDeclaredFields(); - for (Field declaredField : declaredFields) { - if (declaredField.getName().equals(propertyName)) { - return declaredField; - } - } - javaClass = javaClass.getSuperclass(); - } - return null; - } - - public static Class getGenericTypeForProperty(Class javaClass, String propertyName) { - Class genericClass = null; - - Field declaredField = getDeclaredField(javaClass, propertyName); - Type genericType = declaredField != null ? declaredField.getGenericType() : null; - if (genericType instanceof ParameterizedType) { - Type[] typeArguments = ((ParameterizedType) genericType).getActualTypeArguments(); - if (typeArguments.length>0) { - genericClass = (Class) typeArguments[0]; - } - } - return genericClass; - } - - public static Class getGenericTypeForMapProperty(Class javaClass, String propertyName, boolean isKeyType) { - Class genericClass = null; - - Field declaredField = getDeclaredField(javaClass, propertyName); - Type genericType = declaredField != null ? declaredField.getGenericType() : null; - if (genericType instanceof ParameterizedType) { - Type[] typeArguments = ((ParameterizedType) genericType).getActualTypeArguments(); - if (typeArguments.length>0) { - genericClass = (Class) typeArguments[isKeyType ? 0 : 1]; - } - } - return genericClass; - } - - public static Class getGenericType(Class propertyType) { - Class genericType = null; - TypeVariable[] typeParameters = propertyType.getTypeParameters(); - if (typeParameters != null && typeParameters.length>0) { - Type[] bounds = typeParameters[0].getBounds(); - if (bounds != null && bounds.length>0 && (bounds[0] instanceof Class)) { - genericType = (Class) bounds[0]; - } - } - return genericType; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/AbstractMappingAwareCustomTypeMarshaller.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/AbstractMappingAwareCustomTypeMarshaller.java deleted file mode 100644 index c39a78b38..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/AbstractMappingAwareCustomTypeMarshaller.java +++ /dev/null @@ -1,70 +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.mapping.engine.types; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.internal.MappingUtils; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.query.Query; -import org.springframework.dao.InvalidDataAccessResourceUsageException; - -/** - * Abstract implementation of CustomTypeMarshaller interface that handles the details of getting the correct mapped key for a property - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractMappingAwareCustomTypeMarshaller implements CustomTypeMarshaller{ - - private Class targetType; - - public AbstractMappingAwareCustomTypeMarshaller(Class targetType) { - this.targetType = targetType; - } - - public boolean supports(Datastore datastore) { - return true; - } - - public Class getTargetType() { - return this.targetType; - } - - public Object write(PersistentProperty property, T value, N nativeTarget) { - String targetName = MappingUtils.getTargetKey(property); - return writeInternal(property, targetName,value,nativeTarget); - } - - protected abstract Object writeInternal(PersistentProperty property, String key, T value, N nativeTarget); - - public Q query(PersistentProperty property, Query.PropertyCriterion criterion, Q nativeQuery) { - String targetName = MappingUtils.getTargetKey(property); - queryInternal(property, targetName, criterion, nativeQuery); - return nativeQuery; - } - - protected void queryInternal(PersistentProperty property, String key, Query.PropertyCriterion value, Q nativeQuery) { - throw new InvalidDataAccessResourceUsageException("Custom type [" + getTargetType().getName() + - "] does not support querying"); - } - - public T read(PersistentProperty property, N source) { - String targetName = MappingUtils.getTargetKey(property); - return readInternal(property, targetName, source); - } - - protected abstract T readInternal(PersistentProperty property, String key, N nativeSource); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/CustomTypeMarshaller.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/CustomTypeMarshaller.java deleted file mode 100644 index d5adfc408..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/CustomTypeMarshaller.java +++ /dev/null @@ -1,71 +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.mapping.engine.types; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.query.Query; - -/** - * Interface for defining custom datastore types beyond the simple and association - * types supported out of the box. - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface CustomTypeMarshaller { - - /** - * Whether the marshaller supports the given datastore type - * - * @param datastore The datastore type - * @return True if it is supported - */ - boolean supports(Datastore datastore); - - /** - * - * @return The target Java type - */ - Class getTargetType(); - - /** - * Converts a value to its native form - * - * @param property The property being converted - * @param value The value - * @param nativeTarget The nativeTarget - * @return The written value - */ - Object write(@SuppressWarnings("rawtypes") PersistentProperty property, T value, N nativeTarget); - - /** - * Populates a query - * - * @param property The property being converted - * @param criterion The criterion - * @param nativeQuery The nativeQuery - * @return The native query - */ - Q query(@SuppressWarnings("rawtypes") PersistentProperty property, Query.PropertyCriterion criterion, Q nativeQuery); - - /** - * Converts a value from its native form - * @param property The property being converted - * @param source The native form - * @return The converted type - */ - T read(@SuppressWarnings("rawtypes") PersistentProperty property, N source); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/graph/GraphDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/graph/GraphDatastore.java deleted file mode 100644 index e755d4957..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/graph/GraphDatastore.java +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (C) 2010 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.mapping.graph; - -import org.grails.datastore.mapping.core.Datastore; - -/** - * @author Guillaume Laforge - */ -public interface GraphDatastore extends Datastore {} \ No newline at end of file diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/engine/AbstractKeyValueEntityPersister.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/engine/AbstractKeyValueEntityPersister.java deleted file mode 100644 index 403466703..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/engine/AbstractKeyValueEntityPersister.java +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (C) 2010 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.mapping.keyvalue.engine; - -import org.springframework.context.ApplicationEventPublisher; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.NativeEntryEntityPersister; -import org.grails.datastore.mapping.keyvalue.mapping.config.Family; -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValue; -import org.grails.datastore.mapping.model.ClassMapping; -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.PropertyMapping; - -/** - * Abstract implementation of the EntityPersister abstract class - * for key/value style stores. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class AbstractKeyValueEntityPersister extends NativeEntryEntityPersister { - protected String entityFamily; - - protected AbstractKeyValueEntityPersister(MappingContext context, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher) { - super(context, entity, session, publisher); - entityFamily = getFamily(entity, classMapping); - } - - @Override - public String getEntityFamily() { - return entityFamily; - } - - @Override - public ClassMapping getClassMapping() { - return classMapping; - } - - @Override - protected String getNativePropertyKey(PersistentProperty prop) { - PropertyMapping pm = prop.getMapping(); - String propKey = null; - if (pm.getMappedForm()!=null) { - propKey = pm.getMappedForm().getKey(); - } - if (propKey == null) { - propKey = prop.getName(); - } - return propKey; - } - - protected String getFamily(PersistentEntity persistentEntity, ClassMapping cm) { - String table = null; - if (cm.getMappedForm() != null) { - table = cm.getMappedForm().getFamily(); - } - if (table == null) table = persistentEntity.getJavaClass().getName(); - return table; - } - - protected String getKeyspace(ClassMapping cm, String defaultValue) { - String keyspace = null; - if (cm.getMappedForm() != null) { - keyspace = cm.getMappedForm().getKeyspace(); - } - if (keyspace == null) keyspace = defaultValue; - return keyspace; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/engine/KeyValueEntry.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/engine/KeyValueEntry.java deleted file mode 100644 index ec05e5fd7..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/engine/KeyValueEntry.java +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (C) 2010 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.mapping.keyvalue.engine; - -import java.util.HashMap; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public class KeyValueEntry extends HashMap { - - private static final long serialVersionUID = 1; - - private String family; - - public KeyValueEntry(String family) { - this.family = family; - } - - public String getFamily() { - return family; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/AnnotationKeyValueMappingFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/AnnotationKeyValueMappingFactory.java deleted file mode 100644 index 3c9273090..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/AnnotationKeyValueMappingFactory.java +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (C) 2010 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.mapping.keyvalue.mapping.config; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; - -import org.springframework.core.annotation.AnnotationUtils; -import org.grails.datastore.mapping.annotation.Index; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.springframework.util.ReflectionUtils; - -/** - * Uses annotations to configure entity mappies - * - * @author Graeme Rocher - * @since 1.1 - */ -@SuppressWarnings("rawtypes") -public class AnnotationKeyValueMappingFactory extends KeyValueMappingFactory { - public AnnotationKeyValueMappingFactory(String keyspace) { - super(keyspace); - } - - @Override - public KeyValue createMappedForm(PersistentProperty mpp) { - final Class javaClass = mpp.getOwner().getJavaClass(); - final ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(javaClass); - - final PropertyDescriptor pd = cpf.getPropertyDescriptor(mpp.getName()); - final KeyValue kv = super.createMappedForm(mpp); - Index index = AnnotationUtils.getAnnotation(pd.getReadMethod(), Index.class); - - if (index == null) { - final Field field = ReflectionUtils.findField(javaClass, mpp.getName()); - if (field != null) { - ReflectionUtils.makeAccessible(field); - index = field.getAnnotation(Index.class); - } - } - if (index != null) { - kv.setIndex(true); - } - - return kv; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/Family.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/Family.java deleted file mode 100644 index 167c13424..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/Family.java +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (C) 2010 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.mapping.keyvalue.mapping.config; - -import org.grails.datastore.mapping.config.Entity; - -/** - *

    A Family is a grouping of KeyValue pairs and is typically composed - * of a keyspace and the family name.

    - * - *

    For example in Cassandra a Family relates to a ColumnFamily or in BigTable - * a Family relates to a an Entity kind.

    - * - *

    Other more simplistic key/value stores may just use prefixes on keys for the family

    - * - * @author Graeme Rocher - * @since 1.0 - */ -public class Family extends Entity{ - - private String keyspace; - private String family; - - public Family() { - } - - public Family(String keyspace, String family) { - this.keyspace = keyspace; - this.family = family; - } - - public String getKeyspace() { - return keyspace; - } - - public String getFamily() { - return family; - } - - public void setKeyspace(String keyspace) { - this.keyspace = keyspace; - } - - public void setFamily(String family) { - this.family = family; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/GormKeyValueMappingFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/GormKeyValueMappingFactory.java deleted file mode 100644 index c42dc779b..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/GormKeyValueMappingFactory.java +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2010 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.mapping.keyvalue.mapping.config; - -import org.grails.datastore.mapping.config.AbstractGormMappingFactory; -import org.grails.datastore.mapping.config.Property; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.IdentityMapping; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class GormKeyValueMappingFactory extends AbstractGormMappingFactory { - - private String keyspace; - - public GormKeyValueMappingFactory(String keyspace) { - this.keyspace = keyspace; - } - - @Override - public Family createMappedForm(PersistentEntity entity) { - Family family = super.createMappedForm(entity); - if (family.getKeyspace() == null) { - family.setKeyspace(keyspace); - } - if (family.getFamily() == null) { - family.setFamily(entity.getName()); - } - return family; - } - - @Override - public KeyValue createMappedForm(PersistentProperty mpp) { - KeyValue kv = super.createMappedForm(mpp); - if (kv.getKey() == null) { - kv.setKey(mpp.getName()); - } - return kv; - } - - @Override - protected Class getPropertyMappedFormType() { - return KeyValue.class; - } - - @Override - protected Class getEntityMappedFormType() { - return Family.class; - } - - @Override - protected IdentityMapping getIdentityMappedForm(final ClassMapping classMapping, KeyValue property) { - if (property != null) { - final String name = property.getName(); - if (name != null) { - final PersistentProperty idProperty = classMapping.getEntity().getPropertyByName(name); - return new IdentityMapping() { - public String[] getIdentifierName() { - return new String[]{name}; - } - - public ClassMapping getClassMapping() { - return classMapping; - } - - public Property getMappedForm() { - return idProperty.getMapping().getMappedForm(); - } - }; - } - } - return super.getIdentityMappedForm(classMapping, property); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValue.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValue.java deleted file mode 100644 index 5f7ec995d..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValue.java +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2010 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.mapping.keyvalue.mapping.config; - -import org.grails.datastore.mapping.config.Property; - -/** - *

    A KeyValue is a used to define the key used for a particular value

    - * - * @author Graeme Rocher - * @since 1.0 - */ -public class KeyValue extends Property { - - public KeyValue() { - } - - public KeyValue(String key) { - setTargetName(key); - } - - public String getKey() { - return getTargetName(); - } - - public void setKey(String key) { - setTargetName(key); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValueMappingContext.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValueMappingContext.java deleted file mode 100644 index 66a8d4c8b..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValueMappingContext.java +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (C) 2010 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.mapping.keyvalue.mapping.config; - -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.DefaultMappingConfigurationStrategy; -import org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; - -/** - * A MappingContext used to map objects to a Key/Value store - * - * @author Graeme Rocher - * @since 1.0 - */ -public class KeyValueMappingContext extends AbstractMappingContext { - protected MappingFactory mappingFactory; - protected MappingConfigurationStrategy syntaxStrategy; - private String keyspace; - public static final String GROOVY_OBJECT_CLASS = "groovy.lang.GroovyObject"; - - @Override - public void setCanInitializeEntities(boolean canInitializeEntities) { - super.setCanInitializeEntities(canInitializeEntities); - syntaxStrategy.setCanExpandMappingContext(false); - } - - /** - * Constructs a context using the given keyspace - * - * @param keyspace The keyspace, this is typically the application name - */ - public KeyValueMappingContext(String keyspace) { - Assert.notNull(keyspace, "Argument [keyspace] cannot be null"); - this.keyspace = keyspace; - initializeDefaultMappingFactory(keyspace); - - if (ClassUtils.isPresent(GROOVY_OBJECT_CLASS, KeyValueMappingContext.class.getClassLoader())) { - syntaxStrategy = new GormMappingConfigurationStrategy(mappingFactory); - } - else { - syntaxStrategy = new DefaultMappingConfigurationStrategy(mappingFactory); - } - } - - public String getKeyspace() { - return keyspace; - } - - protected void initializeDefaultMappingFactory(String keyspace) { - // TODO: Need to abstract the construction of these to support JPA syntax etc. - if (ClassUtils.isPresent(GROOVY_OBJECT_CLASS, KeyValueMappingContext.class.getClassLoader())) { - mappingFactory = new GormKeyValueMappingFactory(keyspace); - } - else { - mappingFactory = new AnnotationKeyValueMappingFactory(keyspace); - } - } - - public void setMappingFactory(MappingFactory mappingFactory) { - this.mappingFactory = mappingFactory; - } - - public void setSyntaxStrategy(MappingConfigurationStrategy syntaxStrategy) { - this.syntaxStrategy = syntaxStrategy; - } - - public MappingConfigurationStrategy getMappingSyntaxStrategy() { - return syntaxStrategy; - } - - @Override - public MappingFactory getMappingFactory() { - return mappingFactory; - } - - @Override - protected PersistentEntity createPersistentEntity(@SuppressWarnings("rawtypes") Class javaClass) { - return new KeyValuePersistentEntity(javaClass, this); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValueMappingFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValueMappingFactory.java deleted file mode 100644 index 39c720f27..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValueMappingFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (C) 2010 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.mapping.keyvalue.mapping.config; - -import org.grails.datastore.mapping.model.MappingFactory; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public class KeyValueMappingFactory extends MappingFactory { - - protected String keyspace; - - public KeyValueMappingFactory(String keyspace) { - this.keyspace = keyspace; - } - - @Override - public Family createMappedForm(PersistentEntity entity) { - return new Family(keyspace, entity.getName()); - } - - @Override - public KeyValue createMappedForm(@SuppressWarnings("rawtypes") PersistentProperty mpp) { - return new KeyValue(mpp.getName()); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValuePersistentEntity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValuePersistentEntity.java deleted file mode 100644 index 9287e9d90..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValuePersistentEntity.java +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2010 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.mapping.keyvalue.mapping.config; - -import org.grails.datastore.mapping.model.AbstractClassMapping; -import org.grails.datastore.mapping.model.AbstractPersistentEntity; -import org.grails.datastore.mapping.model.ClassMapping; -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.Embedded; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public class KeyValuePersistentEntity extends AbstractPersistentEntity{ - private Object mappedForm; - private KeyValueClassMapping classMapping; - - public KeyValuePersistentEntity(@SuppressWarnings("rawtypes") Class javaClass, MappingContext context) { - super(javaClass, context); - this.mappedForm = context.getMappingFactory().createMappedForm(KeyValuePersistentEntity.this); - this.classMapping = new KeyValueClassMapping(this, context); - } - - @SuppressWarnings("unchecked") - @Override - public ClassMapping getMapping() { - return classMapping; - } - - public class KeyValueClassMapping extends AbstractClassMapping { - public KeyValueClassMapping(PersistentEntity entity, MappingContext context) { - super(entity, context); - - } - @Override - public Family getMappedForm() { - return (Family) mappedForm; - } - } - - @Override - public PersistentEntity getParentEntity() { - Class superclass = this.javaClass.getSuperclass(); - if( superclass != null ) { - return context.getPersistentEntity(superclass.getName()); - } - - return null; - } - - @Override - public PersistentProperty getPropertyByName(String name) { - if(name != null && name.contains(".")) { - String[] props = name.split("\\."); - - // Get the embedded property type - PersistentProperty embeddedProp = super.getPropertyByName(props[0]); - if( embeddedProp instanceof Embedded) { - PersistentEntity embeddedEntity = ((Embedded) embeddedProp).getAssociatedEntity(); - return embeddedEntity.getPropertyByName(props[1]); - } - - return super.getPropertyByName(name); - } - else { - return super.getPropertyByName(name); - } - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractClassMapping.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractClassMapping.java deleted file mode 100644 index c679054a1..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractClassMapping.java +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model; - -import org.grails.datastore.mapping.config.Entity; - -/** - * Abstract implementation of the ClassMapping interface. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractClassMapping implements ClassMapping { - protected PersistentEntity entity; - protected MappingContext context; - private IdentityMapping identifierMapping; - - public AbstractClassMapping(PersistentEntity entity, MappingContext context) { - this.entity = entity; - this.context = context; - MappingConfigurationStrategy syntaxStrategy = context.getMappingSyntaxStrategy(); - this.identifierMapping = syntaxStrategy.getIdentityMapping(this); - } - - public PersistentEntity getEntity() { - return entity; - } - - public abstract T getMappedForm(); - - public IdentityMapping getIdentifier() { - return identifierMapping; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractMappingContext.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractMappingContext.java deleted file mode 100644 index 40fb3f91e..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractMappingContext.java +++ /dev/null @@ -1,324 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - -import org.grails.datastore.mapping.model.lifecycle.Initializable; -import org.grails.datastore.mapping.model.types.conversion.DefaultConversionService; -import org.grails.datastore.mapping.proxy.JavassistProxyFactory; -import org.grails.datastore.mapping.proxy.ProxyFactory; -import org.springframework.beans.BeanUtils; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.converter.Converter; -import org.springframework.core.convert.converter.ConverterRegistry; -import org.springframework.core.convert.support.GenericConversionService; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; -import org.springframework.validation.Validator; - -/** - * Abstract implementation of the MappingContext interface. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractMappingContext implements MappingContext, Initializable { - - public static final String GROOVY_PROXY_FACTORY_NAME = "org.grails.datastore.gorm.proxy.GroovyProxyFactory"; - public static final String JAVASIST_PROXY_FACTORY = "javassist.util.proxy.ProxyFactory"; - protected Collection persistentEntities = new ConcurrentLinkedQueue(); - protected Map persistentEntitiesByName = new ConcurrentHashMap(); - protected Map> persistentEntitiesByDiscriminator = new ConcurrentHashMap>(); - protected Map entityValidators = new ConcurrentHashMap(); - protected Collection eventListeners = new ConcurrentLinkedQueue(); - protected GenericConversionService conversionService = new DefaultConversionService(); - protected ProxyFactory proxyFactory; - private boolean canInitializeEntities = true; - private boolean initialized; - - public ConversionService getConversionService() { - return conversionService; - } - - public ConverterRegistry getConverterRegistry() { - return conversionService; - } - - public void setCanInitializeEntities(boolean canInitializeEntities) { - this.canInitializeEntities = canInitializeEntities; - } - - public abstract MappingFactory getMappingFactory(); - - public ProxyFactory getProxyFactory() { - if (this.proxyFactory == null) { - ClassLoader classLoader = AbstractMappingContext.class.getClassLoader(); - if (ClassUtils.isPresent(JAVASIST_PROXY_FACTORY, classLoader)) { - proxyFactory = DefaultProxyFactoryCreator.create(); - } - else if (ClassUtils.isPresent(GROOVY_PROXY_FACTORY_NAME, classLoader)) { - try { - proxyFactory = (ProxyFactory) BeanUtils.instantiate(ClassUtils.forName(GROOVY_PROXY_FACTORY_NAME, classLoader)); - } catch (ClassNotFoundException e) { - proxyFactory = DefaultProxyFactoryCreator.create(); - } - } - else { - proxyFactory = DefaultProxyFactoryCreator.create(); - } - } - return proxyFactory; - } - - public void addMappingContextListener(Listener listener) { - if (listener != null) - eventListeners.add(listener); - } - - public void setProxyFactory(ProxyFactory factory) { - if (factory != null) { - this.proxyFactory = factory; - } - } - - private static class DefaultProxyFactoryCreator { - public static ProxyFactory create() { - return new JavassistProxyFactory(); - } - } - - public void addTypeConverter(Converter converter) { - conversionService.addConverter(converter); - } - - /** - * Retrieves a validator for an entity - * - * @param entity The entity The entity - * @return The validator or null if there is none - */ - public Validator getEntityValidator(PersistentEntity entity) { - if (entity != null) { - return entityValidators.get(entity); - } - return null; - } - - /** - * Adds a validator for an entity - * - * @param entity The PersistentEntity The entity - * @param validator The validator The validator - */ - public void addEntityValidator(PersistentEntity entity, Validator validator) { - if (entity != null && validator != null) { - entityValidators.put(entity, validator); - } - } - - /** - * Adds an external PersistentEntity instance, one that is not managed and persisted by this context - * - * @param javaClass The Java class representing the entity - * @return The PersistentEntity instance - */ - public PersistentEntity addExternalPersistentEntity(Class javaClass) { - Assert.notNull(javaClass, "PersistentEntity class cannot be null"); - - PersistentEntity entity = persistentEntitiesByName.get(javaClass.getName()); - - if (entity == null) { - entity = addPersistentEntityInternal(javaClass, true, canInitializeEntities); - } - - return entity; - } - - /** - * Adds a PersistentEntity instance - * - * @param javaClass The Java class representing the entity - * @param override Whether to override an existing entity - * @return The PersistentEntity instance - */ - public PersistentEntity addPersistentEntity(Class javaClass, boolean override) { - Assert.notNull(javaClass, "PersistentEntity class cannot be null"); - if (override) { - return addPersistentEntityInternal(javaClass, false, canInitializeEntities); - } - return addPersistentEntity(javaClass); - } - - public Collection addPersistentEntities(Class... javaClasses) { - Collection entities = new ArrayList(); - - for (Class javaClass : javaClasses) { - PersistentEntity entity = createPersistentEntity(javaClass); - if(entity == null) continue; - - registerEntityWithContext(entity); - entities.add(entity); - - } - if(canInitializeEntities) { - for (PersistentEntity entity : entities) { - initializePersistentEntity(entity); - } - } - for (Listener eventListener : eventListeners) { - for (PersistentEntity entity : entities) { - eventListener.persistentEntityAdded(entity); - } - } - return entities; - } - - /** - * Adds a PersistentEntity instance - * - * @param javaClass The Java class representing the entity - * @return The PersistentEntity instance - */ - public PersistentEntity addPersistentEntity(Class javaClass) { - Assert.notNull(javaClass, "PersistentEntity class cannot be null"); - - PersistentEntity entity = persistentEntitiesByName.get(javaClass.getName()); - - if (entity == null) { - entity = addPersistentEntityInternal(javaClass, false, canInitializeEntities); - } - - return entity; - } - - private PersistentEntity addPersistentEntityInternal(Class javaClass, boolean isExternal, boolean isInitialize) { - PersistentEntity entity = createPersistentEntity(javaClass); - if (entity == null) { - return null; - } - entity.setExternal(isExternal); - - registerEntityWithContext(entity); - - if(isInitialize) { - initializePersistentEntity(entity); - } - - for (Listener eventListener : eventListeners) { - eventListener.persistentEntityAdded(entity); - } - return entity; - } - - private void registerEntityWithContext(PersistentEntity entity) { - persistentEntities.remove(entity); - persistentEntities.add(entity); - persistentEntitiesByName.put(entity.getName(), entity); - } - - public void initialize() { - for(PersistentEntity entity : persistentEntities) { - initializePersistentEntity(entity); - } - this.initialized = true; - } - - public boolean isInitialized() { - return initialized; - } - - private void initializePersistentEntity(PersistentEntity entity) { - try { - entity.initialize(); - } - catch(IllegalMappingException x) { - persistentEntities.remove(entity); - persistentEntitiesByName.remove(entity.getName()); - throw x; - } - - if (!entity.isRoot()) { - PersistentEntity root = entity.getRootEntity(); - Map children = persistentEntitiesByDiscriminator.get(root); - if (children == null) { - children = new ConcurrentHashMap(); - persistentEntitiesByDiscriminator.put(root, children); - } - children.put(entity.getDiscriminator(), entity); - } - } - - /** - * Returns true if the given entity is in an inheritance hierarchy - * - * @param entity The entity - * @return True if it is - */ - public boolean isInInheritanceHierarchy(PersistentEntity entity) { - if (entity != null) { - if (!entity.isRoot()) return true; - PersistentEntity rootEntity = entity.getRootEntity(); - final Map children = persistentEntitiesByDiscriminator.get(rootEntity); - if (children != null && !children.isEmpty()) { - return true; - } - } - return false; - } - - public PersistentEntity getChildEntityByDiscriminator(PersistentEntity root, String discriminator) { - final Map children = persistentEntitiesByDiscriminator.get(root); - if (children != null) { - return children.get(discriminator); - } - return null; - } - - protected abstract PersistentEntity createPersistentEntity(Class javaClass); - - public PersistentEntity createEmbeddedEntity(Class type) { - EmbeddedPersistentEntity embedded = new EmbeddedPersistentEntity(type, this); - embedded.initialize(); - return embedded; - } - - public Collection getPersistentEntities() { - return persistentEntities; - } - - public boolean isPersistentEntity(Class type) { - return type != null && getPersistentEntity(type.getName()) != null; - - } - - public boolean isPersistentEntity(Object value) { - return value != null && isPersistentEntity(value.getClass()); - } - - public PersistentEntity getPersistentEntity(String name) { - final int proxyIndicator = name.indexOf("_$$_"); - if (proxyIndicator > -1) { - name = name.substring(0, proxyIndicator); - } - - return persistentEntitiesByName.get(name); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentEntity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentEntity.java deleted file mode 100644 index f343bddf5..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentEntity.java +++ /dev/null @@ -1,293 +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.grails.datastore.mapping.model; - -import groovy.lang.Closure; - -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Modifier; -import java.util.*; - -import org.grails.datastore.mapping.config.Entity; -import org.grails.datastore.mapping.config.groovy.MappingConfigurationBuilder; -import org.grails.datastore.mapping.core.EntityCreationException; -import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.model.types.OneToMany; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.springframework.beans.BeanUtils; -import org.springframework.util.Assert; - -/** - * Abstract implementation to be subclasses on a per datastore basis - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class AbstractPersistentEntity implements PersistentEntity { - protected Class javaClass; - protected List persistentProperties; - protected List associations; - protected Map propertiesByName = new HashMap(); - protected MappingContext context; - protected PersistentProperty identity; - protected PersistentProperty version; - protected List persistentPropertyNames; - private String decapitalizedName; - protected Set owners; - private PersistentEntity parentEntity; - private boolean external; - private MappingProperties mappingProperties = new MappingProperties(); - private boolean initialized = false; - - public AbstractPersistentEntity(Class javaClass, MappingContext context) { - Assert.notNull(javaClass, "The argument [javaClass] cannot be null"); - this.javaClass = javaClass; - this.context = context; - decapitalizedName = Introspector.decapitalize(javaClass.getSimpleName()); - } - - public boolean isExternal() { - return external; - } - - public void setExternal(boolean external) { - this.external = external; - } - - public MappingContext getMappingContext() { - return context; - } - - public boolean isInitialized() { - return initialized; - } - - public void initialize() { - if(!initialized) { - - initialized = true; - - initializeMappingProperties(); - owners = context.getMappingSyntaxStrategy().getOwningEntities(javaClass, context); - persistentProperties = context.getMappingSyntaxStrategy().getPersistentProperties(this, context, getMapping()); - identity = resolveIdentifier(); - persistentPropertyNames = new ArrayList(); - associations = new ArrayList(); - - for (PersistentProperty persistentProperty : persistentProperties) { - - if (!(persistentProperty instanceof OneToMany)) { - persistentPropertyNames.add(persistentProperty.getName()); - } - - if (persistentProperty instanceof Association) { - associations.add((Association) persistentProperty); - } - - propertiesByName.put(persistentProperty.getName(), persistentProperty); - } - - Class superClass = javaClass.getSuperclass(); - if (superClass != null && - !superClass.equals(Object.class) && - !Modifier.isAbstract(superClass.getModifiers())) { - parentEntity = context.addPersistentEntity(superClass); - } - - getMapping().getMappedForm(); // initialize mapping - - if (mappingProperties.isVersioned()) { - version = propertiesByName.get("version"); - if(version == null) { - mappingProperties.setVersion(false); - } - } - } - - } - - protected PersistentProperty resolveIdentifier() { - return context.getMappingSyntaxStrategy().getIdentity(javaClass, context); - } - - public boolean hasProperty(String name, Class type) { - final PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(getJavaClass(), name); - return pd != null && pd.getPropertyType().equals(type); - } - - public boolean isIdentityName(String propertyName) { - return getIdentity().getName().equals(propertyName); - } - - public PersistentEntity getParentEntity() { - return parentEntity; - } - - public String getDiscriminator() { - return getJavaClass().getSimpleName(); - } - - public PersistentEntity getRootEntity() { - PersistentEntity root = this; - PersistentEntity parent = getParentEntity(); - while (parent != null) { - if(!parent.isInitialized()) { - parent.initialize(); - } - root = parent; - parent = parent.getParentEntity(); - } - return root; - } - - public boolean isRoot() { - return getParentEntity() == null; - } - - public boolean isOwningEntity(PersistentEntity owner) { - return owner != null && owners.contains(owner.getJavaClass()); - } - - public String getDecapitalizedName() { - return decapitalizedName; - } - - public List getPersistentPropertyNames() { - return persistentPropertyNames; - } - - public ClassMapping getMapping() { - return new AbstractClassMapping(this, context) { - @Override - public T getMappedForm() { - return null; - } - }; - } - - public Object newInstance() { - try { - return getJavaClass().newInstance(); - } catch (InstantiationException e) { - throw new EntityCreationException("Unable to create entity of type [" + getJavaClass().getName() + - "]: " + e.getMessage(), e); - } catch (IllegalAccessException e) { - throw new EntityCreationException("Unable to create entity of type [" + getJavaClass().getName() + - "]: " + e.getMessage(), e); - } - } - - public String getName() { - return javaClass.getName(); - } - - public PersistentProperty getIdentity() { - return identity; - } - - public PersistentProperty getVersion() { - return version; - } - - public boolean isVersioned() { - initializeMappingProperties(); - return mappingProperties.isVersioned(); - } - - public Class getJavaClass() { - return javaClass; - } - - public boolean isInstance(Object obj) { - return getJavaClass().isInstance(obj); - } - - public List getPersistentProperties() { - return persistentProperties; - } - - public List getAssociations() { - return associations; - } - - public PersistentProperty getPropertyByName(String name) { - return propertiesByName.get(name); - } - - private void initializeMappingProperties() { - if(!mappingProperties.isIntialized()) { - mappingProperties.setIntialized(true); - - MappingConfigurationBuilder builder = new MappingConfigurationBuilder( - mappingProperties, MappingProperties.class); - - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(getJavaClass()); - List values = - cpf.getStaticPropertyValuesFromInheritanceHierarchy(GormProperties.MAPPING, Closure.class); - for (int i = values.size(); i > 0; i--) { - Closure value = values.get(i - 1); - builder.evaluate(value); - } - - Object mappingVersion = builder.getProperties().get(MappingConfigurationBuilder.VERSION_KEY); - if (mappingVersion instanceof Boolean) { - mappingProperties.setVersion((Boolean)mappingVersion); - } - } - } - - private static class MappingProperties { - private Boolean version = true; - private boolean intialized = false; - - public boolean isIntialized() { - return intialized; - } - - public void setIntialized(boolean intialized) { - this.intialized = intialized; - } - - public void setVersion(final boolean version) { - this.version = version; - } - - public boolean isVersioned() { - return version == null ? true : version; - } - } - - @Override - public int hashCode() { - return javaClass.hashCode(); - } - - @Override - public boolean equals(Object o) { - if (o == null || !(o instanceof PersistentEntity)) return false; - if (this == o) return true; - - PersistentEntity other = (PersistentEntity) o; - return javaClass.equals(other.getJavaClass()); - } - - @Override - public String toString() { - return javaClass.getName(); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentProperty.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentProperty.java deleted file mode 100644 index 80254f05c..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentProperty.java +++ /dev/null @@ -1,75 +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.grails.datastore.mapping.model; - -import java.beans.PropertyDescriptor; - -import org.grails.datastore.mapping.config.Property; -import org.grails.datastore.mapping.reflect.NameUtils; - -/** - * Abstract implementation of the PersistentProperty interface that uses the - * PropertyDescriptor instance to establish name and type. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractPersistentProperty implements PersistentProperty { - protected PersistentEntity owner; - protected MappingContext context; - protected String name; - protected Class type; - - public AbstractPersistentProperty(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { - this.owner = owner; - this.context = context; - this.name = descriptor.getName(); - this.type = descriptor.getPropertyType(); - } - - public AbstractPersistentProperty(PersistentEntity owner, MappingContext context, String name, Class type) { - this.owner = owner; - this.context = context; - this.name = name; - this.type = type; - } - - public String getName() { - return name; - } - - public String getCapitilizedName() { - return NameUtils.capitalize(getName()); - } - - public Class getType() { - return type; - } - - public PersistentEntity getOwner() { - return owner; - } - - @Override - public String toString() { - return getName() + ":" + getType().getName(); - } - - public boolean isNullable() { - final Object mappedForm = getMapping().getMappedForm(); - return mappedForm instanceof Property && ((Property)mappedForm).isNullable(); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ClassMapping.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ClassMapping.java deleted file mode 100644 index f5573c9f6..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ClassMapping.java +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model; - -import org.grails.datastore.mapping.config.Entity; - -/** - * A class mapping is a mapping between a class and some external - * form such as a table, column family, or document (depending on the underlying data store). - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface ClassMapping { - - /** - * Obtains the PersistentEntity for this class mapping - * - * @return The PersistentEntity - */ - PersistentEntity getEntity(); - - /** - * Returns the mapped form of the class such as a Table, a Key Space, Document etc. - * @return The mapped representation - */ - T getMappedForm(); - - /** - * Returns details of the identifier used for this class - * - * @return The Identity - */ - IdentityMapping getIdentifier(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DatastoreConfigurationException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DatastoreConfigurationException.java deleted file mode 100644 index db908b515..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DatastoreConfigurationException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model; - -/** - * Exception thrown when something goes wrong configuring a datastore. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class DatastoreConfigurationException extends RuntimeException{ - - private static final long serialVersionUID = 1; - - public DatastoreConfigurationException(String message) { - super(message); - } - - public DatastoreConfigurationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/EmbeddedPersistentEntity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/EmbeddedPersistentEntity.java deleted file mode 100644 index ef812e14c..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/EmbeddedPersistentEntity.java +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright 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.mapping.model; - -/** - * Models an embedded entity - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class EmbeddedPersistentEntity extends AbstractPersistentEntity{ - public EmbeddedPersistentEntity(Class type, MappingContext ctx) { - super(type, ctx); - } - - @Override - protected PersistentProperty resolveIdentifier() { - return null; // no identifiers in embedded entities - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IdentityMapping.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IdentityMapping.java deleted file mode 100644 index e9d24736c..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IdentityMapping.java +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public interface IdentityMapping extends PropertyMapping { - - /** - * The identifier property name(s). Usually there is just one identifier - * name, however in the case of a composite or natural identifier there - * may be serveral. - * - * @return identifier names that make up the key - */ - String[] getIdentifierName(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IllegalMappingException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IllegalMappingException.java deleted file mode 100644 index ea42b1601..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/IllegalMappingException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model; - -/** - * Thrown when an error occurs reading the mapping between object and datastore. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class IllegalMappingException extends RuntimeException { - - private static final long serialVersionUID = 1; - - public IllegalMappingException(String s) { - super(s); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingConfigurationStrategy.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingConfigurationStrategy.java deleted file mode 100644 index c40bc9fb6..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingConfigurationStrategy.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.grails.datastore.mapping.model; - -import java.util.List; -import java.util.Set; - -/** - *

    This interface defines a strategy for reading how - * persistent properties are defined in a persistent entity.

    - * - *

    Subclasses can implement this interface in order to provide - * a different mechanism for mapping entities such as annotations or XML.

    - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public interface MappingConfigurationStrategy { - - /** - * Tests whether the given class is a persistent entity - * - * @param javaClass The java class - * @return true if it is a persistent entity - */ - boolean isPersistentEntity(Class javaClass); - - /** - * @see #getPersistentProperties(Class, MappingContext, ClassMapping) - */ - List getPersistentProperties(Class javaClass, MappingContext context); - - /** - * @see #getPersistentProperties(Class, MappingContext, ClassMapping) - */ - List getPersistentProperties(PersistentEntity entity, MappingContext context, ClassMapping classMapping); - - /** - * Obtains a List of PersistentProperty instances for the given Mapped class - * - * @param javaClass The Java class - * @param context The MappingContext instance - * @param mapping The mapping for this class - * @return The PersistentProperty instances - */ - List getPersistentProperties(Class javaClass, MappingContext context, ClassMapping mapping); - - /** - * Obtains the identity of a persistent entity - * - * @param javaClass The Java class - * @param context The MappingContext - * @return A PersistentProperty instance - */ - PersistentProperty getIdentity(Class javaClass, MappingContext context); - - /** - * Obtains the default manner in which identifiers are mapped. In GORM - * this is just using a property called 'id', but in other frameworks this - * may differ. For example JPA expects an annotated @Id property - * - * @return The default identifier mapping - * @param classMapping The ClassMapping instance - */ - IdentityMapping getDefaultIdentityMapping(ClassMapping classMapping); - - /** - * Returns a set of entities that "own" the given entity. Ownership - * dictates default cascade strategies. So if entity A owns entity B - * then saves, updates and deletes will cascade from A to B - * - * @param javaClass The Java class - * @param context The MappingContext - * @return A Set of owning classes - */ - Set getOwningEntities(Class javaClass, MappingContext context); - - /** - * Obtains the identity mapping for the specified class mapping - * - * @param classMapping The class mapping - * @return The identity mapping - */ - IdentityMapping getIdentityMapping(ClassMapping classMapping); - - /** - * Whether the strategy can add new entities to the mapping context - */ - void setCanExpandMappingContext(boolean canExpandMappingContext); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingContext.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingContext.java deleted file mode 100644 index 4155580eb..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingContext.java +++ /dev/null @@ -1,200 +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.grails.datastore.mapping.model; - -import java.util.Collection; - -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.converter.Converter; -import org.springframework.core.convert.converter.ConverterRegistry; -import org.grails.datastore.mapping.proxy.ProxyFactory; -import org.springframework.validation.Validator; - -/** - *

    Defines the overall context including all known - * PersistentEntity instances and methods to obtain instances on demand

    - * - *

    This interface is used internally to establish associations - * between entities and also at runtime to obtain entities by name

    - * - *

    The generic type parameters T & R are used to specify the - * mapped form of a class (example Table) and property (example Column) respectively.

    - * - *

    Uses instances of the {@link org.grails.datastore.mapping.core.Datastore} interface to - * discover how to persist objects

    - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public interface MappingContext { - - /** - * Obtains a list of PersistentEntity instances - * - * @return A list of PersistentEntity instances - */ - Collection getPersistentEntities(); - - /** - * Obtains a PersistentEntity by name - * - * @param name The name of the entity - * @return The entity or null - */ - PersistentEntity getPersistentEntity(String name); - - /** - * Returns true if the given entity is in an inheritance hierarchy - * @param entity The entity - * @return True if it is - */ - boolean isInInheritanceHierarchy(PersistentEntity entity); - /** - * Obtains a child of the given root entity using the given discriminator - * @param root The root entity - * @param discriminator The discriminator - * @return The child entity or null if non exists - */ - PersistentEntity getChildEntityByDiscriminator(PersistentEntity root, String discriminator); - - /** - * Adds several PersistentEntity instances - * - * @param javaClasses The Java class representing the entity - * @return The PersistentEntity instance - */ - Collection addPersistentEntities(Class...javaClasses); - /** - * Adds a PersistentEntity instance - * - * @param javaClass The Java class representing the entity - * @return The PersistentEntity instance - */ - PersistentEntity addPersistentEntity(Class javaClass); - - /** - * Adds a PersistentEntity instance - * - * @param javaClass The Java class representing the entity - * @param override Whether to override an existing entity - * - * @return The PersistentEntity instance - */ - PersistentEntity addPersistentEntity(Class javaClass, boolean override); - - /** - * Adds a persistent entity that is not mapped by this MappingContext instance. - * Used for cross store persistence - * - * @param javaClass The Java class - * @return The persistent entity - */ - PersistentEntity addExternalPersistentEntity(Class javaClass); - - /** - * Adds a validator to be used by the entity for validation - * @param entity The PersistentEntity - * @param validator The validator - */ - void addEntityValidator(PersistentEntity entity, Validator validator); - - /** - * Add a converter used to convert property values to and from the datastore - * - * @param converter The converter to add - */ - void addTypeConverter(Converter converter); - - /** - * Obtains the ConversionService instance to use for type conversion - * @return The conversion service instance - */ - ConversionService getConversionService(); - - /** - * Obtains the converter registry - * - * @return The converter registry used for type conversion - */ - ConverterRegistry getConverterRegistry(); - - /** - * Obtains a validator for the given entity - * @param entity The entity - * @return A validator or null if none exists for the given entity - */ - Validator getEntityValidator(PersistentEntity entity); - - /** - * Returns the syntax reader used to interpret the entity - * mapping syntax - * - * @return The SyntaxReader - */ - MappingConfigurationStrategy getMappingSyntaxStrategy(); - - /** - * Obtains the MappingFactory instance - * @return The mapping factory instance - */ - MappingFactory getMappingFactory(); - - /** - * Returns whether the specified class is a persistent entity - * @param type The type to check - * @return True if it is - */ - boolean isPersistentEntity(Class type); - - /** - * Returns whether the specified value is a persistent entity - * @param value The value to check - * @return True if it is - */ - boolean isPersistentEntity(Object value); - - /** - * Factory used for creating proxies - * @return The proxy factory - */ - ProxyFactory getProxyFactory(); - - /** - * Factory to use for creating proxies - * @param factory The proxy factory - */ - void setProxyFactory(ProxyFactory factory); - - /** - * Adds a new mapping context listener instance - * @param listener The listener - */ - void addMappingContextListener(Listener listener); - - PersistentEntity createEmbeddedEntity(Class type); - - /** - * Implementors can register for events when the mapping context changes - */ - interface Listener { - - /** - * Fired when a new entity is added - * @param entity The entity - */ - void persistentEntityAdded(PersistentEntity entity); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingFactory.java deleted file mode 100644 index 2f3ec7f94..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingFactory.java +++ /dev/null @@ -1,374 +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.grails.datastore.mapping.model; - -import java.beans.PropertyDescriptor; -import java.io.Serializable; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.URI; -import java.net.URL; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.GregorianCalendar; -import java.util.HashSet; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.TimeZone; -import java.util.concurrent.ConcurrentHashMap; - -import org.grails.datastore.mapping.config.Entity; -import org.grails.datastore.mapping.config.Property; -import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller; -import org.grails.datastore.mapping.model.types.Basic; -import org.grails.datastore.mapping.model.types.Custom; -import org.grails.datastore.mapping.model.types.Embedded; -import org.grails.datastore.mapping.model.types.EmbeddedCollection; -import org.grails.datastore.mapping.model.types.Identity; -import org.grails.datastore.mapping.model.types.ManyToMany; -import org.grails.datastore.mapping.model.types.ManyToOne; -import org.grails.datastore.mapping.model.types.OneToMany; -import org.grails.datastore.mapping.model.types.OneToOne; -import org.grails.datastore.mapping.model.types.Simple; -import org.grails.datastore.mapping.model.types.ToOne; - -/** - *

    An abstract factory for creating persistent property instances.

    - * - *

    Subclasses should implement the createMappedForm method in order to - * provide a mechanisms for representing the property in a form appropriate - * for mapping to the underlying datastore. Example:

    - * - *
    - *  
    - *      class RelationalPropertyFactory extends PropertyFactory {
    - *            public Column createMappedForm(PersistentProperty mpp) {
    - *                return new Column(mpp)
    - *            }
    - *      }
    - *  
    - * 
    - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class MappingFactory { - - public static final String IDENTITY_PROPERTY = "id"; - public static final Set SIMPLE_TYPES; - - static { - SIMPLE_TYPES = Collections.unmodifiableSet(new HashSet(Arrays.asList( - boolean.class.getName(), - long.class.getName(), - short.class.getName(), - int.class.getName(), - byte.class.getName(), - float.class.getName(), - double.class.getName(), - char.class.getName(), - Boolean.class.getName(), - Long.class.getName(), - Short.class.getName(), - Integer.class.getName(), - Byte.class.getName(), - Float.class.getName(), - Double.class.getName(), - Character.class.getName(), - String.class.getName(), - java.util.Date.class.getName(), - Time.class.getName(), - Timestamp.class.getName(), - java.sql.Date.class.getName(), - BigDecimal.class.getName(), - BigInteger.class.getName(), - Locale.class.getName(), - Calendar.class.getName(), - GregorianCalendar.class.getName(), - java.util.Currency.class.getName(), - TimeZone.class.getName(), - Object.class.getName(), - Class.class.getName(), - byte[].class.getName(), - Byte[].class.getName(), - char[].class.getName(), - Character[].class.getName(), - Blob.class.getName(), - Clob.class.getName(), - Serializable.class.getName(), - URI.class.getName(), - URL.class.getName(), - "org.bson.types.ObjectId"))); - } - - private static Map typeConverterMap = new ConcurrentHashMap(); - - public static void registerCustomType(CustomTypeMarshaller marshallerCustom) { - typeConverterMap.put(marshallerCustom.getTargetType(), marshallerCustom); - } - - public boolean isSimpleType(Class propType) { - if (propType == null) return false; - if (propType.isEnum()) return true; - if (propType.isArray()) { - return isSimpleType(propType.getComponentType()); - } - final String typeName = propType.getName(); - return isSimpleType(typeName); - } - - public static boolean isSimpleType(final String typeName) { - return SIMPLE_TYPES.contains(typeName); - } - - /** - * Creates the mapped form of a persistent entity - * - * @param entity The entity - * @return The mapped form - */ - public abstract R createMappedForm(PersistentEntity entity); - - /** - * Creates the mapped form of a PersistentProperty instance - * @param mpp The PersistentProperty instance - * @return The mapped form - */ - public abstract T createMappedForm(PersistentProperty mpp); - - /** - * Creates an identifier property - * - * @param owner The owner - * @param context The context - * @param pd The PropertyDescriptor - * @return An Identity instance - */ - public Identity createIdentity(PersistentEntity owner, MappingContext context, PropertyDescriptor pd) { - return new Identity(owner, context, pd) { - PropertyMapping propertyMapping = createPropertyMapping(this, owner); - public PropertyMapping getMapping() { - return propertyMapping; - } - }; - } - - /** - * Creates a custom prpoerty type - * - * @param owner The owner - * @param context The context - * @param pd The PropertyDescriptor - * @return A custom property type - */ - public Custom createCustom(PersistentEntity owner, MappingContext context, PropertyDescriptor pd) { - CustomTypeMarshaller customTypeMarshaller = typeConverterMap.get(pd.getPropertyType()); - if (customTypeMarshaller == null) { - throw new IllegalStateException("Cannot create a custom type without a type converter for type " + pd.getPropertyType()); - } - return new Custom(owner, context, pd, customTypeMarshaller) { - PropertyMapping propertyMapping = createPropertyMapping(this, owner); - public PropertyMapping getMapping() { - return propertyMapping; - } - }; - } - - /** - * Creates a simple property type used for mapping basic types such as String, long, integer etc. - * - * @param owner The owner - * @param context The MappingContext - * @param pd The PropertyDescriptor - * @return A Simple property type - */ - public Simple createSimple(PersistentEntity owner, MappingContext context, PropertyDescriptor pd) { - return new Simple(owner, context, pd) { - PropertyMapping propertyMapping = createPropertyMapping(this, owner); - public PropertyMapping getMapping() { - return propertyMapping; - } - }; - } - - protected PropertyMapping createPropertyMapping(final PersistentProperty property, final PersistentEntity owner) { - return new PropertyMapping() { - private T mappedForm = createMappedForm(property); - public ClassMapping getClassMapping() { - return owner.getMapping(); - } - public T getMappedForm() { - return mappedForm; - } - }; - } - - /** - * Creates a one-to-one association type used for mapping a one-to-one association between entities - * - * @param entity The entity - * @param context The context - * @param property The property - * @return The ToOne instance - */ - public ToOne createOneToOne(PersistentEntity entity, MappingContext context, PropertyDescriptor property) { - return new OneToOne(entity, context, property) { - PropertyMapping propertyMapping = createPropertyMapping(this, owner); - public PropertyMapping getMapping() { - return propertyMapping; - } - }; - } - - /** - * Creates a many-to-one association type used for a mapping a many-to-one association between entities - * - * @param entity The entity - * @param context The context - * @param property The property - * @return The ToOne instance - */ - public ToOne createManyToOne(PersistentEntity entity, MappingContext context, PropertyDescriptor property) { - return new ManyToOne(entity, context, property) { - PropertyMapping propertyMapping = createPropertyMapping(this, owner); - public PropertyMapping getMapping() { - return propertyMapping; - } - }; - - } - - /** - * Creates a {@link OneToMany} type used to model a one-to-many association between entities - * - * @param entity The entity - * @param context The context - * @param property The property - * @return The {@link OneToMany} instance - */ - public OneToMany createOneToMany(PersistentEntity entity, MappingContext context, PropertyDescriptor property) { - return new OneToMany(entity, context, property) { - PropertyMapping propertyMapping = createPropertyMapping(this, owner); - public PropertyMapping getMapping() { - return propertyMapping; - } - }; - - } - - /** - * Creates a {@link ManyToMany} type used to model a many-to-many association between entities - * - * @param entity The entity - * @param context The context - * @param property The property - * @return The {@link ManyToMany} instance - */ - public ManyToMany createManyToMany(PersistentEntity entity, MappingContext context, PropertyDescriptor property) { - return new ManyToMany(entity, context, property) { - PropertyMapping propertyMapping = createPropertyMapping(this, owner); - public PropertyMapping getMapping() { - return propertyMapping; - } - }; - } - - /** - * Creates an {@link Embedded} type used to model an embedded association (composition) - * - * @param entity The entity - * @param context The context - * @param property The property - * @return The {@link Embedded} instance - */ - public Embedded createEmbedded(PersistentEntity entity, - MappingContext context, PropertyDescriptor property) { - return new Embedded(entity, context, property) { - PropertyMapping propertyMapping = createPropertyMapping(this, owner); - public PropertyMapping getMapping() { - return propertyMapping; - } - }; - } - - /** - * Creates an {@link EmbeddedCollection} type used to model an embedded collection association (composition). - * - * @param entity The entity - * @param context The context - * @param property The property - * @return The {@link Embedded} instance - */ - public EmbeddedCollection createEmbeddedCollection(PersistentEntity entity, - MappingContext context, PropertyDescriptor property) { - return new EmbeddedCollection(entity, context, property) { - PropertyMapping propertyMapping = createPropertyMapping(this, owner); - public PropertyMapping getMapping() { - return propertyMapping; - } - }; - } - - /** - * Creates a {@link Basic} collection type - * - * @param entity The entity - * @param context The context - * @param property The property - * @return The Basic collection type - */ - public Basic createBasicCollection(PersistentEntity entity, - MappingContext context, PropertyDescriptor property) { - return new Basic(entity, context, property) { - PropertyMapping propertyMapping = createPropertyMapping(this, owner); - public PropertyMapping getMapping() { - return propertyMapping; - } - }; - } - - public static boolean isCustomType(Class propertyType) { - return typeConverterMap.containsKey(propertyType); - } - - public IdentityMapping createIdentityMapping(final ClassMapping classMapping) { - return createDefaultIdentityMapping(classMapping); - } - - public IdentityMapping createDefaultIdentityMapping(final ClassMapping classMapping) { - return new IdentityMapping() { - - public String[] getIdentifierName() { - return new String[] { IDENTITY_PROPERTY }; - } - - public ClassMapping getClassMapping() { - return classMapping; - } - - public Property getMappedForm() { - // no custom mapping - return null; - } - }; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentEntity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentEntity.java deleted file mode 100644 index 7cfc4a2f4..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentEntity.java +++ /dev/null @@ -1,185 +0,0 @@ -/* Copyright 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.mapping.model; - -import java.util.List; - -import org.grails.datastore.mapping.model.lifecycle.Initializable; -import org.grails.datastore.mapping.model.types.Association; - -/** - * Represents a persistent entity. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public interface PersistentEntity extends Initializable { - - /** - * The entity name including any package prefix - * - * @return The entity name - */ - String getName(); - - /** - * Whether this PersistentEntity is mapped using a different store. Used for cross store persistence. - * - * @return true if this entity is externally mapped - */ - boolean isExternal(); - - /** - * Whether this PersistentEntity is mapped using a different store. Used for cross store persistence. - * @param external true if this entity is externally mapped - */ - void setExternal(boolean external); - - /** - * Returns the identity of the instance - * - * @return The identity - */ - PersistentProperty getIdentity(); - - /** - * Returns the version property. - * - * @return the property - */ - PersistentProperty getVersion(); - - /** - * Is the entity versioned for optimistic locking. - * - * @return true if versioned - */ - boolean isVersioned(); - - /** - * A list of properties to be persisted - * @return A list of PersistentProperty instances - */ - List getPersistentProperties(); - - /** - * A list of the associations for this entity. This is typically - * a subset of the list returned by {@link #getPersistentProperties()} - * - * @return A list of associations - */ - List getAssociations(); - - /** - * Obtains a PersistentProperty instance by name - * - * @param name The name of the property - * @return The PersistentProperty or null if it doesn't exist - */ - PersistentProperty getPropertyByName(String name); - - /** - * @return The underlying Java class for this entity - */ - Class getJavaClass(); - - /** - * Tests whether the given instance is an instance of this persistent entity - * - * @param obj The object - * @return True if it is - */ - boolean isInstance(Object obj); - - /** - * Defines the mapping between this persistent entity - * and an external form - * - * @return The ClassMapping instance - */ - ClassMapping getMapping(); - - /** - * Constructs a new instance - * @return The new instnace - */ - Object newInstance(); - - /** - * A list of property names that a persistent - * @return A List of strings - */ - List getPersistentPropertyNames(); - - /** - * @return Returns the name of the class decapitalized form - */ - String getDecapitalizedName(); - - /** - * Returns whether the specified entity asserts ownership over this - * entity - * - * @param owner The owning entity - * @return True if it does own this entity - */ - boolean isOwningEntity(PersistentEntity owner); - - /** - * Returns the parent entity of this entity - * @return The ParentEntity instance - */ - PersistentEntity getParentEntity(); - - /** - * Obtains the root entity of an inheritance hierarchy - * @return The root entity - */ - PersistentEntity getRootEntity(); - - /** - * Whether this entity is a root entity - * @return True if it is a root entity - */ - boolean isRoot(); - - /** - * The discriminator used when persisting subclasses of an inheritance hierarchy - * @return The discriminator - */ - String getDiscriminator(); - - /** - * Obtains the MappingContext where this PersistentEntity is defined - * @return The MappingContext instance - */ - MappingContext getMappingContext(); - - /** - * Checks whether an entity has a bean property of the given name and type - * @param name The name - * @param type The type - * @return True if it does - */ - boolean hasProperty(String name, Class type); - - /** - * True if the given property is the identifier - * @param propertyName the property name - * @return True if it is the identifier - */ - boolean isIdentityName(String propertyName); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentProperty.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentProperty.java deleted file mode 100644 index ec6ec5115..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentProperty.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.grails.datastore.mapping.model; - -import org.grails.datastore.mapping.config.Property; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public interface PersistentProperty { - - /** - * The name of the property - * @return The property name - */ - String getName(); - - /** - * The name with the first letter in upper case as per Java bean conventions - * @return The capitilized name - */ - String getCapitilizedName(); - - /** - * The type of the property - * @return The property type - */ - Class getType(); - - /** - * Specifies the mapping between this property and an external form - * such as a column, key/value pair etc. - * - * @return The PropertyMapping instance - */ - PropertyMapping getMapping(); - - /** - * Obtains the owner of this persistent property - * - * @return The owner - */ - PersistentEntity getOwner(); - - /** - * Whether the property can be set to null - * - * @return True if it can - */ - boolean isNullable(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PropertyMapping.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PropertyMapping.java deleted file mode 100644 index 2747d4c3f..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PropertyMapping.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.grails.datastore.mapping.model; - -import org.grails.datastore.mapping.config.Property; - -/** - * Interface for a property mapping which specifies what or where a particular property is mapped to. - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface PropertyMapping { - - /** - * Retrieves the ClassMapping instance of the owning class - * - * @return The ClassMapping instance - */ - @SuppressWarnings("rawtypes") - ClassMapping getClassMapping(); - - /** - * Returns the mapped form of the property such as a Column, a Key/Value pair, attribute etc. - * @return The mapped representation - */ - T getMappedForm(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/DefaultMappingConfigurationStrategy.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/DefaultMappingConfigurationStrategy.java deleted file mode 100644 index 729e718a3..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/DefaultMappingConfigurationStrategy.java +++ /dev/null @@ -1,161 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.config; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.grails.datastore.mapping.config.Property; -import org.springframework.core.annotation.AnnotationUtils; -import org.grails.datastore.mapping.annotation.Entity; -import org.grails.datastore.mapping.annotation.Id; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.IdentityMapping; -import org.grails.datastore.mapping.model.IllegalMappingException; -import org.grails.datastore.mapping.model.MappingConfigurationStrategy; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.MappingFactory; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; - -/** - * @author Graeme Rocher - * @since 1.1 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class DefaultMappingConfigurationStrategy implements MappingConfigurationStrategy { - - private static final Set EXCLUDED_PROPERTIES = new HashSet(Arrays.asList("class", "metaClass")); - - private MappingFactory propertyFactory; - - public DefaultMappingConfigurationStrategy(MappingFactory propertyFactory) { - this.propertyFactory = propertyFactory; - } - - private boolean isExcludedProperty(String propertyName, ClassMapping classMapping, Collection transients) { - IdentityMapping id = classMapping != null ? classMapping.getIdentifier() : null; - return id != null && id.getIdentifierName()[0].equals(propertyName) || EXCLUDED_PROPERTIES.contains(propertyName) || transients.contains(propertyName); - } - - public boolean isPersistentEntity(Class javaClass) { - return AnnotationUtils.findAnnotation(javaClass, Entity.class) != null; - } - - public List getPersistentProperties(Class javaClass, MappingContext context) { - return getPersistentProperties(javaClass, context, null); - } - - /** - * @see #getPersistentProperties(Class, org.grails.datastore.mapping.model.MappingContext, org.grails.datastore.mapping.model.ClassMapping) - */ - public List getPersistentProperties(PersistentEntity entity, MappingContext context, ClassMapping classMapping) { - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass()); - PropertyDescriptor[] descriptors = cpf.getPropertyDescriptors(); - final ArrayList persistentProperties = new ArrayList(); - - for (PropertyDescriptor descriptor : descriptors) { - final String propertyName = descriptor.getName(); - if (isExcludedProperty(propertyName, classMapping, Collections.emptyList())) continue; - Class propertyType = descriptor.getPropertyType(); - if (propertyFactory.isSimpleType(propertyType)) { - persistentProperties.add(propertyFactory.createSimple(entity, context, descriptor)); - } - else if (MappingFactory.isCustomType(propertyType)) { - persistentProperties.add(propertyFactory.createCustom(entity, context, descriptor)); - } - } - return persistentProperties; - } - - private PersistentEntity getPersistentEntity(Class javaClass, MappingContext context, ClassMapping classMapping) { - PersistentEntity entity; - if (classMapping != null) - entity = classMapping.getEntity(); - else - entity = context.getPersistentEntity(javaClass.getName()); - return entity; - } - - public List getPersistentProperties(Class javaClass, MappingContext context, ClassMapping mapping) { - PersistentEntity entity = getPersistentEntity(javaClass, context, mapping); - if (entity != null) { - return getPersistentProperties(entity, context, mapping); - } - - return Collections.emptyList(); - } - - public PersistentProperty getIdentity(Class javaClass, MappingContext context) { - final ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(javaClass); - - for (Field field : cpf.getJavaClass().getDeclaredFields()) { - final Id annotation = field.getAnnotation(Id.class); - if (annotation != null) { - PersistentEntity entity = context.getPersistentEntity(javaClass.getName()); - PropertyDescriptor pd = cpf.getPropertyDescriptor(field.getName()); - return propertyFactory.createIdentity(entity, context, pd); - } - } - throw new IllegalMappingException("No identifier specified for persistent class: " + javaClass.getName()); - } - - /** - * Obtains the identity mapping for the specified class mapping - * - * @param classMapping The class mapping - * @return The identity mapping - */ - public IdentityMapping getIdentityMapping(ClassMapping classMapping) { - return getDefaultIdentityMapping(classMapping); - } - - public void setCanExpandMappingContext(boolean canExpandMappingContext) { - // noop - } - - public IdentityMapping getDefaultIdentityMapping(final ClassMapping classMapping) { - - final PersistentEntity e = classMapping.getEntity(); - final PersistentProperty identity = getIdentity(e.getJavaClass(), e.getMappingContext()); - return new IdentityMapping() { - - public String[] getIdentifierName() { - return new String[] { identity.getName() }; - } - - public ClassMapping getClassMapping() { - return classMapping; - } - - public Property getMappedForm() { - // no custom mapping - return null; - } - }; - } - - public Set getOwningEntities(Class javaClass, MappingContext context) { - return Collections.emptySet(); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormMappingConfigurationStrategy.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormMappingConfigurationStrategy.java deleted file mode 100755 index 0fdaf5568..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormMappingConfigurationStrategy.java +++ /dev/null @@ -1,829 +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.grails.datastore.mapping.model.config; - -import groovy.lang.Closure; -import groovy.lang.GroovyObject; - -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.persistence.Entity; - -import org.grails.datastore.mapping.engine.internal.MappingUtils; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.IdentityMapping; -import org.grails.datastore.mapping.model.IllegalMappingException; -import org.grails.datastore.mapping.model.MappingConfigurationStrategy; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.MappingFactory; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.types.*; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.grails.datastore.mapping.reflect.ReflectionUtils; -import org.springframework.util.StringUtils; - -import static org.grails.datastore.mapping.model.config.GormProperties.*; - -/** - *

    This implementation of the MappingConfigurationStrategy interface - * will interpret GORM-style syntax for defining entities and associations. - *

    - * - *

    Example in Groovy code:

    - * - *
    - *  
    - *      class Author {
    - *          String name
    - *          static hasMany = [books:Book]
    - *      }
    - *      class Book {
    - *         String title
    - *         static belongsTo = [author:Author]
    -        }
    - *  
    - *
    - * 
    - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class GormMappingConfigurationStrategy implements MappingConfigurationStrategy { - private static final String IDENTITY_PROPERTY = IDENTITY; - private static final String VERSION_PROPERTY = VERSION; - private MappingFactory propertyFactory; - private static final Set EXCLUDED_PROPERTIES = new HashSet(Arrays.asList("class", "metaClass")); - private boolean canExpandMappingContext = true; - - public GormMappingConfigurationStrategy(MappingFactory propertyFactory) { - this.propertyFactory = propertyFactory; - } - - /** - * Whether the strategy can add new entities to the mapping context - */ - public void setCanExpandMappingContext(boolean canExpandMappingContext) { - this.canExpandMappingContext = canExpandMappingContext; - } - - /** - * Tests whether an class is a persistent entity - * - * Based on the same method in Grails core within the DomainClassArtefactHandler class - * @param clazz The java class - * - * @return True if it is a persistent entity - */ - public boolean isPersistentEntity(Class clazz) { - // its not a closure - if (clazz == null) return false; - if (Closure.class.isAssignableFrom(clazz)) { - return false; - } - if (Enum.class.isAssignableFrom(clazz)) return false; - if (clazz.isAnnotationPresent(Entity.class)) { - return true; - } - // this is done so we don't need a statically typed reference to the Grails annotation - for (Annotation annotation : clazz.getAnnotations()) { - if (annotation.toString().equals("@grails.persistence.Entity()")) return true; - } - Class testClass = clazz; - boolean result = false; - while (testClass != null && !testClass.equals(GroovyObject.class) && - !testClass.equals(Object.class)) { - try { - // make sure the identify and version field exist - testClass.getDeclaredField(IDENTITY_PROPERTY); - testClass.getDeclaredField(VERSION_PROPERTY); - - // passes all conditions return true - result = true; - break; - } catch (SecurityException e) { - // ignore - } catch (NoSuchFieldException e) { - // ignore - } - testClass = testClass.getSuperclass(); - } - return result; - } - - public List getPersistentProperties(Class javaClass, MappingContext context) { - return getPersistentProperties(javaClass, context, null); - } - - public List getPersistentProperties(Class javaClass, MappingContext context, ClassMapping classMapping) { - PersistentEntity entity = getPersistentEntity(javaClass, context, classMapping); - - if (entity != null) { - return getPersistentProperties(entity, context, classMapping); - } - return Collections.emptyList(); - } - - public List getPersistentProperties(PersistentEntity entity, MappingContext context, ClassMapping classMapping) { - final List persistentProperties = new ArrayList(); - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass()); - - // owners are the classes that own this class - Collection embedded = getCollectionStaticProperty(cpf, EMBEDDED); - Collection transients = getCollectionStaticProperty(cpf, TRANSIENT); - - // hasMany associations for defining one-to-many and many-to-many - Map hasManyMap = getAssociationMap(cpf); - // mappedBy for defining by which property an association is mapped - Map mappedByMap = getMapStaticProperty(cpf, MAPPED_BY); - // hasOne for declaring a one-to-one association with the foreign key in the child - Map hasOneMap = getAssociationMap(cpf, HAS_ONE); - - for (PropertyDescriptor descriptor : cpf.getPropertyDescriptors()) { - if (descriptor.getPropertyType() == null || descriptor.getPropertyType() == Object.class) { - // indexed property - continue; - } - if (descriptor.getReadMethod() == null || descriptor.getWriteMethod() == null) { - // non-persistent getter or setter - continue; - } - if (descriptor.getName().equals(VERSION) && !entity.isVersioned()) { - continue; - } - - Field field = cpf.getDeclaredField(descriptor.getName()); - if (field != null && java.lang.reflect.Modifier.isTransient(field.getModifiers())) { - continue; - } - final String propertyName = descriptor.getName(); - if (isExcludedProperty(propertyName, classMapping, transients)) continue; - Class propertyType = descriptor.getPropertyType(); - Class currentPropType = propertyType; - // establish if the property is a one-to-many - // if it is a Set and there are relationships defined - // and it is defined as persistent - if (embedded.contains(propertyName)) { - if (isCollectionType(currentPropType)) { - final Association association = establishRelationshipForCollection(descriptor, entity, context, hasManyMap, mappedByMap, true); - if (association != null) { - persistentProperties.add(association); - } - } - else { - final ToOne association = establishDomainClassRelationship(entity, descriptor, context, hasOneMap, true); - if (association != null) { - persistentProperties.add(association); - } - } - } - else if (isCollectionType(currentPropType)) { - final Association association = establishRelationshipForCollection(descriptor, entity, context, hasManyMap, mappedByMap, false); - if (association != null) { - configureOwningSide(association); - persistentProperties.add(association); - } - } - // otherwise if the type is a domain class establish relationship - else if (isPersistentEntity(currentPropType)) { - final ToOne association = establishDomainClassRelationship(entity, descriptor, context, hasOneMap, false); - if (association != null) { - configureOwningSide(association); - persistentProperties.add(association); - } - } - else if (Enum.class.isAssignableFrom(currentPropType) || - propertyFactory.isSimpleType(propertyType)) { - persistentProperties.add(propertyFactory.createSimple(entity, context, descriptor)); - } - else if (MappingFactory.isCustomType(propertyType)) { - persistentProperties.add(propertyFactory.createCustom(entity, context, descriptor)); - } - } - return persistentProperties; - } - - private List getCollectionStaticProperty(ClassPropertyFetcher cpf, String property) { - List colls = cpf.getStaticPropertyValuesFromInheritanceHierarchy(property, Collection.class); - if (colls == null) { - return Collections.emptyList(); - } - List values = new ArrayList(); - for (Collection coll : colls) { - values.addAll(coll); - } - return values; - } - - private Map getMapStaticProperty(ClassPropertyFetcher cpf, String property) { - List maps = cpf.getStaticPropertyValuesFromInheritanceHierarchy(property, Map.class); - if (maps == null) { - return Collections.emptyMap(); - } - Map values = new HashMap(); - for (int i = maps.size(); i > 0; i--) { - Map map = maps.get(i - 1); - values.putAll(map); - } - return values; - } - - private void configureOwningSide(Association association) { - PersistentEntity associatedEntity = association.getAssociatedEntity(); - if(associatedEntity == null) { - association.setOwningSide(true); - } - else { - if (association.isBidirectional()) { - if (associatedEntity.isOwningEntity(association.getOwner())) { - association.setOwningSide(true); - } - } - else { - if (association instanceof OneToOne) { - if (associatedEntity.isOwningEntity(association.getOwner())) - association.setOwningSide(true); - } else if (!(association instanceof Basic)) { - if (associatedEntity.isOwningEntity(association.getOwner())) { - association.setOwningSide(true); - } - else { - association.setOwningSide(false); - } - } - } - } - } - - /** - * Evaluates the belongsTo property to find out who owns who - */ - private Set establishRelationshipOwners(ClassPropertyFetcher cpf) { - Set owners = new HashSet(); - owners.addAll(cpf.getStaticPropertyValuesFromInheritanceHierarchy(BELONGS_TO, Class.class)); - owners.addAll(getCollectionStaticProperty(cpf, BELONGS_TO)); - owners.addAll(getMapStaticProperty(cpf, BELONGS_TO).values()); - return owners; - } - - private Association establishRelationshipForCollection(PropertyDescriptor property, PersistentEntity entity, MappingContext context, Map hasManyMap, Map mappedByMap, boolean embedded) { - // is it a relationship - Class relatedClassType = hasManyMap.get(property.getName()); - // try a bit harder for embedded collections (could make this the default, rendering 'hasMany' optional - // if generics are used) - if (relatedClassType == null && embedded) { - Class javaClass = entity.getJavaClass(); - - Class genericClass = MappingUtils.getGenericTypeForProperty(javaClass, property.getName()); - - if (genericClass != null) { - relatedClassType = genericClass; - } - } - - if (relatedClassType == null) { - return propertyFactory.createBasicCollection(entity, context, property); - } - - if (embedded) { - if (propertyFactory.isSimpleType(relatedClassType)) { - return propertyFactory.createBasicCollection(entity, context, property); - } - else if (!isPersistentEntity(relatedClassType)) { - // no point in setting up bidirectional link here, since target isn't an entity. - EmbeddedCollection association = propertyFactory.createEmbeddedCollection(entity, context, property); - PersistentEntity associatedEntity = getOrCreateEmbeddedEntity(entity, context, relatedClassType); - association.setAssociatedEntity(associatedEntity); - return association; - } - } - else if (!isPersistentEntity(relatedClassType)) { - // otherwise set it to not persistent as you can't persist - // relationships to non-domain classes - return propertyFactory.createBasicCollection(entity, context, property); - } - - // set the referenced type in the property - ClassPropertyFetcher referencedCpf = ClassPropertyFetcher.forClass(relatedClassType); - String referencedPropertyName = null; - - // if the related type is a domain class - // then figure out what kind of relationship it is - - // check the relationship defined in the referenced type - // if it is also a Set/domain class etc. - Map relatedClassRelationships = getAssociationMap(referencedCpf, HAS_MANY); - Class relatedClassPropertyType = null; - - String relatedClassPropertyName = null; - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass()); - // First check whether there is an explicit relationship - // mapping for this property (as provided by "mappedBy"). - String mappingProperty = (String)mappedByMap.get(property.getName()); - if (StringUtils.hasText(mappingProperty)) { - // First find the specified property on the related class, if it exists. - PropertyDescriptor pd = findProperty(getPropertiesAssignableFromType(entity.getJavaClass(), referencedCpf), - mappingProperty); - - // If a property of the required type does not exist, search - // for any collection properties on the related class. - if (pd == null) { - pd = findProperty(referencedCpf.getPropertiesAssignableToType(Collection.class), mappingProperty); - } - - // We've run out of options. The given "mappedBy" setting is invalid. - if (pd == null) { - if (entity.isExternal()) { - return null; - } - throw new IllegalMappingException("Non-existent mapping property [" + mappingProperty + - "] specified for property [" + property.getName() + - "] in class [" + entity.getJavaClass().getName() + "]"); - } - - // Tie the properties together. - relatedClassPropertyType = pd.getPropertyType(); - referencedPropertyName = pd.getName(); - } - else { - - if (!forceUnidirectional(property, mappedByMap)) { - // if the related type has a relationships map it may be a many-to-many - // figure out if there is a many-to-many relationship defined - if (isRelationshipToMany(entity, relatedClassType, relatedClassRelationships)) { - Map relatedClassMappedBy = getMapStaticProperty(cpf, MAPPED_BY); - // retrieve the relationship property - for (Object o : relatedClassRelationships.keySet()) { - String currentKey = (String) o; - String mappedByProperty = (String) relatedClassMappedBy.get(currentKey); - if (mappedByProperty != null && !mappedByProperty.equals(property.getName())) continue; - Class currentClass = (Class)relatedClassRelationships.get(currentKey); - if (currentClass.isAssignableFrom(entity.getJavaClass())) { - relatedClassPropertyName = currentKey; - break; - } - } - // Map classRelationships = cpf.getPropertyValue(HAS_MANY, Map.class); - // - // if (isRelationshipToMany(entity, relatedClassType, classRelationships)) { - // String relatedClassPropertyName = findManyRelatedClassPropertyName( - // property.getName(), referencedCpf, classRelationships, relatedClassType); - - // if there is one defined get the type - if (relatedClassPropertyName != null) { - relatedClassPropertyType = referencedCpf.getPropertyType(relatedClassPropertyName); - } - } - - // otherwise figure out if there is a one-to-many relationship by retrieving any properties that are of the related type - // if there is more than one property then (for the moment) ignore the relationship - if (relatedClassPropertyType == null || Collection.class.isAssignableFrom(relatedClassPropertyType)) { - List descriptors = getPropertiesAssignableFromType(entity.getJavaClass(), referencedCpf); - - if (descriptors.size() == 1) { - final PropertyDescriptor pd = descriptors.get(0); - relatedClassPropertyType = pd.getPropertyType(); - referencedPropertyName = pd.getName(); - } - else if (descriptors.size() > 1) { - // try now to use the class name by convention - String classPropertyName = entity.getDecapitalizedName(); - PropertyDescriptor pd = findProperty(descriptors, classPropertyName); - if (pd == null) { - if (entity.isExternal()) { - return null; - } - pd = descriptors.get(0); - } - - if (pd != null) { - relatedClassPropertyType = pd.getPropertyType(); - referencedPropertyName = pd.getName(); - } - } - } - } - } - - // if its a many-to-many figure out the owning side of the relationship - final boolean isInverseSideEntity = isPersistentEntity(relatedClassPropertyType); - Association association = null; - boolean many = false; - if (embedded) { - association = propertyFactory.createEmbeddedCollection(entity, context, property); - } - else if (relatedClassPropertyType == null || isInverseSideEntity) { - // uni or bi-directional one-to-many - association = propertyFactory.createOneToMany(entity, context, property); - } - else if (Collection.class.isAssignableFrom(relatedClassPropertyType) || - Map.class.isAssignableFrom(relatedClassPropertyType)) { - // many-to-many - association = propertyFactory.createManyToMany(entity, context, property); - ((ManyToMany)association).setInversePropertyName(relatedClassPropertyName); - many = true; - } - else { - // uni-directional one-to-many - association = propertyFactory.createOneToMany(entity, context, property); - - } - - PersistentEntity associatedEntity = getOrCreateAssociatedEntity(entity, context, relatedClassType); - if (many) { - Map classRelationships = referencedCpf.getPropertyValue(HAS_MANY, Map.class); - referencedPropertyName = findManyRelatedClassPropertyName(null, - referencedCpf, classRelationships, entity.getJavaClass()); - } - - if (association != null) { - association.setAssociatedEntity(associatedEntity); - if (referencedPropertyName != null) { - // bidirectional - association.setReferencedPropertyName(referencedPropertyName); - } - } - return association; - } - - private List getPropertiesAssignableFromType(Class type, ClassPropertyFetcher propertyFetcher) { - List props = propertyFetcher.getPropertiesAssignableFromType(type); - // exclude properties of type object! - List valid = new ArrayList(props.size()); - for (PropertyDescriptor prop : props) { - if (prop.getPropertyType() != null && !prop.getPropertyType().equals(Object.class)) { - valid.add(prop); - } - } - return valid; - } - - private String findManyRelatedClassPropertyName(String propertyName, - ClassPropertyFetcher cpf, Map classRelationships, Class classType) { - Map mappedBy = getMapStaticProperty(cpf, MAPPED_BY); - // retrieve the relationship property - for (Object o : classRelationships.keySet()) { - String currentKey = (String) o; - String mappedByProperty = (String)mappedBy.get(currentKey); - if (mappedByProperty != null && !mappedByProperty.equals(propertyName)) continue; - Class currentClass = (Class)classRelationships.get(currentKey); - if (currentClass.isAssignableFrom(classType)) { - return currentKey; - } - } - return null; - } - - /** - * Find out if the relationship is a 1-to-many or many-to-many. - * - * @param relatedClassType The related type - * @param relatedClassRelationships The related types relationships - * @return true if the relationship is a many-to-many - */ - private boolean isRelationshipToMany(PersistentEntity entity, - Class relatedClassType, Map relatedClassRelationships) { - return relatedClassRelationships != null && - !relatedClassRelationships.isEmpty() && - !relatedClassType.equals(entity.getJavaClass()); - } - - /** - * Finds a property type is an array of descriptors for the given property name - * - * @param descriptors The descriptors - * @param propertyName The property name - * @return The Class or null - */ - private PropertyDescriptor findProperty(List descriptors, String propertyName) { - for (PropertyDescriptor descriptor : descriptors) { - if (descriptor.getName().equals(propertyName)) { - return descriptor; - } - } - return null; - } - - /** - * Establish relationship with related domain class - * - * @param entity - * @param property Establishes a relationship between this class and the domain class property - * @param context - * @param hasOneMap - * @param embedded - */ - private ToOne establishDomainClassRelationship(PersistentEntity entity, PropertyDescriptor property, MappingContext context, Map hasOneMap, boolean embedded) { - ToOne association = null; - Class propType = property.getPropertyType(); - - if (embedded && !isPersistentEntity(propType)) { - // uni-directional to embedded non-entity - PersistentEntity associatedEntity = getOrCreateEmbeddedEntity(entity, context, propType); - association = propertyFactory.createEmbedded(entity, context, property); - association.setAssociatedEntity(associatedEntity); - return association; - } - - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(propType); - - // establish relationship to type - Map relatedClassRelationships = getAllAssociationMap(cpf); - Map mappedBy = getMapStaticProperty(cpf, MAPPED_BY); - - Class relatedClassPropertyType = null; - - // if there is a relationships map use that to find out - // whether it is mapped to a Set - String relatedClassPropertyName = null; - - if (!forceUnidirectional(property, mappedBy)) { - if (relatedClassRelationships != null && !relatedClassRelationships.isEmpty()) { - - PropertyDescriptor[] descriptors = ReflectionUtils.getPropertiesOfType(entity.getJavaClass(), propType); - relatedClassPropertyName = findOneToManyThatMatchesType(entity, relatedClassRelationships); - // if there is only one property on many-to-one side of the relationship then - // try to establish if it is bidirectional - if (descriptors.length == 1 && isNotMappedToDifferentProperty(property,relatedClassPropertyName, mappedBy)) { - if (StringUtils.hasText(relatedClassPropertyName)) { - // get the type of the property - relatedClassPropertyType = cpf.getPropertyType(relatedClassPropertyName); - } - } - // if there is more than one property on the many-to-one side then we need to either - // find out if there is a mappedBy property or whether a convention is used to decide - // on the mapping property - else if (descriptors.length > 1) { - if (mappedBy.containsValue(property.getName())) { - for (Object o : mappedBy.keySet()) { - String mappedByPropertyName = (String) o; - if (property.getName().equals(mappedBy.get(mappedByPropertyName))) { - Class mappedByRelatedType = (Class) relatedClassRelationships.get(mappedByPropertyName); - if (mappedByRelatedType != null && propType.isAssignableFrom(mappedByRelatedType)) - relatedClassPropertyType = cpf.getPropertyType(mappedByPropertyName); - } - } - } - else { - String classNameAsProperty = Introspector.decapitalize(propType.getName()); - if (property.getName().equals(classNameAsProperty) && !mappedBy.containsKey(relatedClassPropertyName)) { - relatedClassPropertyType = cpf.getPropertyType(relatedClassPropertyName); - } - } - } - } - - // otherwise retrieve all the properties of the type from the associated class - if (relatedClassPropertyType == null) { - List descriptors = getPropertiesAssignableFromType(entity.getJavaClass(), cpf); - - // if there is only one then the association is established - if (descriptors.size() == 1) { - relatedClassPropertyType = descriptors.get(0).getPropertyType(); - relatedClassPropertyName = descriptors.get(0).getName(); - } - } - } - - // establish relationship based on this type - - final boolean isAssociationEntity = isPersistentEntity(relatedClassPropertyType); - // one-to-one - if (relatedClassPropertyType == null || isAssociationEntity) { - association = embedded ? propertyFactory.createEmbedded(entity, context, property) : - propertyFactory.createOneToOne(entity, context, property); - - if (hasOneMap.containsKey(property.getName()) && !embedded) { - association.setForeignKeyInChild(true); - } - } - // bi-directional many-to-one - else if (!embedded && Collection.class.isAssignableFrom(relatedClassPropertyType)||Map.class.isAssignableFrom(relatedClassPropertyType)) { - association = propertyFactory.createManyToOne(entity, context, property); - } - - // bi-directional - if (association != null) { - PersistentEntity associatedEntity = getOrCreateAssociatedEntity(entity, context, propType); - association.setAssociatedEntity(associatedEntity); - boolean isNotCircular = entity != associatedEntity; - if (relatedClassPropertyName != null && isNotCircular) { - association.setReferencedPropertyName(relatedClassPropertyName); - } - } - - return association; - } - - /** - * check if mappedBy is set explicitly to null for the given property. - * @param property - * @param mappedBy - * @return true if mappedBy is set explicitly to null - */ - private boolean forceUnidirectional(PropertyDescriptor property, Map mappedBy) { - return mappedBy.containsKey(property.getName()) && (mappedBy.get(property.getName())==null); - } - - /** - * Tries to obtain or create an associated entity. Note that if #canExpandMappingContext is set to false then this method may return null - * - * @param entity The main entity - * @param context The context - * @param propType The associated property type - * @return The associated entity or null - */ - protected PersistentEntity getOrCreateAssociatedEntity(PersistentEntity entity, MappingContext context, Class propType) { - PersistentEntity associatedEntity = context.getPersistentEntity(propType.getName()); - if (associatedEntity == null) { - if(canExpandMappingContext) { - if (entity.isExternal()) { - associatedEntity = context.addExternalPersistentEntity(propType); - } - else { - associatedEntity = context.addPersistentEntity(propType); - } - } - } - else { - if(!associatedEntity.isInitialized()) { - associatedEntity.initialize(); - } - } - return associatedEntity; - } - - /** - * Tries to obtain or create an embedded entity. Note that if #canExpandMappingContext is set to false then this method may return null - * - * @param entity The main entity - * @param context The context - * @param type The associated property type - * @return The associated entity or null - */ - protected PersistentEntity getOrCreateEmbeddedEntity(PersistentEntity entity, MappingContext context, Class type) { - PersistentEntity associatedEntity = context.getPersistentEntity(type.getName()); - if (associatedEntity == null) { - // If this is a persistent entity, add and initialize, otherwise - // assume it's embedded - if( isPersistentEntity(type) ) { - if (entity.isExternal()) { - associatedEntity = context.addExternalPersistentEntity(type); - associatedEntity.initialize(); - } - else { - associatedEntity = context.addPersistentEntity(type); - associatedEntity.initialize(); - } - } - else { - PersistentEntity embeddedEntity = context.createEmbeddedEntity(type); - embeddedEntity.initialize(); - return embeddedEntity; - } - } - else { - if(!associatedEntity.isInitialized()) { - associatedEntity.initialize(); - } - } - return associatedEntity; - } - - private boolean isNotMappedToDifferentProperty(PropertyDescriptor property, - String relatedClassPropertyName, Map mappedBy) { - - String mappedByForRelation = (String)mappedBy.get(relatedClassPropertyName); - if (mappedByForRelation == null) return true; - if (!property.getName().equals(mappedByForRelation)) return false; - return true; - } - - private String findOneToManyThatMatchesType(PersistentEntity entity, Map relatedClassRelationships) { - for (Object o : relatedClassRelationships.keySet()) { - String currentKey = (String) o; - Class currentClass = (Class)relatedClassRelationships.get(currentKey); - - if (currentClass.isAssignableFrom(entity.getJavaClass())) { - return currentKey; - } - } - - return null; - } - - private boolean isCollectionType(Class type) { - return Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type); - } - - private boolean isExcludedProperty(String propertyName, ClassMapping classMapping, Collection transients) { - IdentityMapping id = classMapping != null ? classMapping.getIdentifier() : null; - String[] identifierName = id != null ? id.getIdentifierName() : null; - return identifierName != null && propertyName.equals(identifierName[0]) || - id == null && propertyName.equals(IDENTITY_PROPERTY) || - EXCLUDED_PROPERTIES.contains(propertyName) || - transients.contains(propertyName); - } - - /** - * Retrieves the association map - * @param cpf The ClassPropertyFetcher instance - * @return The association map - */ - protected Map getAssociationMap(ClassPropertyFetcher cpf) { - return getAssociationMap(cpf, HAS_MANY); - } - - /** - * Retrieves the association map - * @param cpf The ClassPropertyFetcher instance - * @return The association map - */ - protected Map getAllAssociationMap(ClassPropertyFetcher cpf) { - - Map associationMap = getAssociationMap(cpf, HAS_MANY); - associationMap.putAll(getAssociationMap(cpf, HAS_ONE)); - associationMap.putAll(getAssociationMap(cpf, BELONGS_TO)); - return associationMap; - } - - private Map getAssociationMap(ClassPropertyFetcher cpf, String relationshipType) { - return getMapStaticProperty(cpf, relationshipType); - } - - private PersistentEntity getPersistentEntity(Class javaClass, MappingContext context, ClassMapping classMapping) { - if (classMapping != null) { - return classMapping.getEntity(); - } - - return context.getPersistentEntity(javaClass.getName()); - } - - public Set getOwningEntities(Class javaClass, MappingContext context) { - return establishRelationshipOwners(ClassPropertyFetcher.forClass(javaClass)); - } - - /** - * @see org.grails.datastore.mapping.model.MappingConfigurationStrategy#getIdentity(Class, org.grails.datastore.mapping.model.MappingContext) - */ - public PersistentProperty getIdentity(Class javaClass, MappingContext context) { - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(javaClass); - PersistentEntity entity = context.getPersistentEntity(javaClass.getName()); - ClassMapping mapping = entity.getMapping(); - - IdentityMapping id = mapping.getIdentifier(); - final String[] names = id.getIdentifierName(); - if (names.length == 1) { - final PropertyDescriptor pd = cpf.getPropertyDescriptor(names[0]); - - if (pd != null) { - return propertyFactory.createIdentity(entity, context, pd); - } - if (!entity.isExternal()) { - throw new IllegalMappingException("Mapped identifier [" + names[0] + "] for class [" + - javaClass.getName() + "] is not a valid property"); - } - return null; - } - return null; - } - - /** - * Obtains the identity mapping for the specified class mapping - * - * @param classMapping The class mapping - * @return The identity mapping - */ - public IdentityMapping getIdentityMapping(ClassMapping classMapping) { - return propertyFactory.createIdentityMapping(classMapping); - } - - public IdentityMapping getDefaultIdentityMapping(final ClassMapping classMapping) { - return propertyFactory.createDefaultIdentityMapping(classMapping); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormProperties.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormProperties.java deleted file mode 100644 index 510dbc801..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormProperties.java +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.config; - -/** - * Reserved static property names used by GORM to evaluate GORM-style syntax. - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface GormProperties { - String IDENTITY = "id"; - String VERSION = "version"; - String TRANSIENT = "transients"; - String MAPPING_STRATEGY = "mapWith"; - String MAPPED_BY = "mappedBy"; - String BELONGS_TO = "belongsTo"; - String HAS_MANY = "hasMany"; - String HAS_ONE = "hasOne"; - String DATE_CREATED = "dateCreated"; - String MAPPING = "mapping"; - String NAMED_QUERIES = "namedQueries"; - String LAST_UPDATED = "lastUpdated"; - String EMBEDDED = "embedded"; - String CONSTRAINTS = "constraints"; -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/lifecycle/Initializable.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/lifecycle/Initializable.java deleted file mode 100644 index f745714b1..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/lifecycle/Initializable.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.grails.datastore.mapping.model.lifecycle; - -/** - * Interface for object that requires explicit initialization - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface Initializable { - - /** - * Call to initialize the object - */ - void initialize(); - - boolean isInitialized(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Association.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Association.java deleted file mode 100644 index 4755212d6..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Association.java +++ /dev/null @@ -1,154 +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.grails.datastore.mapping.model.types; - -import java.beans.PropertyDescriptor; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.persistence.CascadeType; -import javax.persistence.FetchType; - -import org.grails.datastore.mapping.model.AbstractPersistentProperty; -import org.grails.datastore.mapping.model.IllegalMappingException; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; - -/** - * Models an association between one class and another - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public abstract class Association extends AbstractPersistentProperty { - - public static final List DEFAULT_OWNER_CASCADE = Arrays.asList(CascadeType.ALL); - - public static final List DEFAULT_CHILD_CASCADE = Arrays.asList(CascadeType.PERSIST); - - private PersistentEntity associatedEntity; - private String referencedPropertyName; - private boolean owningSide; - private List cascadeOperations = new ArrayList(); - private FetchType fetchStrategy = FetchType.EAGER; - - public Association(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { - super(owner, context, descriptor); - } - - public Association(PersistentEntity owner, MappingContext context, String name, Class type) { - super(owner, context, name, type); - } - - public FetchType getFetchStrategy() { - return fetchStrategy; - } - - public void setFetchStrategy(FetchType fetchStrategy) { - this.fetchStrategy = fetchStrategy; - } - - public boolean isBidirectional() { - return associatedEntity != null && referencedPropertyName != null; - } - - public Association getInverseSide() { - final PersistentProperty associatedProperty = associatedEntity.getPropertyByName(referencedPropertyName); - if (associatedProperty == null) return null; - if (associatedProperty instanceof Association) { - return (Association) associatedProperty; - } - throw new IllegalMappingException("The inverse side [" + associatedEntity.getName() + "." + - associatedProperty.getName() + "] of the association [" + getOwner().getName() + "." + - getName() + "] is not valid. Associations can only map to other entities and collection types."); - } - - /** - * Returns true if the this association cascade for the given cascade operation - * - * @param cascadeOperation The cascadeOperation - * @return True if it does - */ - public boolean doesCascade(CascadeType cascadeOperation) { - List cascades = getCascadeOperations(); - return cascadeOperation != null && (cascades.contains(CascadeType.ALL) || cascades.contains(cascadeOperation)); - } - - protected List getCascadeOperations() { - List cascades; - if (cascadeOperations.isEmpty()) { - if (isOwningSide()) cascades = DEFAULT_OWNER_CASCADE; - else { - cascades = DEFAULT_CHILD_CASCADE; - } - } - else { - cascades = this.cascadeOperations; - } - return cascades; - } - - /** - * Returns whether this side owns the relationship. This controls - * the default cascading behavior if none is specified - * - * @return True if this property is the owning side - */ - public boolean isOwningSide() { - return owningSide; - } - - public void setOwningSide(boolean owningSide) { - this.owningSide = owningSide; - } - - public void setAssociatedEntity(PersistentEntity associatedEntity) { - this.associatedEntity = associatedEntity; - } - - public PersistentEntity getAssociatedEntity() { - return associatedEntity; - } - - public void setReferencedPropertyName(String referencedPropertyName) { - this.referencedPropertyName = referencedPropertyName; - } - - public String getReferencedPropertyName() { - return referencedPropertyName; - } - - @Override - public String toString() { - return getOwner().getName() + "->" + getName(); - } - - public boolean isList() { - return List.class.isAssignableFrom(getType()); - } - - public boolean isCircular() { - PersistentEntity associatedEntity1 = getAssociatedEntity(); - if(associatedEntity1 == null) { - return false; - } - else { - return isBidirectional() && associatedEntity1.equals(getOwner()); - } - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Basic.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Basic.java deleted file mode 100644 index 109b282c2..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Basic.java +++ /dev/null @@ -1,59 +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.mapping.model.types; - -import java.beans.PropertyDescriptor; - -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Models a basic collection type such as a list of Strings - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public abstract class Basic extends Association { - - public Basic(PersistentEntity owner, MappingContext context, - PropertyDescriptor descriptor) { - super(owner, context, descriptor); - } - - public Basic(PersistentEntity owner, MappingContext context, String name, Class type) { - super(owner, context, name, type); - } - - @Override - public Association getInverseSide() { - return null; // basic collection types have no inverse side - } - - @Override - public boolean isOwningSide() { - return true; - } - - @Override - public void setOwningSide(boolean owningSide) { - // noop - } - - @Override - public PersistentEntity getAssociatedEntity() { - return null; // basic collection types have no associated entity - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/BasicTypeConverterRegistrar.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/BasicTypeConverterRegistrar.java deleted file mode 100644 index 46749ea94..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/BasicTypeConverterRegistrar.java +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types; - -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; - -import org.springframework.core.convert.converter.Converter; -import org.springframework.core.convert.converter.ConverterRegistry; - -/** - * A registrar that registers basic type converters - * - * @author Graeme Rocher - * @since 1.0 - */ -public class BasicTypeConverterRegistrar { - - public void register(ConverterRegistry registry) { - registry.addConverter(new Converter() { - public String convert(Date date) { - return String.valueOf(date.getTime()); - } - }); - - registry.addConverter(new Converter() { - public Calendar convert(Date date) { - final GregorianCalendar calendar = new GregorianCalendar(); - calendar.setTime(date); - return calendar; - } - }); - - registry.addConverter(new Converter() { - public Long convert(Integer integer) { - return integer.longValue(); - } - }); - - registry.addConverter(new Converter() { - public Integer convert(Long longValue) { - return longValue.intValue(); - } - }); - - registry.addConverter(new Converter() { - public Double convert(Integer integer) { - return integer.doubleValue(); - } - }); - - registry.addConverter(new Converter() { - public Date convert(CharSequence s) { - try { - final Long time = Long.valueOf(s.toString()); - return new Date(time); - } catch (NumberFormatException e) { - throw new IllegalArgumentException(e); - } - } - }); - - registry.addConverter(new Converter() { - public Double convert(CharSequence s) { - try { - return Double.valueOf(s.toString()); - } catch (NumberFormatException e) { - throw new IllegalArgumentException(e); - } - } - }); - - registry.addConverter(new Converter() { - public Integer convert(CharSequence s) { - try { - return Integer.valueOf(s.toString()); - } catch (NumberFormatException e) { - throw new IllegalArgumentException(e); - } - } - }); - - registry.addConverter(new Converter() { - public Long convert(CharSequence s) { - try { - return Long.valueOf(s.toString()); - } catch (NumberFormatException e) { - throw new IllegalArgumentException(e); - } - } - }); - - registry.addConverter(new Converter() { - public String convert(Object o) { - return o.toString(); - } - }); - - registry.addConverter(new Converter() { - public String convert(Calendar calendar) { - return String.valueOf(calendar.getTime().getTime()); - } - }); - - registry.addConverter(new Converter() { - public Calendar convert(CharSequence s) { - try { - Date date = new Date(Long.valueOf(s.toString())); - Calendar c = new GregorianCalendar(); - c.setTime(date); - return c; - } catch (NumberFormatException e) { - throw new IllegalArgumentException(e); - } - } - }); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Custom.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Custom.java deleted file mode 100644 index 7cefbe470..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Custom.java +++ /dev/null @@ -1,53 +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.mapping.model.types; - -import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller; -import org.grails.datastore.mapping.model.AbstractPersistentProperty; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -import java.beans.PropertyDescriptor; - -/** - * Represents a custom type ie. a type whose database read/write semantics are specified by the user. - * - * @author Graeme Rocher - * @since 1.0 - */ -public abstract class Custom extends AbstractPersistentProperty { - private CustomTypeMarshaller customTypeMarshaller; - - public Custom(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor, - CustomTypeMarshaller customTypeMarshaller) { - super(owner, context, descriptor); - this.customTypeMarshaller = customTypeMarshaller; - } - - protected Custom(PersistentEntity owner, MappingContext context, String name, Class type, - CustomTypeMarshaller customTypeMarshaller) { - super(owner, context, name, type); - this.customTypeMarshaller = customTypeMarshaller; - } - - /** - * @return The type converter for this custom type - */ - @SuppressWarnings("rawtypes") - public CustomTypeMarshaller getCustomTypeMarshaller() { - return customTypeMarshaller; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Embedded.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Embedded.java deleted file mode 100644 index 3dfa16ec9..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Embedded.java +++ /dev/null @@ -1,42 +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.grails.datastore.mapping.model.types; - -import java.beans.PropertyDescriptor; - -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Models an embedded component - * - * @author Graeme Rocher - * @since 1.0 - */ -public abstract class Embedded extends ToOne { - - public Embedded(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { - super(owner, context, descriptor); - } - - public Embedded(PersistentEntity owner, MappingContext context, String name, @SuppressWarnings("rawtypes") Class type) { - super(owner, context, name, type); - } - - @Override - public boolean isOwningSide() { - return true; // embedded instances are always owned - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/EmbeddedCollection.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/EmbeddedCollection.java deleted file mode 100644 index 906a942e7..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/EmbeddedCollection.java +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright 2011 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.mapping.model.types; - -import java.beans.PropertyDescriptor; - -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Models an embedded collection. - * - * @author Burt Beckwith - * @since 1.0 - */ -public abstract class EmbeddedCollection extends Association { - - public EmbeddedCollection(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { - super(owner, context, descriptor); - } - - @Override - public boolean isOwningSide() { - return true; // embedded instances are always owned - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Identity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Identity.java deleted file mode 100644 index a1e880e24..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Identity.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.grails.datastore.mapping.model.types; - -import java.beans.PropertyDescriptor; - -import org.grails.datastore.mapping.model.AbstractPersistentProperty; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Represents the identity of a persistent entity - * - * @author Graeme Rocher - * @since 1.0 - */ -public abstract class Identity extends AbstractPersistentProperty { - public Identity(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { - super(owner, context, descriptor); - } - public Identity(PersistentEntity owner, MappingContext context, String name, @SuppressWarnings("rawtypes") Class type) { - super(owner, context, name, type); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ManyToMany.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ManyToMany.java deleted file mode 100644 index 54c9ea371..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ManyToMany.java +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types; - -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -import java.beans.PropertyDescriptor; - -/** - * Models a many-to-many association between one class and another - * - * @author Graeme Rocher - * @since 1.0 - */ -public abstract class ManyToMany extends Association { - - String inversePropertyName; - - public ManyToMany(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { - super(owner, context, descriptor); - } - - public ManyToMany(PersistentEntity owner, MappingContext context, String name, @SuppressWarnings("rawtypes") Class type) { - super(owner, context, name, type); - } - - public String getInversePropertyName() { - return inversePropertyName; - } - - public void setInversePropertyName(String inversePropertyName) { - this.inversePropertyName = inversePropertyName; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ManyToOne.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ManyToOne.java deleted file mode 100644 index 6928d74dc..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ManyToOne.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.grails.datastore.mapping.model.types; - -import java.beans.PropertyDescriptor; - -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Models a many-to-one association - * - * @author Graeme Rocher - * @since 1.0 - */ -public abstract class ManyToOne extends ToOne { - public ManyToOne(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { - super(owner, context, descriptor); - } - - public ManyToOne(PersistentEntity owner, MappingContext context, String name, @SuppressWarnings("rawtypes") Class type) { - super(owner, context, name, type); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToMany.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToMany.java deleted file mode 100644 index 775cfece0..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToMany.java +++ /dev/null @@ -1,37 +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.grails.datastore.mapping.model.types; - -import java.beans.PropertyDescriptor; - -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Models a one-to-many association - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public abstract class OneToMany extends Association { - public OneToMany(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { - super(owner, context, descriptor); - } - - public OneToMany(PersistentEntity owner, MappingContext context, String name, Class type) { - super(owner, context, name, type); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToOne.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToOne.java deleted file mode 100644 index b1573b2ea..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToOne.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.grails.datastore.mapping.model.types; - -import java.beans.PropertyDescriptor; - -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Models a one-to-one association - * - * @author Graeme Rocher - * @since 1.0 - */ -public abstract class OneToOne extends ToOne { - public OneToOne(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { - super(owner, context, descriptor); - } - - public OneToOne(PersistentEntity owner, MappingContext context, String name, @SuppressWarnings("rawtypes") Class type) { - super(owner, context, name, type); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Simple.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Simple.java deleted file mode 100644 index 78f923fa5..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Simple.java +++ /dev/null @@ -1,37 +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.grails.datastore.mapping.model.types; - -import org.grails.datastore.mapping.model.AbstractPersistentProperty; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -import java.beans.PropertyDescriptor; - -/** - * Models a simple property type - * - * @author Graeme Rocher - * @since 1.0 - */ -public abstract class Simple extends AbstractPersistentProperty { - public Simple(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { - super(owner, context, descriptor); - } - - public Simple(PersistentEntity owner, MappingContext context, String name, @SuppressWarnings("rawtypes") Class type) { - super(owner, context, name, type); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ToOne.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ToOne.java deleted file mode 100644 index 12896d7d2..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ToOne.java +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types; - -import java.beans.PropertyDescriptor; - -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * @author Graeme Rocher - * @since 1.1 - */ -public abstract class ToOne extends Association { - - private boolean foreignKeyInChild; - - public ToOne(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { - super(owner, context, descriptor); - } - - public ToOne(PersistentEntity owner, MappingContext context, String name, @SuppressWarnings("rawtypes") Class type) { - super(owner, context, name, type); - } - - public void setForeignKeyInChild(boolean foreignKeyInChild) { - this.foreignKeyInChild = foreignKeyInChild; - } - - public boolean isForeignKeyInChild() { - return foreignKeyInChild; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DefaultConversionService.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DefaultConversionService.java deleted file mode 100644 index af606acc5..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DefaultConversionService.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.grails.datastore.mapping.model.types.conversion; - -import groovy.lang.GroovyObject; - -import java.io.Serializable; - -import org.springframework.core.convert.TypeDescriptor; -import org.springframework.format.datetime.DateFormatterRegistrar; - -/** - * Default conversion service th - * @author Graeme Rocher - */ -public class DefaultConversionService extends org.springframework.core.convert.support.DefaultConversionService { - - public DefaultConversionService() { - DateFormatterRegistrar.addDateConverters(this); - - addConverter(new StringToShortConverter()); - addConverter(new StringToBigIntegerConverter()); - addConverter(new StringToBigDecimalConverter()); - addConverter(new StringToCurrencyConverter()); - addConverter(new StringToLocaleConverter()); - addConverter(new StringToTimeZoneConverter()); - addConverter(new StringToURLConverter()); - addConverter(new IntArrayToIntegerArrayConverter()); - addConverter(new LongArrayToLongArrayConverter()); - addConverter(new IntegerToByteConverter()); - addConverter(new DoubleToFloatConverter()); - addConverter(new IntegerToShortConverter()); - } - - @Override - public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { - // force converting GStringImpl & StreamCharBuffer to String before conversion - if(source instanceof CharSequence && source.getClass() != String.class && - targetType != null && targetType.getType() != source.getClass()) { - source = source.toString(); - sourceType = TypeDescriptor.valueOf(String.class); - } - return super.convert(source, sourceType, targetType); - } - - @Override - public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) { - // fix EnumToString conversions for Enums implemented in Groovy - // see org.springframework.core.convert.support.EnumToStringConverter.match method - if (targetType != null - && targetType.getType() == String.class - && sourceType != null - && (sourceType.getType() == GroovyObject.class || - sourceType.getType() == Comparable.class || - sourceType.getType() == Serializable.class)) { - return false; - } - boolean reply = super.canConvert(sourceType, targetType); - if(!reply && sourceType != null && CharSequence.class.isAssignableFrom(sourceType.getType())) { - reply = super.canConvert(TypeDescriptor.valueOf(String.class), targetType); - } - return reply; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DoubleToFloatConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DoubleToFloatConverter.groovy deleted file mode 100644 index 1f8f555c1..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DoubleToFloatConverter.groovy +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types.conversion - -import groovy.transform.CompileStatic - -import org.springframework.core.convert.converter.Converter - -/** - * @author Stefan Armbruster - */ -@CompileStatic -class DoubleToFloatConverter implements Converter { - @Override - Float convert(Double source) { - source as Float - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntArrayToIntegerArrayConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntArrayToIntegerArrayConverter.groovy deleted file mode 100644 index a77ebd67d..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntArrayToIntegerArrayConverter.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types.conversion - -import groovy.transform.CompileStatic - -import org.springframework.core.convert.converter.Converter - -/** - * @author Stefan Armbruster - */ -@CompileStatic -class IntArrayToIntegerArrayConverter implements Converter { - Integer[] convert(int[] source) { - source as Integer[] - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToByteConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToByteConverter.groovy deleted file mode 100644 index f2e20b260..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToByteConverter.groovy +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types.conversion - -import groovy.transform.CompileStatic - -import org.springframework.core.convert.converter.Converter - -/** - * @author Stefan Armbruster - */ -@CompileStatic -class IntegerToByteConverter implements Converter { - @Override - Byte convert(Integer source) { - source as Byte - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToShortConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToShortConverter.groovy deleted file mode 100644 index 21bc6037d..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToShortConverter.groovy +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types.conversion - -import groovy.transform.CompileStatic - -import org.springframework.core.convert.converter.Converter - -/** - * @author Stefan Armbruster - */ -@CompileStatic -class IntegerToShortConverter implements Converter { - @Override - Short convert(Integer source) { - source as Short - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/LongArrayToLongArrayConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/LongArrayToLongArrayConverter.groovy deleted file mode 100644 index 49b33133e..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/LongArrayToLongArrayConverter.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types.conversion - -import groovy.transform.CompileStatic - -import org.springframework.core.convert.converter.Converter - -/** - * @author Stefan Armbruster - */ -@CompileStatic -class LongArrayToLongArrayConverter implements Converter { - Long[] convert(long[] source) { - source as Long[] - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigDecimalConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigDecimalConverter.groovy deleted file mode 100644 index 4107d26f4..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigDecimalConverter.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types.conversion - -import groovy.transform.CompileStatic - -import org.springframework.core.convert.converter.Converter - -/** - * @author Stefan Armbruster - */ -@CompileStatic -class StringToBigDecimalConverter implements Converter { - BigDecimal convert(String source) { - new BigDecimal(source) - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigIntegerConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigIntegerConverter.groovy deleted file mode 100644 index a2be7f594..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigIntegerConverter.groovy +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types.conversion - -import groovy.transform.CompileStatic - -import org.springframework.core.convert.converter.Converter - -/** - * @author Stefan Armbruster - */ -@CompileStatic -class StringToBigIntegerConverter implements Converter { - BigInteger convert(String source) { - new BigInteger(source) - } - -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToCurrencyConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToCurrencyConverter.groovy deleted file mode 100644 index 7185e815f..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToCurrencyConverter.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types.conversion - -import groovy.transform.CompileStatic - -import org.springframework.core.convert.converter.Converter - -/** - * @author Stefan Armbruster - */ -@CompileStatic -class StringToCurrencyConverter implements Converter { - Currency convert(String source) { - Currency.getInstance(source) - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToLocaleConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToLocaleConverter.groovy deleted file mode 100644 index 72c553f37..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToLocaleConverter.groovy +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types.conversion - -import groovy.transform.CompileStatic - -import org.springframework.core.convert.converter.Converter - -/** - * @author Stefan Armbruster - */ -@CompileStatic -class StringToLocaleConverter implements Converter { - Locale convert(String source) { - String[] parts = source.split("_") - switch (parts.length) { - case 1: return new Locale(parts[0]) - case 2: return new Locale(parts[0],parts[1]) - case 3: return new Locale(parts[0],parts[1],parts[2]) - default: return new Locale(source) - } - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToShortConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToShortConverter.groovy deleted file mode 100644 index e2ccd0f43..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToShortConverter.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types.conversion - -import groovy.transform.CompileStatic - -import org.springframework.core.convert.converter.Converter - -/** - * @author Stefan Armbruster - */ -@CompileStatic -class StringToShortConverter implements Converter { - Short convert(String source) { - new Short(source) - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToTimeZoneConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToTimeZoneConverter.groovy deleted file mode 100644 index b0c514aa5..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToTimeZoneConverter.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types.conversion - -import groovy.transform.CompileStatic - -import org.springframework.core.convert.converter.Converter - -/** - * @author Stefan Armbruster - */ -@CompileStatic -class StringToTimeZoneConverter implements Converter { - TimeZone convert(String source) { - TimeZone.getTimeZone(source) - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToURLConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToURLConverter.groovy deleted file mode 100644 index 5adfe2076..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToURLConverter.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2010 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.mapping.model.types.conversion - -import groovy.transform.CompileStatic - -import org.springframework.core.convert.converter.Converter - -/** - * @author Stefan Armbruster - */ -@CompileStatic -class StringToURLConverter implements Converter { - URL convert(String source) { - new URL(source) - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/EntityProxy.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/EntityProxy.java deleted file mode 100644 index 975bcf6b3..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/EntityProxy.java +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 2010 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.mapping.proxy; - -import java.io.Serializable; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public interface EntityProxy { - - /** - * Initializes the proxy if it hasn't been initialized already - */ - void initialize(); - - /** - * Obtains the target performing initialization if necessary - * @return The target - */ - Object getTarget(); - - /** - * Checks whether the proxy has been initialized - * @return True if it has - */ - boolean isInitialized(); - - /** - * @return The identifier - */ - Serializable getProxyKey(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/GroovyObjectMethodHandler.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/GroovyObjectMethodHandler.java deleted file mode 100644 index 16909fd81..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/GroovyObjectMethodHandler.java +++ /dev/null @@ -1,130 +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.grails.datastore.mapping.proxy; - -import groovy.lang.MetaClass; - -import java.lang.reflect.Method; - -import javassist.util.proxy.MethodHandler; - -import org.codehaus.groovy.runtime.InvokerHelper; - -/** - * Javassist MethodHandler for handling GroovyObject methods - * - * delegates getProperty, setProperty & invokeMethod to super class's MetaClass - * - * @author Lari Hotari - */ -public class GroovyObjectMethodHandler implements MethodHandler { - public static final Object INVOKE_IMPLEMENTATION = new Object(); - protected final Class proxyClass; - protected transient MetaClass metaClass; - - public GroovyObjectMethodHandler(Class proxyClass) { - this.proxyClass = proxyClass; - } - - public Object getProperty(Object self, String property) { - if("metaClass".equals(property)) { - return getThisMetaClass(); - } - Object delegate = resolveDelegate(self); - return InvokerHelper.getMetaClass(delegate).getProperty(delegate, property); - } - - protected Object resolveDelegate(Object self) { - return self; - } - - public void setProperty(Object self, String property, Object newValue) { - if("metaClass".equals(property)) { - setThisMetaClass((MetaClass)newValue); - return; - } - Object delegate = resolveDelegate(self); - InvokerHelper.getMetaClass(delegate).setProperty(delegate, property, newValue); - } - - public Object invokeThisMethod(Object self, String name, Object args) { - Object delegate = resolveDelegate(self); - return InvokerHelper.getMetaClass(delegate).invokeMethod(delegate, name, args); - } - - public MetaClass getThisMetaClass() { - if (metaClass == null) { - metaClass = InvokerHelper.getMetaClass(proxyClass); - } - return metaClass; - } - - public void setThisMetaClass(MetaClass metaClass) { - this.metaClass = metaClass; - } - - @Override - public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable { - Object result = handleInvocation(self, thisMethod, args); - if(!wasHandled(result)) { - return proceed.invoke(self, args); - } else { - return result; - } - } - - public boolean wasHandled(Object result) { - return result != INVOKE_IMPLEMENTATION; - } - - public Object handleInvocation(Object self, Method thisMethod, Object[] args) { - String methodName = thisMethod.getName(); - if (args.length == 0) { - if ("getMetaClass".equals(methodName)) { - return getThisMetaClass(); - } - } - else if (args.length == 1) { - if ("getProperty".equals(methodName)) { - String name = args[0].toString(); - if("metaClass".equals(name)) { - return getThisMetaClass(); - } else { - return getProperty(self, name); - } - } else if ("setMetaClass".equals(methodName)) { - setThisMetaClass((MetaClass)args[0]); - return Void.class; - } - } - else if (args.length == 2) { - if ("setProperty".equals(methodName)) { - String name = args[0].toString(); - Object value = args[1]; - if("metaClass".equals(name)) { - setThisMetaClass((MetaClass)value); - } else { - setProperty(self, name, value); - } - return Void.class; - } else if ("invokeMethod".equals(methodName)) { - invokeThisMethod(self, args[0].toString(), args[1]); - return Void.class; - } - } - return INVOKE_IMPLEMENTATION; - } -} 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 deleted file mode 100644 index 257b8cdcb..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/JavassistProxyFactory.java +++ /dev/null @@ -1,170 +0,0 @@ -/* Copyright (C) 2010 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.mapping.proxy; - -import groovy.lang.GroovyObject; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import javassist.util.proxy.MethodFilter; -import javassist.util.proxy.MethodHandler; -import javassist.util.proxy.ProxyFactory; -import javassist.util.proxy.ProxyObject; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.reflect.ReflectionUtils; - -/** - * A proxy factory that uses Javassist to create proxies - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class JavassistProxyFactory implements org.grails.datastore.mapping.proxy.ProxyFactory { - - private static final Map PROXY_FACTORIES = new ConcurrentHashMap(); - - private static final Set EXCLUDES = new HashSet(Arrays.asList("$getStaticMetaClass")); - - public boolean isProxy(Object object) { - return object instanceof EntityProxy; - } - - public Serializable getIdentifier(Object obj) { - return ((EntityProxy)obj).getProxyKey(); - - } - - /** - * Checks whether a given proxy is initialized - * - * @param object The object to check - * @return True if it is - */ - public boolean isInitialized(Object object) { - return !isProxy(object) || ((EntityProxy) object).isInitialized(); - } - - /** - * Unwraps the given proxy if it is one - * - * @param object The object - * @return The unwrapped proxy - */ - public Object unwrap(Object object) { - if (isProxy(object)) { - return ((EntityProxy)object).getTarget(); - } - return object; - } - - public T createProxy(Session session, Class type, Serializable key) { - return (T) getProxyInstance(session, type, key); - } - - protected Object createProxiedInstance(final Session session, final Class cls, Class proxyClass, final Serializable id) { - MethodHandler mi = new GroovyObjectMethodHandler(proxyClass) { - private Object target; - - @Override - protected Object resolveDelegate(Object self) { - return target; - } - - public Object invoke(Object proxy, Method method, Method proceed, Object[] args) throws Throwable { - if (args.length == 0) { - final String methodName = method.getName(); - if (methodName.equals("getId") || methodName.equals("getProxyKey")) { - return id; - } - if (methodName.equals("initialize")) { - initialize(); - return null; - } - if (methodName.equals("isInitialized")) { - return target != null; - } - if (methodName.equals("getTarget")) { - initialize(); - return target; - } - } - if (target == null) { - initialize(); - - // This tends to happen during unit testing if the proxy class is not properly mocked - // and therefore can't be found in the session. - if( target == null ) { - throw new IllegalStateException("Proxy for ["+cls.getName()+":"+id+"] could not be initialized"); - } - } - - Object result = handleInvocation(target, method, args); - if(!wasHandled(result)) { - return org.springframework.util.ReflectionUtils.invokeMethod(method, target, args); - } else { - return result; - } - } - - public void initialize() { - target = session.retrieve(cls, id); - } - }; - Object proxy = ReflectionUtils.instantiate(proxyClass); - ((ProxyObject)proxy).setHandler(mi); - return proxy; - } - - protected Object getProxyInstance(Session session, Class type, Serializable id) { - Class proxyClass = getProxyClass(type); - return createProxiedInstance(session, type, proxyClass, id); - } - - protected Class getProxyClass(Class type) { - - Class proxyClass = PROXY_FACTORIES.get(type); - if (proxyClass == null) { - javassist.util.proxy.ProxyFactory pf = new ProxyFactory(); - pf.setSuperclass(type); - pf.setInterfaces(new Class[]{ EntityProxy.class, GroovyObject.class }); - pf.setFilter(new MethodFilter() { - public boolean isHandled(Method method) { - final String methodName = method.getName(); - if (methodName.indexOf("super$") > -1) { - return false; - } - if (method.getParameterTypes().length == 0 && (methodName.equals("finalize"))) { - return false; - } - if (EXCLUDES.contains(methodName) || method.isSynthetic() || method.isBridge()) { - return false; - } - return true; - } - }); - proxyClass = pf.createClass(); - PROXY_FACTORIES.put(type, proxyClass); - } - return proxyClass; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/ProxyFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/ProxyFactory.java deleted file mode 100644 index 340a29bfc..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/ProxyFactory.java +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (C) 2010 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.mapping.proxy; - -import java.io.Serializable; - -import org.grails.datastore.mapping.core.Session; - -/** - * The factory used to create proxies - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface ProxyFactory { - - /** - * Creates a proxy - * - * @param The type of the proxy to create - * @param session The session instance - * @param type The type of the proxy to create - * @param key The key to proxy - * @return A proxy instance - */ - T createProxy(Session session, Class type, Serializable key); - - /** - * Checks whether the specified instance is a proxy - * - * @param object The object to check - * @return True if it is a proxy - */ - boolean isProxy(Object object); - - /** - * Checks whether a given proxy is initialized - * @param object The object to check - * @return True if it is - */ - boolean isInitialized(Object object); - - /** - * Unwraps the given proxy if it is one - * @param object The object - * @return The unwrapped proxy - */ - Object unwrap(Object object); - /** - * Obtains the identifier of an object without initializing the proxy if it is one - * @param obj The object - * @return The identifier - */ - Serializable getIdentifier(Object obj); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/AssociationQuery.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/AssociationQuery.java deleted file mode 100644 index 436b227ee..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/AssociationQuery.java +++ /dev/null @@ -1,53 +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.mapping.query; - -import java.util.List; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.query.Query.Criterion; - -/** - * Used to capture the metadata for a query on an associated object. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class AssociationQuery extends Query implements Criterion { - - private Association association; - - protected AssociationQuery(Session session, PersistentEntity entity, Association association) { - super(session, entity); - this.association = association; - } - - /** - * The association being queried - * - * @return The association - */ - public Association getAssociation() { - return association; - } - - @Override - protected List executeQuery(PersistentEntity e, Junction j) { - throw new UnsupportedOperationException("AssociationQuery instances are not executable and are merely metadata defined to query associations in a primary query"); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Projections.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Projections.java deleted file mode 100644 index f9cf376f6..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Projections.java +++ /dev/null @@ -1,122 +0,0 @@ -/* Copyright (C) 2010 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.mapping.query; - -/** - * Projections used to customize the results of a query - * - * @author Graeme Rocher - * @since 1.0 - */ -public class Projections { - public static final Query.IdProjection ID_PROJECTION = new Query.IdProjection(); - public static final Query.CountProjection COUNT_PROJECTION = new Query.CountProjection(); - - /** - * Projection used to obtain the id of an object - * @return The IdProjection instance - */ - public static Query.IdProjection id() { - return ID_PROJECTION; - } - - /** - * Projection that returns the number of records from the query - * instead of the results themselves - * - * @return The CountProjection instance - */ - public static Query.CountProjection count() { - return COUNT_PROJECTION; - } - - /** - * A projection that obtains the value of a property of an entity - * @param name The name of the property - * @return The PropertyProjection instance - */ - public static Query.PropertyProjection property(String name) { - return new Query.PropertyProjection(name); - } - - /** - * Computes the sum of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - public static Query.SumProjection sum(String name) { - return new Query.SumProjection(name); - } - - /** - * Computes the min value of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - public static Query.MinProjection min(String name) { - return new Query.MinProjection(name); - } - - /** - * Computes the max value of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - public static Query.MaxProjection max(String name) { - return new Query.MaxProjection(name); - } - - /** - * Computes the average value of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - public static Query.AvgProjection avg(String name) { - return new Query.AvgProjection(name); - } - - /** - * Projection that signifies to return only distinct results - * - * @return Distinct projection - */ - public static Query.DistinctProjection distinct() { - return new Query.DistinctProjection(); - } - - /** - * Projection that signifies to return only distinct results - * - * @param property The name of the property - * @return Distinct projection - */ - public static Query.DistinctPropertyProjection distinct(String property) { - return new Query.DistinctPropertyProjection(property); - } - - /** - * Projection that signifies to return only distinct results - * - * @param property The name of the property - * @return Distinct projection - */ - public static Query.CountDistinctProjection countDistinct(String property) { - return new Query.CountDistinctProjection(property); - } -} 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 deleted file mode 100644 index c3c7f216a..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Query.java +++ /dev/null @@ -1,1318 +0,0 @@ -/* Copyright (C) 2010 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.mapping.query; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.persistence.FetchType; -import javax.persistence.FlushModeType; - -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.ConnectionNotFoundException; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.EntityPersister; -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.Association; -import org.grails.datastore.mapping.query.api.AssociationCriteria; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.grails.datastore.mapping.query.event.PostQueryEvent; -import org.grails.datastore.mapping.query.event.PreQueryEvent; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.dao.InvalidDataAccessResourceUsageException; -import org.springframework.util.Assert; - -/** - * Models a query that can be executed against a data store. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class Query implements Cloneable{ - - protected PersistentEntity entity; - protected Junction criteria = new Conjunction(); - protected ProjectionList projections = new ProjectionList(); - protected int max = -1; - protected int offset = 0; - protected List orderBy = new ArrayList(); - protected Session session; - protected boolean uniqueResult; - protected Map fetchStrategies = new HashMap(); - protected boolean queryCache; - - protected Query(Session session, PersistentEntity entity) { - this.entity = entity; - this.session = session; - } - - @Override - public Object clone() { - Query newQuery = getSession().createQuery(entity.getJavaClass()); - for (Criterion criterion : criteria.getCriteria()) { - newQuery.add(criterion); - } - return newQuery; - } - - /** - * @return The criteria defined by this query - */ - public Junction getCriteria() { - return criteria; - } - - /** - * Specifies whether a join query should be used (if join queries are supported by the underlying datastore) - * - * @param property The property - * @return The query - */ - public Query join(String property) { - fetchStrategies.put(property, FetchType.EAGER); - return this; - } - - /** - * Specifies whether a select (lazy) query should be used (if join queries are supported by the underlying datastore) - * - * @param property The property - * @return The query - */ - public Query select(String property) { - fetchStrategies.put(property, FetchType.LAZY); - return this; - } - - /** - * Specifies whether the query results should be cached (if supported by the underlying datastore) - * - * @param cache True if caching should be enabled - * @return The query - */ - public Query cache(boolean cache) { - queryCache = true; - return this; - } - - public ProjectionList projections() { - return projections; - } - - /** - * Adds the specified criterion instance to the query - * - * @param criterion The criterion instance - */ - public void add(Criterion criterion) { - Junction currentJunction = criteria; - addToJunction(currentJunction, criterion); - } - - /** - * @return The session that created the query - */ - public Session getSession() { - return session; - } - - /** - * @return The PersistentEntity being query - */ - public PersistentEntity getEntity() { - return entity; - } - - /** - * Creates a disjunction (OR) query - * @return The Junction instance - */ - public Junction disjunction() { - Junction currentJunction = criteria; - return disjunction(currentJunction); - } - - /** - * Creates a disjunction (OR) query - * @return The Junction instance - */ - public Junction conjunction() { - Junction currentJunction = criteria; - return conjunction(currentJunction); - } - - /** - * Creates a negation of several criterion - * @return The negation - */ - public Junction negation() { - Junction currentJunction = criteria; - return negation(currentJunction); - } - - private Junction negation(Junction currentJunction) { - Negation dis = new Negation(); - currentJunction.add(dis); - return dis; - } - - /** - * Defines the maximum number of results to return - * @param max The max results - * @return This query instance - */ - public Query max(int max) { - this.max = max; - return this; - } - - /** - * Defines the maximum number of results to return - * @param max The max results - * @return This query instance - */ - public Query maxResults(int max) { - return max(max); - } - - /** - * Defines the offset (the first result index) of the query - * @param offset The offset - * @return This query instance - */ - public Query offset(int offset) { - this.offset = offset; - return this; - } - - /** - * Defines the offset (the first result index) of the query - * @param offset The offset - * @return This query instance - */ - public Query firstResult(int offset) { - return offset(offset); - } - - /** - * Specifies the order of results - * @param order The order object - * @return The Query instance - */ - public Query order(Order order) { - if (order != null) { - orderBy.add(order); - } - return this; - } - - /** - * Gets the Order entries for this query - * @return The order entries - */ - public List getOrderBy() { - return orderBy; - } - - /** - * Restricts the results by the given properties value - * - * @param property The name of the property - * @param value The value to restrict by - * @return This query instance - */ - public Query eq(String property, Object value) { - Object resolved = resolveIdIfEntity(value); - if (resolved == value) { - criteria.add(Restrictions.eq(property, value)); - } - else { - criteria.add(Restrictions.eq(property,resolved)); - } - return this; - } - - /** - * Shortcut to restrict the query to multiple given property values - * - * @param values The values - * @return This query instance - */ - public Query allEq(Map values) { - for (String property : values.keySet()) { - eq(property, values.get(property)); - } - return this; - } - - /** - * Used to restrict a value to be empty (such as a blank string or an empty collection) - * - * @param property The property name - */ - public Query isEmpty(String property) { - criteria.add(Restrictions.isEmpty(property)); - return this; - } - - /** - * Used to restrict a value to be not empty (such as a blank string or an empty collection) - * - * @param property The property name - */ - public Query isNotEmpty(String property) { - criteria.add(Restrictions.isNotEmpty(property)); - return this; - } - - /** - * Used to restrict a property to be null - * - * @param property The property name - */ - public Query isNull(String property) { - criteria.add(Restrictions.isNull(property)); - return this; - } - - /** - * Used to restrict a property to be not null - * - * @param property The property name - */ - public Query isNotNull(String property) { - criteria.add(Restrictions.isNotNull(property)); - return this; - } - - /** - * Creates an association query - * - * @param associationName The assocation name - * @return The Query instance - */ - public AssociationQuery createQuery(String associationName) { - final PersistentProperty property = entity.getPropertyByName(associationName); - if (property == null || !(property instanceof Association)) { - throw new InvalidDataAccessResourceUsageException("Cannot query association [" + - associationName + "] of class [" + entity + - "]. The specified property is not an association."); - } - - Association association = (Association) property; - - final PersistentEntity associatedEntity = association.getAssociatedEntity(); - - return new AssociationQuery(session, associatedEntity, association); - } - - /** - * Restricts the results by the given properties value - * - * @param value The value to restrict by - * @return This query instance - */ - public Query idEq(Object value) { - value = resolveIdIfEntity(value); - - criteria.add(Restrictions.idEq(value)); - return this; - } - - /** - * Used to restrict a value to be greater than the given value - * - * @param property The name of the property - * @param value The value to restrict by - * @return This query instance - */ - public Query gt(String property, Object value) { - criteria.add(Restrictions.gt(property, value)); - return this; - } - - /** - * Used to restrict a value to be greater than or equal to the given value - * - * @param property The name of the property - * @param value The value to restrict by - * @return This query instance - */ - public Query gte(String property, Object value) { - criteria.add(Restrictions.gte(property, value)); - return this; - } - - /** - * Used to restrict a value to be less than or equal to the given value - * - * @param property The name of the property - * @param value The value to restrict by - * @return This query instance - */ - public Query lte(String property, Object value) { - criteria.add(Restrictions.lte(property, value)); - return this; - } - - /** - * Used to restrict a value to be greater than or equal to the given value - * - * @param property The name of the property - * @param value The value to restrict by - * @return This query instance - */ - public Query ge(String property, Object value) { - return gte(property, value); - } - - /** - * Used to restrict a value to be less than or equal to the given value - * - * @param property The name of the property - * @param value The value to restrict by - * @return This query instance - */ - public Query le(String property, Object value) { - return lte(property, value); - } - - /** - * Used to restrict a value to be less than the given value - * - * @param property The name of the property - * @param value The value to restrict by - * @return This query instance - */ - public Query lt(String property, Object value) { - criteria.add(Restrictions.lt(property, value)); - return this; - } - - /** - * Restricts the results by the given property values - * - * @param property The name of the property - * @param values The values to restrict by - * @return This query instance - */ - public Query in(String property, List values) { - criteria.add(Restrictions.in(property, values)); - return this; - } - - /** - * Restricts the results by the given property value range - * - * @param property The name of the property - * @param start The start of the range - * @param end The end of the range - * @return This query instance - */ - public Query between(String property, Object start, Object end) { - criteria.add(Restrictions.between(property, start, end)); - return this; - } - - /** - * Restricts the results by the given properties value - * - * @param property The name of the property - * @param expr The expression to restrict by - * @return This query instance - */ - public Query like(String property, String expr) { - criteria.add(Restrictions.like(property, expr)); - return this; - } - - /** - * Restricts the results by the given properties value - * - * @param property The name of the property - * @param expr The expression to restrict by - * @return This query instance - */ - public Query ilike(String property, String expr) { - criteria.add(Restrictions.ilike(property, expr)); - return this; - } - - /** - * Restricts the results by the given properties value - * - * @param property The name of the property - * @param expr The expression to restrict by - * @return This query instance - */ - public Query rlike(String property, String expr) { - criteria.add(Restrictions.rlike(property, expr)); - return this; - } - - /** - * Creates a conjunction using two specified criterion - * - * @param a The left hand side - * @param b The right hand side - * @return This query instance - */ - public Query and( Criterion a, Criterion b) { - Assert.notNull(a, "Left hand side of AND cannot be null"); - Assert.notNull(b, "Right hand side of AND cannot be null"); - criteria.add(Restrictions.and(a, b)); - return this; - } - - /** - * Creates a disjunction using two specified criterion - * - * @param a The left hand side - * @param b The right hand side - * @return This query instance - */ - public Query or( Criterion a, Criterion b) { - Assert.notNull(a, "Left hand side of AND cannot be null"); - Assert.notNull(b, "Right hand side of AND cannot be null"); - criteria.add(Restrictions.or(a, b)); - return this; - } - - /** - * Executes the query returning zero or many results as a list. - * - * @return The results - */ - public List list() { - uniqueResult = false; - flushBeforeQuery(); - - ApplicationEventPublisher publisher = session.getDatastore().getApplicationEventPublisher(); - if(publisher != null) { - publisher.publishEvent(new PreQueryEvent(this)); - } - - List results = executeQuery(entity, criteria); - - if(publisher != null) { - PostQueryEvent postQueryEvent = new PostQueryEvent(this, results); - publisher.publishEvent(postQueryEvent); - results = postQueryEvent.getResults(); - } - - - return results; - } - - /** - * Executes the query returning a single result or null - * @return The result - */ - public Object singleResult() { - uniqueResult = true; - List results = list(); - return results.isEmpty() ? null : results.get(0); - } - - /** - * Here purely for compatibility - * - * @param uniqueResult Whether it is a unique result - * @deprecated - */ - @Deprecated - public void setUniqueResult(boolean uniqueResult) { - this.uniqueResult = uniqueResult; - } - - /** - * Subclasses should implement this to provide the concrete implementation - * of querying - * - * @param entity The entity - * @param criteria The criteria - * @return The results - */ - protected abstract List executeQuery(PersistentEntity entity, Junction criteria); - - protected Object resolveIdIfEntity(Object value) { - // use the object id as the value if its a persistent entity - MappingContext mappingContext = session.getMappingContext(); - if (mappingContext.getProxyFactory().isProxy(value)) { - return mappingContext.getProxyFactory().getIdentifier(value); - } - return mappingContext.isPersistentEntity(value) ? findInstanceId(value) : value; - } - - private Serializable findInstanceId(Object value) { - EntityPersister ep = (EntityPersister) session.getPersister(value); - if (ep != null) { - return ep.getObjectIdentifier(value); - } - - return (Serializable)new EntityAccess(session - .getMappingContext() - .getPersistentEntity(value.getClass().getName()), value) - .getIdentifier(); - } - - private Junction disjunction(Junction currentJunction) { - Disjunction dis = new Disjunction(); - currentJunction.add(dis); - return dis; - } - - private Junction conjunction(Junction currentJunction) { - Conjunction dis = new Conjunction(); - currentJunction.add(dis); - return dis; - } - - /** - * Default behavior is the flush the session before a query in the case of FlushModeType.AUTO. - * Subclasses can override this method to disable that. - */ - protected void flushBeforeQuery() { - // flush before query execution in FlushModeType.AUTO - if (session.getFlushMode() == FlushModeType.AUTO) { - session.flush(); - } - } - - /** - * A criterion is used to restrict the results of a query - */ - private void addToJunction(Junction currentJunction, Criterion criterion) { - if (criterion instanceof PropertyCriterion) { - final PropertyCriterion pc = (PropertyCriterion) criterion; - Object value = resolveIdIfEntity(pc.getValue()); - pc.setValue(value); - } - if (criterion instanceof AssociationCriteria) { - AssociationCriteria ac = (AssociationCriteria) criterion; - AssociationQuery associationQuery = createQuery(ac.getAssociation().getName()); - for (Criterion associationCriterion : ac.getCriteria()) { - associationQuery.add(associationCriterion); - } - currentJunction.add(associationQuery); - } - else if (criterion instanceof Junction) { - Junction j = (Junction) criterion; - Junction newj; - if (j instanceof Disjunction) { - newj= disjunction(currentJunction); - } else if (j instanceof Negation) { - newj= negation(currentJunction); - } - else { - newj= conjunction(currentJunction); - } - for (Criterion c : j.getCriteria()) { - addToJunction(newj, c); - } - } - else { - currentJunction.add(criterion); - } - } - - public static interface Criterion {} - - /** - * The ordering of results. - */ - public static class Order { - private Direction direction = Direction.ASC; - private String property; - - public Order(String property) { - this.property = property; - } - - public Order(String property, Direction direction) { - this.direction = direction; - this.property = property; - } - - public Direction getDirection() { - return direction; - } - - public String getProperty() { - return property; - } - - public static Order desc(String property) { - return new Order(property, Direction.DESC); - } - - public static Order asc(String property) { - return new Order(property, Direction.ASC); - } - - public static enum Direction { - ASC, DESC - } - } - - /** - * Restricts a property to be null - */ - public static class IsNull extends PropertyNameCriterion { - public IsNull(String name) { - super(name); - } - } - - /** - * Restricts a property to be empty (such as a blank string) - */ - public static class IsEmpty extends PropertyNameCriterion { - public IsEmpty(String name) { - super(name); - } - } - - /** - * Restricts a property to be empty (such as a blank string) - */ - public static class IsNotEmpty extends PropertyNameCriterion { - public IsNotEmpty(String name) { - super(name); - } - } - - /** - * Restricts a property to be not null - */ - public static class IsNotNull extends PropertyNameCriterion { - public IsNotNull(String name) { - super(name); - } - } - - /** - * A Criterion that applies to a property - */ - public static class PropertyNameCriterion implements Criterion { - protected String name; - - public PropertyNameCriterion(String name) { - this.name = name; - } - - public String getProperty() { - return name; - } - } - - /** - * A Criterion that compares to properties - */ - public static class PropertyComparisonCriterion extends PropertyNameCriterion{ - protected String otherProperty; - - public PropertyComparisonCriterion(String property, String otherProperty) { - super(property); - this.otherProperty = otherProperty; - } - - public String getOtherProperty() { - return otherProperty; - } - } - - public static class EqualsProperty extends PropertyComparisonCriterion { - public EqualsProperty(String property, String otherProperty) { - super(property, otherProperty); - } - } - - public static class NotEqualsProperty extends PropertyComparisonCriterion { - public NotEqualsProperty(String property, String otherProperty) { - super(property, otherProperty); - } - } - - public static class GreaterThanProperty extends PropertyComparisonCriterion { - public GreaterThanProperty(String property, String otherProperty) { - super(property, otherProperty); - } - } - - public static class GreaterThanEqualsProperty extends PropertyComparisonCriterion { - public GreaterThanEqualsProperty(String property, String otherProperty) { - super(property, otherProperty); - } - } - - public static class LessThanProperty extends PropertyComparisonCriterion { - public LessThanProperty(String property, String otherProperty) { - super(property, otherProperty); - } - } - - public static class LessThanEqualsProperty extends PropertyComparisonCriterion { - public LessThanEqualsProperty(String property, String otherProperty) { - super(property, otherProperty); - } - } - - /** - * Criterion that applies to a property and value - */ - public static class PropertyCriterion extends PropertyNameCriterion { - - protected Object value; - - public PropertyCriterion(String name, Object value) { - super(name); - this.value = value; - } - - public Object getValue() { - return value; - } - - public void setValue(Object v) { - this.value = v; - } - } - - /** - * Used to differentiate criterion that require a subquery - */ - public static class SubqueryCriterion extends PropertyCriterion { - public SubqueryCriterion(String name, QueryableCriteria value) { - super(name, value); - } - } - - public static class EqualsAll extends SubqueryCriterion{ - public EqualsAll(String name, QueryableCriteria value) { - super(name, value); - } - } - - public static class NotEqualsAll extends SubqueryCriterion{ - public NotEqualsAll(String name, QueryableCriteria value) { - super(name, value); - } - } - - public static class GreaterThanAll extends SubqueryCriterion{ - public GreaterThanAll(String name, QueryableCriteria value) { - super(name, value); - } - } - - public static class LessThanAll extends SubqueryCriterion{ - public LessThanAll(String name, QueryableCriteria value) { - super(name, value); - } - } - - public static class GreaterThanEqualsAll extends SubqueryCriterion{ - public GreaterThanEqualsAll(String name, QueryableCriteria value) { - super(name, value); - } - } - - public static class LessThanEqualsAll extends SubqueryCriterion{ - public LessThanEqualsAll(String name, QueryableCriteria value) { - super(name, value); - } - } - - /** - * A criterion that restricts the results based on equality - */ - public static class Equals extends PropertyCriterion { - - public Equals(String name, Object value) { - super(name, value); - } - - @Override - public void setValue(Object value) { - this.value = value; - } - } - - public static class SizeEquals extends PropertyCriterion{ - public SizeEquals(String name, int value) { - super(name, value); - } - } - - public static class SizeNotEquals extends PropertyCriterion{ - public SizeNotEquals(String name, int value) { - super(name, value); - } - } - - public static class SizeGreaterThan extends PropertyCriterion{ - public SizeGreaterThan(String name, int value) { - super(name, value); - } - } - - public static class SizeGreaterThanEquals extends PropertyCriterion{ - public SizeGreaterThanEquals(String name, int value) { - super(name, value); - } - } - - public static class SizeLessThanEquals extends PropertyCriterion{ - public SizeLessThanEquals(String name, int value) { - super(name, value); - } - } - - public static class SizeLessThan extends PropertyCriterion{ - public SizeLessThan(String name, int value) { - super(name, value); - } - } - - /** - * A criterion that restricts the results based on the equality of the identifier - */ - public static class IdEquals extends PropertyCriterion { - - private static final String ID = "id"; - - public IdEquals(Object value) { - super(ID, value); - } - - @Override - public void setValue(Object value) { - this.value = value; - } - } - - /** - * A criterion that restricts the results based on equality - */ - public static class NotEquals extends PropertyCriterion { - - public NotEquals(String name, Object value) { - super(name, value); - } - - @Override - public void setValue(Object value) { - this.value = value; - } - } - - /** - * Criterion used to restrict the results based on a list of values - */ - public static class In extends PropertyCriterion { - private String name; - private Collection values = Collections.emptyList(); - - public In(String name, Collection values) { - super(name, values); - this.name = name; - this.values = values; - } - - public String getName() { - return name; - } - - @Override - public String getProperty() { - return getName(); - } - - public Collection getValues() { - return Collections.unmodifiableCollection(values); - } - } - - /** - * Used to restrict a value to be greater than the given value - */ - public static class GreaterThan extends PropertyCriterion { - public GreaterThan(String name, Object value) { - super(name, value); - } - } - - /** - * Used to restrict a value to be greater than or equal to the given value - */ - public static class GreaterThanEquals extends PropertyCriterion { - public GreaterThanEquals(String name, Object value) { - super(name, value); - } - } - - /** - * Used to restrict a value to be less than the given value - */ - public static class LessThan extends PropertyCriterion { - public LessThan(String name, Object value) { - super(name, value); - } - } - - /** - * Used to restrict a value to be less than the given value - */ - public static class LessThanEquals extends PropertyCriterion { - public LessThanEquals(String name, Object value) { - super(name, value); - } - } - - /** - * Criterion used to restrict the result to be between values (range query) - */ - public static class Between extends PropertyCriterion { - private String property; - private Object from; - private Object to; - - public Between(String property, Object from, Object to) { - super(property, from); - this.property = property; - this.from = from; - this.to = to; - } - - @Override - public String getProperty() { - return property; - } - - public Object getFrom() { - return from; - } - - public Object getTo() { - return to; - } - } - - /** - * Criterion used to restrict the results based on a pattern (likeness) - */ - public static class Like extends PropertyCriterion { - public Like(String name, String expression) { - super(name, expression); - } - - public String getPattern() { - return getValue().toString(); - } - } - - /** - * Criterion used to restrict the results based on a pattern (likeness) - */ - public static class ILike extends Like { - public ILike(String name, String expression) { - super(name, expression); - } - } - - /** - * Criterion used to restrict the results based on a regular expression pattern - */ - public static class RLike extends Like { - public RLike(String name, String expression) { - super(name, expression); - } - - @Override - public String getPattern() { - return getValue().toString(); - } - } - - public static abstract class Junction implements Criterion { - private List criteria = new ArrayList(); - - protected Junction() { - } - - public Junction(List criteria) { - this.criteria = criteria; - } - - public Junction add(Criterion c) { - if (c != null) { - if (c instanceof Equals) { - final Equals eq = (Equals) c; - Object value = eq.getValue(); - - if (value != null) { - - try { - Session session = AbstractDatastore.retrieveSession(); - final PersistentEntity persistentEntity = session.getMappingContext().getPersistentEntity(value.getClass().getName()); - if (persistentEntity != null) { - EntityPersister ep = (EntityPersister) session.getPersister(value); - - if (ep != null) { - c = new Equals(eq.getProperty(), ep.getObjectIdentifier(value)); - } - } - } catch (ConnectionNotFoundException e) { - // continue, use original value - } - } - } - criteria.add(c); - } - return this; - } - - public List getCriteria() { - return criteria; - } - - public boolean isEmpty() { - return criteria.isEmpty(); - } - } - - /** - * A Criterion used to combine to criterion in a logical AND - */ - public static class Conjunction extends Junction { - public Conjunction() { - } - - public Conjunction(List criteria) { - super(criteria); - } - } - - /** - * A Criterion used to combine to criterion in a logical OR - */ - public static class Disjunction extends Junction { - public Disjunction() { - } - - public Disjunction(List criteria) { - super(criteria); - } - } - - /** - * A criterion used to negate several other criterion - */ - public static class Negation extends Junction {} - - /** - * A projection - */ - public static class Projection {} - - /** - * A projection used to obtain the identifier of an object - */ - public static class IdProjection extends Projection {} - - /** - * Used to count the results of a query - */ - public static class CountProjection extends Projection {} - - public static class DistinctProjection extends Projection {} - - /** - * A projection that obtains the value of a property of an entity - */ - public static class PropertyProjection extends Projection { - private String propertyName; - - protected PropertyProjection(String propertyName) { - this.propertyName = propertyName; - } - - public String getPropertyName() { - return propertyName; - } - } - - public static class DistinctPropertyProjection extends PropertyProjection{ - protected DistinctPropertyProjection(String propertyName) { - super(propertyName); - } - } - - public static class CountDistinctProjection extends PropertyProjection{ - public CountDistinctProjection(String property) { - super(property); - } - } - - /** - * Computes the average value of a property - */ - public static class AvgProjection extends PropertyProjection { - protected AvgProjection(String propertyName) { - super(propertyName); - } - } - - /** - * Computes the max value of a property - */ - public static class MaxProjection extends PropertyProjection { - protected MaxProjection(String propertyName) { - super(propertyName); - } - } - - /** - * Computes the min value of a property - */ - public static class MinProjection extends PropertyProjection { - protected MinProjection(String propertyName) { - super(propertyName); - } - } - - /** - * Computes the sum of a property - */ - public static class SumProjection extends PropertyProjection { - protected SumProjection(String propertyName) { - super(propertyName); - } - } - - - /** - * A list of projections - */ - public static class ProjectionList implements org.grails.datastore.mapping.query.api.ProjectionList { - - private List projections = new ArrayList(); - - public List getProjectionList() { - return Collections.unmodifiableList(projections); - } - - public ProjectionList add(Projection p) { - projections.add(p); - return this; - } - - public org.grails.datastore.mapping.query.api.ProjectionList id() { - add(Projections.id()); - return this; - } - - public org.grails.datastore.mapping.query.api.ProjectionList count() { - add(Projections.count()); - return this; - } - - public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(String property) { - add(Projections.countDistinct(property)); - return this; - } - - public boolean isEmpty() { - return projections.isEmpty(); - } - - public ProjectionList distinct() { - return this; - } - - public org.grails.datastore.mapping.query.api.ProjectionList distinct(String property) { - add(Projections.distinct(property)); - return this; - } - - public org.grails.datastore.mapping.query.api.ProjectionList rowCount() { - return count(); - } - - /** - * A projection that obtains the value of a property of an entity - * @param name The name of the property - * @return The PropertyProjection instance - */ - public org.grails.datastore.mapping.query.api.ProjectionList property(String name) { - add(Projections.property(name)); - return this; - } - - /** - * Computes the sum of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - public org.grails.datastore.mapping.query.api.ProjectionList sum(String name) { - add(Projections.sum(name)); - return this; - } - - /** - * Computes the min value of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - public org.grails.datastore.mapping.query.api.ProjectionList min(String name) { - add(Projections.min(name)); - return this; - } - - /** - * Computes the max value of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - public org.grails.datastore.mapping.query.api.ProjectionList max(String name) { - add(Projections.max(name)); - return this; - } - - /** - * Computes the average value of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - public org.grails.datastore.mapping.query.api.ProjectionList avg(String name) { - add(Projections.avg(name)); - return this; - } - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Restrictions.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Restrictions.java deleted file mode 100644 index 4329432a5..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Restrictions.java +++ /dev/null @@ -1,323 +0,0 @@ -/* Copyright (C) 2010 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.mapping.query; - -import java.util.Collection; - -/** - * Factory for creating {@link org.grails.datastore.mapping.query.Query.Criterion} instances - */ -public class Restrictions { - - /** - * Restricts the property to be equal to the given value - * @param property The property - * @param value The value - * @return An instance of Query.Equals - */ - public static Query.Equals eq(String property, Object value) { - return new Query.Equals(property, value); - } - - /** - * Restricts the property to be equal to the given value - * @param value The value - * @return An instance of Query.Equals - */ - public static Query.IdEquals idEq(Object value) { - return new Query.IdEquals(value); - } - - /** - * Restricts the property to be not equal to the given value - * @param property The property - * @param value The value - * @return An instance of Query.Equals - */ - - public static Query.NotEquals ne(String property, Object value) { - return new Query.NotEquals(property, value); - } - - /** - * Restricts the property to be in the list of given values - * @param property The property - * @param values The values - * @return An instance of Query.In - */ - public static Query.In in(String property, Collection values) { - return new Query.In(property, values); - } - - /** - * Restricts the property match the given String expressions. Expressions use SQL-like % to denote wildcards - * @param property The property name - * @param expression The expression - * @return An instance of Query.Like - */ - public static Query.Like like(String property, String expression) { - return new Query.Like(property, expression); - } - - public static Query.ILike ilike(String property, String expression) { - return new Query.ILike(property, expression); - } - - /** - * Restricts the property match the given regular expressions. - * - * @param property The property name - * @param expression The expression - * @return An instance of Query.RLike - */ - public static Query.RLike rlike(String property, String expression) { - return new Query.RLike(property, expression); - } - - public static Query.Criterion and(Query.Criterion a, Query.Criterion b) { - return new Query.Conjunction().add(a).add(b); - } - - public static Query.Criterion or(Query.Criterion a, Query.Criterion b) { - return new Query.Disjunction().add(a).add(b); - } - - /** - * Restricts the results by the given property value range - * - * @param property The name of the property - * @param start The start of the range - * @param end The end of the range - * @return The Between instance - */ - public static Query.Between between(String property, Object start, Object end) { - return new Query.Between(property, start, end); - } - - /** - * Used to restrict a value to be greater than the given value - * @param property The property - * @param value The value - * @return The GreaterThan instance - */ - public static Query.GreaterThan gt(String property, Object value) { - return new Query.GreaterThan(property, value); - } - - /** - * Used to restrict a value to be less than the given value - * @param property The property - * @param value The value - * @return The LessThan instance - */ - public static Query.LessThan lt(String property, Object value) { - return new Query.LessThan(property, value); - } - - /** - * Used to restrict a value to be greater than or equal to the given value - * @param property The property - * @param value The value - * @return The LessThan instance - */ - public static Query.GreaterThanEquals gte(String property, Object value) { - return new Query.GreaterThanEquals(property, value); - } - - /** - * Used to restrict a value to be less than or equal to the given value - * @param property The property - * @param value The value - * @return The LessThan instance - */ - public static Query.LessThanEquals lte(String property, Object value) { - return new Query.LessThanEquals(property, value); - } - - /** - * Used to restrict a value to be null - * - * @param property The property name - * @return The IsNull instance - */ - public static Query.IsNull isNull(String property) { - return new Query.IsNull(property); - } - - /** - * Used to restrict a value to be empty (such as a blank string or an empty collection) - * - * @param property The property name - * @return The IsEmpty instance - */ - public static Query.IsEmpty isEmpty(String property) { - return new Query.IsEmpty(property); - } - - /** - * Used to restrict a value to be not empty (such as a non-blank string) - * - * @param property The property name - * @return The IsEmpty instance - */ - public static Query.IsNotEmpty isNotEmpty(String property) { - return new Query.IsNotEmpty(property); - } - - /** - * Used to restrict a value to be null - * - * @param property The property name - * @return The IsNull instance - */ - public static Query.IsNotNull isNotNull(String property) { - return new Query.IsNotNull(property); - } - - /** - * Used to restrict the size of a collection property - * - * @param property The property - * @param size The size to restrict - * @return The result - */ - public static Query.SizeEquals sizeEq(String property, int size) { - return new Query.SizeEquals(property, size); - } - - /** - * Used to restrict the size of a collection property to be greater than the given value - * - * @param property The property - * @param size The size to restrict - * @return The result - */ - public static Query.SizeGreaterThan sizeGt(String property, int size) { - return new Query.SizeGreaterThan(property, size); - } - - /** - * Used to restrict the size of a collection property to be greater than or equal to the given value - * - * @param property The property - * @param size The size to restrict - * @return The result - */ - public static Query.SizeGreaterThanEquals sizeGe(String property, int size) { - return new Query.SizeGreaterThanEquals(property, size); - } - - /** - * Creates a Criterion that contrains a collection property to be less than or equal to the given size - * - * @param property The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public static Query.SizeLessThanEquals sizeLe(String property, int size) { - return new Query.SizeLessThanEquals(property, size); - } - - /** - * Creates a Criterion that contrains a collection property to be less than to the given size - * - * @param property The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public static Query.SizeLessThan sizeLt(String property, int size) { - return new Query.SizeLessThan(property, size); - } - - /** - * Creates a Criterion that contrains a collection property to be not equal to the given size - * - * @param property The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public static Query.SizeNotEquals sizeNe(String property, int size) { - return new Query.SizeNotEquals(property, size); - } - - /** - * Constraints a property to be equal to a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return The criterion instance - */ - public static Query.EqualsProperty eqProperty(String propertyName, String otherPropertyName) { - return new Query.EqualsProperty(propertyName, otherPropertyName); - } - - /** - * Constraints a property to be not equal to a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criterion instance - */ - public static Query.NotEqualsProperty neProperty(String propertyName, String otherPropertyName) { - return new Query.NotEqualsProperty(propertyName, otherPropertyName); - } - - /** - * Constraints a property to be greater than a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return The criterion - */ - public static Query.GreaterThanProperty gtProperty(String propertyName, String otherPropertyName) { - return new Query.GreaterThanProperty(propertyName, otherPropertyName); - } - - /** - * Constraints a property to be greater than or equal to a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return The criterion - */ - public static Query.GreaterThanEqualsProperty geProperty(String propertyName, String otherPropertyName) { - return new Query.GreaterThanEqualsProperty(propertyName, otherPropertyName); - } - - /** - * Constraints a property to be less than a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return The criterion - */ - public static Query.LessThanProperty ltProperty(String propertyName, String otherPropertyName) { - return new Query.LessThanProperty(propertyName, otherPropertyName); - } - - /** - * Constraints a property to be less than or equal to a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return The criterion - */ - public static Query.LessThanEqualsProperty leProperty(String propertyName, String otherPropertyName) { - return new Query.LessThanEqualsProperty(propertyName, otherPropertyName); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/AssociationCriteria.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/AssociationCriteria.java deleted file mode 100644 index 25d841b4b..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/AssociationCriteria.java +++ /dev/null @@ -1,34 +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.mapping.query.api; - -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.query.Query; - -import java.util.List; - -/** - * Interface for criteria related to an association - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface AssociationCriteria { - - @SuppressWarnings("rawtypes") - Association getAssociation(); - - List getCriteria(); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/Criteria.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/Criteria.java deleted file mode 100644 index 5aeb58fcc..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/Criteria.java +++ /dev/null @@ -1,406 +0,0 @@ -/* Copyright (C) 2010 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.mapping.query.api; - -import java.util.Collection; - -/** - * Interface for the implementations that construct of criteria queries. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public interface Criteria { - - /** - * Creates a criterion that restricts the id to the given value - * @param value The value - * @return The criteria - */ - Criteria idEquals(Object value); - - /** - * Creates a criterion that asserts the given property is empty (such as a blank string) - * - * @param propertyName The property name - * @return The criteria - */ - Criteria isEmpty(String propertyName); - - /** - * Creates a criterion that asserts the given property is not empty - * - * @param propertyName The property name - * @return The criteria - */ - Criteria isNotEmpty(String propertyName); - - /** - * Creates a criterion that asserts the given property is null - * - * @param propertyName The property name - * @return The criteria - */ - Criteria isNull(String propertyName); - - /** - * Creates a criterion that asserts the given property is not null - * - * @param propertyName The property name - * @return The criteria - */ - Criteria isNotNull(String propertyName); - - /** - * Creates an "equals" Criterion based on the specified property name and value. - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return The criteria - */ - Criteria eq(String propertyName, Object propertyValue); - - /** - * Creates an "equals" Criterion based on the specified property name and value. - * - * @param propertyValue The property value - * - * @return The criteria - */ - Criteria idEq(Object propertyValue); - - /** - * Creates a "not equals" Criterion based on the specified property name and value. - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return The criteria - */ - Criteria ne(String propertyName, Object propertyValue); - - /** - * Restricts the results by the given property value range (inclusive) - * - * @param propertyName The property name - * - * @param start The start of the range - * @param finish The end of the range - * @return The criteria - */ - Criteria between(String propertyName, Object start, Object finish); - - /** - * Used to restrict a value to be greater than or equal to the given value - * @param property The property - * @param value The value - * @return The Criterion instance - */ - Criteria gte(String property, Object value); - - /** - * Used to restrict a value to be greater than or equal to the given value - * @param property The property - * @param value The value - * @return The Criterion instance - */ - Criteria ge(String property, Object value); - - /** - * Used to restrict a value to be greater than or equal to the given value - * @param property The property - * @param value The value - * @return The Criterion instance - */ - Criteria gt(String property, Object value); - - /** - * Used to restrict a value to be less than or equal to the given value - * @param property The property - * @param value The value - * @return The Criterion instance - */ - Criteria lte(String property, Object value); - - /** - * Used to restrict a value to be less than or equal to the given value - * @param property The property - * @param value The value - * @return The Criterion instance - */ - Criteria le(String property, Object value); - - /** - * Used to restrict a value to be less than or equal to the given value - * @param property The property - * @param value The value - * @return The Criterion instance - */ - Criteria lt(String property, Object value); - - /** - * Creates an like Criterion based on the specified property name and value. - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return The criteria - */ - Criteria like(String propertyName, Object propertyValue); - - /** - * Creates an ilike Criterion based on the specified property name and value. Unlike a like condition, ilike is case insensitive - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return The criteria - */ - Criteria ilike(String propertyName, Object propertyValue); - - /** - * Creates an rlike Criterion based on the specified property name and value. - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return The criteria - */ - Criteria rlike(String propertyName, Object propertyValue); - - /** - * Creates an "in" Criterion based on the specified property name and list of values. - * - * @param propertyName The property name - * @param values The values - * - * @return The criteria - */ - Criteria in(String propertyName, Collection values); - - /** - * Creates an "in" Criterion based on the specified property name and list of values. - * - * @param propertyName The property name - * @param values The values - * - * @return The criteria - */ - Criteria inList(String propertyName, Collection values); - - /** - * Creates an "in" Criterion based on the specified property name and list of values. - * - * @param propertyName The property name - * @param values The values - * - * @return The criteria - */ - Criteria inList(String propertyName, Object[] values); - - /** - * Creates an "in" Criterion based on the specified property name and list of values. - * - * @param propertyName The property name - * @param values The values - * - * @return The criteria - */ - Criteria in(String propertyName, Object[] values); - - /** - * Orders by the specified property name (defaults to ascending) - * - * @param propertyName The property name to order by - * @return This criteria - */ - Criteria order(String propertyName); - - /** - * Orders by the specified property name and direction - * - * @param propertyName The property name to order by - * @param direction Either "asc" for ascending or "desc" for descending - * - * @return This criteria - */ - Criteria order(String propertyName, String direction); - - /** - * Creates a Criterion that contrains a collection property by size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return This criteria - */ - Criteria sizeEq(String propertyName, int size) ; - - /** - * Creates a Criterion that contrains a collection property to be greater than the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return This criteria - */ - Criteria sizeGt(String propertyName, int size); - - /** - * Creates a Criterion that contrains a collection property to be greater than or equal to the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return This criteria - */ - Criteria sizeGe(String propertyName, int size); - - /** - * Creates a Criterion that contrains a collection property to be less than or equal to the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return This criteria - */ - Criteria sizeLe(String propertyName, int size); - - /** - * Creates a Criterion that contrains a collection property to be less than to the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return This criteria - */ - Criteria sizeLt(String propertyName, int size); - - /** - * Creates a Criterion that contrains a collection property to be not equal to the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return This criteria - */ - Criteria sizeNe(String propertyName, int size); - - /** - * Constraints a property to be equal to a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criteria - */ - Criteria eqProperty(java.lang.String propertyName, java.lang.String otherPropertyName); - - /** - * Constraints a property to be not equal to a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criteria - */ - Criteria neProperty(java.lang.String propertyName, java.lang.String otherPropertyName); - - /** - * Constraints a property to be greater than a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criteria - */ - Criteria gtProperty(java.lang.String propertyName, java.lang.String otherPropertyName); - - /** - * Constraints a property to be greater than or equal to a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criteria - */ - Criteria geProperty(java.lang.String propertyName, java.lang.String otherPropertyName); - - /** - * Constraints a property to be less than a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criteria - */ - Criteria ltProperty(java.lang.String propertyName, java.lang.String otherPropertyName); - - /** - * Constraints a property to be less than or equal to a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criteria - */ - Criteria leProperty(java.lang.String propertyName, java.lang.String otherPropertyName); - - /** - * Creates a subquery criterion that ensures the given property is equal to all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - Criteria eqAll(String propertyName, QueryableCriteria propertyValue); - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - Criteria gtAll(String propertyName, QueryableCriteria propertyValue); - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - Criteria ltAll(String propertyName, QueryableCriteria propertyValue); - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - Criteria geAll(String propertyName, QueryableCriteria propertyValue); - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - Criteria leAll(String propertyName, QueryableCriteria propertyValue); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/ProjectionList.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/ProjectionList.java deleted file mode 100644 index e77e4b50a..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/ProjectionList.java +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2010 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.mapping.query.api; - -/** - * Models a list of projections - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface ProjectionList { - /** - * A Projection that obtains the id of an object - * @return The projection list - */ - ProjectionList id(); - - /** - * Count the number of records returned - * @return The projection list - */ - ProjectionList count(); - - /** - * Count the number of records returned - * @param property The property name to count - * @return The projection list - */ - ProjectionList countDistinct(String property); - - /** - * Projection to return only distinct records - * - * @return The projection list - */ - ProjectionList distinct(); - - /** - * Projection to return only distinct properties - * - * @param property The property name to use - * - * @return The projection list - */ - ProjectionList distinct(String property); - - /** - * Count the number of records returned - * @return The projection list - */ - ProjectionList rowCount(); - - /** - * A projection that obtains the value of a property of an entity - * @param name The name of the property - * @return The PropertyProjection instance - */ - ProjectionList property(String name); - - /** - * Computes the sum of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - ProjectionList sum(String name); - - /** - * Computes the min value of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - ProjectionList min(String name); - - /** - * Computes the max value of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - ProjectionList max(String name); - - /** - * Computes the average value of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - ProjectionList avg(String name); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryArgumentsAware.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryArgumentsAware.java deleted file mode 100644 index 28b7eb527..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryArgumentsAware.java +++ /dev/null @@ -1,33 +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.mapping.query.api; - -import java.util.Map; - -/** - * Interface for classes that are interested in additional query arguments - * defined as a map for things like the limit, offset and join information - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface QueryArgumentsAware { - - /** - * @param arguments The query arguments - */ - void setArguments(@SuppressWarnings("rawtypes") Map arguments); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryableCriteria.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryableCriteria.java deleted file mode 100644 index 9d7bcf7f0..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryableCriteria.java +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (C) 2010 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.mapping.query.api; - -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.Query; - -import java.util.List; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public interface QueryableCriteria extends Criteria{ - - /** - * @return The target entity - */ - PersistentEntity getPersistentEntity(); - /** - * @return A list of all criteria - */ - List getCriteria(); - - List getProjections(); - - /** - * @return Find a single result - */ - T find(); - - /** - * List all results - * @return All results - */ - List list(); - -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/criteria/FunctionCallingCriterion.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/criteria/FunctionCallingCriterion.java deleted file mode 100644 index 078d3e8d4..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/criteria/FunctionCallingCriterion.java +++ /dev/null @@ -1,58 +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.mapping.query.criteria; - -import org.grails.datastore.mapping.query.Query; - -/** - * This criterion calls a function on the property before apply the appropriate comparison. - * - * Example in SQL: year(date) == 2007 where the function is 'year', the property 'date' and the value is '2007' - */ -public class FunctionCallingCriterion extends Query.PropertyNameCriterion { - - private String functionName; - private Query.PropertyCriterion propertyCriterion; - private boolean onValue; - - public FunctionCallingCriterion(String functionName, Query.PropertyCriterion propertyCriterion) { - super(propertyCriterion.getProperty()); - this.functionName = functionName; - this.propertyCriterion = propertyCriterion; - } - - public FunctionCallingCriterion(String name, String functionName, Query.PropertyCriterion propertyCriterion, boolean onValue) { - super(name); - this.functionName = functionName; - this.propertyCriterion = propertyCriterion; - this.onValue = onValue; - } - - public String getFunctionName() { - return functionName; - } - - public Query.PropertyCriterion getPropertyCriterion() { - return propertyCriterion; - } - - /** - * Whether the function is called on the value or on the property - * - */ - public boolean isOnValue() { - return onValue; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/AbstractQueryEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/AbstractQueryEvent.java deleted file mode 100644 index 36d04143d..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/AbstractQueryEvent.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.grails.datastore.mapping.query.event; - -import org.grails.datastore.mapping.query.Query; -import org.springframework.context.ApplicationEvent; - -/** - * Base class for query events. - */ -public abstract class AbstractQueryEvent extends ApplicationEvent { - /** - * The query. - */ - protected Query query; - - public AbstractQueryEvent(Query query) { - super(query.getSession().getDatastore()); - this.query = query; - } - - /** - * @return The type of event. - */ - public abstract QueryEventType getEventType(); - - /** - * Get the query from the event. - * @return The query. - */ - public Query getQuery() { - return query; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PostQueryEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PostQueryEvent.java deleted file mode 100644 index 536b53d6b..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PostQueryEvent.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.grails.datastore.mapping.query.event; - -import org.grails.datastore.mapping.query.Query; - -import java.util.List; - -/** - * Query fired after a query has run. - */ -public class PostQueryEvent extends AbstractQueryEvent { - /** - * The results of the query. - */ - private List results; - - public PostQueryEvent(Query query, List results) { - super(query); - this.results = results; - } - - /** - * @return The results of the query. Note that this list is usually non-modifiable. - */ - public List getResults() { - return results; - } - - /** - * Reset the list of results to a new list. This allows an event handler to modify the results of a query. - * @param results The replacement results. - */ - public void setResults(List results) { - if (results == null) { - throw new IllegalArgumentException("results must be non-null"); - } - this.results = results; - } - - /** - * @return The type of event. - */ - @Override - public QueryEventType getEventType() { - return QueryEventType.PostExecution; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PreQueryEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PreQueryEvent.java deleted file mode 100644 index 43ddb9a2c..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PreQueryEvent.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.grails.datastore.mapping.query.event; - -import org.grails.datastore.mapping.query.Query; - -/** - * Event fired immediately before a query is executed. - */ -public class PreQueryEvent extends AbstractQueryEvent { - public PreQueryEvent(Query query) { - super(query); - } - - /** - * @return The type of event. - */ - @Override - public QueryEventType getEventType() { - return QueryEventType.PreExecution; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/QueryEventType.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/QueryEventType.java deleted file mode 100644 index fd88a2ac7..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/QueryEventType.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.grails.datastore.mapping.query.event; - -/** - * The type of a query event. - */ -public enum QueryEventType { - PreExecution, - PostExecution -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryBuilder.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryBuilder.java deleted file mode 100644 index f8358386d..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryBuilder.java +++ /dev/null @@ -1,773 +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.mapping.query.jpa; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -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.grails.datastore.mapping.query.AssociationQuery; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.AssociationCriteria; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.support.GenericConversionService; -import org.springframework.dao.InvalidDataAccessResourceUsageException; - -/** - * Builds JPA 1.0 String-based queries from the Query model - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class JpaQueryBuilder { - private static final String DISTINCT_CLAUSE = "DISTINCT "; - private static final String SELECT_CLAUSE = "SELECT "; - private static final String AS_CLAUSE = " AS "; - private static final String FROM_CLAUSE = " FROM "; - private static final String ORDER_BY_CLAUSE = " ORDER BY "; - private static final String WHERE_CLAUSE = " WHERE "; - private static final char COMMA = ','; - private static final char CLOSE_BRACKET = ')'; - private static final char OPEN_BRACKET = '('; - private static final char SPACE = ' '; - private static final char QUESTIONMARK = '?'; - private static final char DOT = '.'; - public static final String NOT_CLAUSE = " NOT"; - public static final String LOGICAL_AND = " AND "; - public static final String UPDATE_CLAUSE = "UPDATE "; - public static final String DELETE_CLAUSE = "DELETE "; - - public static final String LOGICAL_OR = " OR "; - private static final Map queryHandlers = new HashMap(); - private PersistentEntity entity; - private Query.Junction criteria; - private Query.ProjectionList projectionList = new Query.ProjectionList(); - private List orders= Collections.emptyList(); - private String logicalName; - private ConversionService conversionService = new GenericConversionService(); - private boolean hibernateCompatible; - - public JpaQueryBuilder(QueryableCriteria criteria) { - this(criteria.getPersistentEntity(), criteria.getCriteria()); - } - - public JpaQueryBuilder(PersistentEntity entity, List criteria) { - this(entity, new Query.Conjunction(criteria)); - } - - public JpaQueryBuilder(PersistentEntity entity,List criteria, Query.ProjectionList projectionList) { - this(entity, new Query.Conjunction(criteria), projectionList); - } - - public JpaQueryBuilder(PersistentEntity entity, List criteria, Query.ProjectionList projectionList, List orders) { - this(entity, new Query.Conjunction(criteria), projectionList, orders); - } - - public JpaQueryBuilder(PersistentEntity entity, Query.Junction criteria) { - this.entity = entity; - this.criteria = criteria; - this.logicalName = entity.getDecapitalizedName(); - } - - public JpaQueryBuilder(PersistentEntity entity, Query.Junction criteria, Query.ProjectionList projectionList) { - this(entity, criteria); - this.projectionList = projectionList; - } - - public JpaQueryBuilder(PersistentEntity entity, Query.Junction criteria, Query.ProjectionList projectionList, List orders) { - this(entity, criteria, projectionList); - this.orders = orders; - } - - public void setHibernateCompatible(boolean hibernateCompatible) { - this.hibernateCompatible = hibernateCompatible; - } - - public void setConversionService(ConversionService conversionService) { - this.conversionService = conversionService; - } - - /** - * Builds an UPDATE statement. - * - * @param propertiesToUpdate THe properties to update - * @return The JpaQueryInfo object - */ - public JpaQueryInfo buildUpdate(Map propertiesToUpdate) { - if (propertiesToUpdate.isEmpty()) { - throw new InvalidDataAccessResourceUsageException("No properties specified to update"); - } - StringBuilder queryString = new StringBuilder(UPDATE_CLAUSE).append(entity.getName()).append(SPACE).append(logicalName); - - List parameters = new ArrayList(); - buildUpdateStatement(queryString, propertiesToUpdate, parameters, hibernateCompatible); - StringBuilder whereClause = new StringBuilder(); - buildWhereClause(entity, criteria, queryString, whereClause, logicalName, false, parameters); - return new JpaQueryInfo(queryString.toString(), parameters); - } - - /** - * Builds a DELETE statement - * - * @return The JpaQueryInfo - */ - public JpaQueryInfo buildDelete() { - StringBuilder queryString = new StringBuilder(DELETE_CLAUSE).append(entity.getName()).append(SPACE).append(logicalName); - StringBuilder whereClause = new StringBuilder(); - List parameters = buildWhereClause(entity, criteria, queryString, whereClause, logicalName, false); - return new JpaQueryInfo(queryString.toString(), parameters); - } - - /** - * Builds SELECT statement - * - * @return The JpaQueryInfo - */ - public JpaQueryInfo buildSelect() { - StringBuilder queryString = new StringBuilder(SELECT_CLAUSE); - - buildSelectClause(queryString); - - StringBuilder whereClause= new StringBuilder(); - List parameters = null; - if (!criteria.isEmpty()) { - parameters = buildWhereClause(entity, criteria, queryString, whereClause,logicalName, true); - } - - appendOrder(queryString, logicalName); - return new JpaQueryInfo(queryString.toString(), parameters); - } - - private void buildSelectClause(StringBuilder queryString) { - if (projectionList.isEmpty()) { - queryString.append(DISTINCT_CLAUSE) - .append(logicalName); - } - else { - for (Iterator i = projectionList.getProjectionList().iterator(); i.hasNext();) { - Query.Projection projection = (Query.Projection) i.next(); - if (projection instanceof Query.CountProjection) { - queryString.append("COUNT(") - .append(logicalName) - .append(CLOSE_BRACKET); - } - else if (projection instanceof Query.IdProjection) { - queryString.append(logicalName) - .append(DOT) - .append(entity.getIdentity().getName()); - } - else if (projection instanceof Query.PropertyProjection) { - Query.PropertyProjection pp = (Query.PropertyProjection) projection; - if (projection instanceof Query.AvgProjection) { - queryString.append("AVG(") - .append(logicalName) - .append(DOT) - .append(pp.getPropertyName()) - .append(CLOSE_BRACKET); - } - else if (projection instanceof Query.SumProjection) { - queryString.append("SUM(") - .append(logicalName) - .append(DOT) - .append(pp.getPropertyName()) - .append(CLOSE_BRACKET); - } - else if (projection instanceof Query.MinProjection) { - queryString.append("MIN(") - .append(logicalName) - .append(DOT) - .append(pp.getPropertyName()) - .append(CLOSE_BRACKET); - } - else if (projection instanceof Query.MaxProjection) { - queryString.append("MAX(") - .append(logicalName) - .append(DOT) - .append(pp.getPropertyName()) - .append(CLOSE_BRACKET); - } - else if (projection instanceof Query.CountDistinctProjection) { - queryString.append("COUNT(DISTINCT ") - .append(logicalName) - .append(DOT) - .append(pp.getPropertyName()) - .append(CLOSE_BRACKET); - } - else { - queryString.append(logicalName) - .append(DOT) - .append(pp.getPropertyName()); - } - } - - if (i.hasNext()) { - queryString.append(COMMA); - } - } - } - - queryString.append(FROM_CLAUSE) - .append(entity.getName()) - .append(AS_CLAUSE ) - .append(logicalName); - } - - static public int appendCriteriaForOperator(StringBuilder q, - String logicalName, final String name, int position, String operator, boolean hibernateCompatible) { - q.append(logicalName) - .append(DOT) - .append(name) - .append(operator) - .append(QUESTIONMARK); - if (!hibernateCompatible) - q.append(++position); - return position; - } - - static { - - queryHandlers.put(AssociationQuery.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, - StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, - ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - - if (!allowJoins) { - throw new InvalidDataAccessResourceUsageException("Joins cannot be used in a DELETE or UPDATE operation"); - } - AssociationQuery aq = (AssociationQuery) criterion; - final Association association = aq.getAssociation(); - Query.Junction associationCriteria = aq.getCriteria(); - List associationCriteriaList = associationCriteria.getCriteria(); - - return handleAssociationCriteria(q, whereClause, logicalName, position, parameters, conversionService, allowJoins, association, associationCriteria, associationCriteriaList, hibernateCompatible); - } - }); - - queryHandlers.put(Query.Negation.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, - StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, - ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - - whereClause.append(NOT_CLAUSE) - .append(OPEN_BRACKET); - - final Query.Negation negation = (Query.Negation)criterion; - position = buildWhereClauseForCriterion(entity, negation, q, whereClause, logicalName, negation.getCriteria(), position, parameters, conversionService, allowJoins, hibernateCompatible); - whereClause.append(CLOSE_BRACKET); - - return position; - } - }); - - queryHandlers.put(Query.Conjunction.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, - StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, - ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - whereClause.append(OPEN_BRACKET); - - final Query.Conjunction conjunction = (Query.Conjunction)criterion; - position = buildWhereClauseForCriterion(entity, conjunction, q, whereClause, logicalName, conjunction.getCriteria(), position, parameters, conversionService, allowJoins, hibernateCompatible); - whereClause.append(CLOSE_BRACKET); - - return position; - } - }); - - queryHandlers.put(Query.Disjunction.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, - StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, - ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - whereClause.append(OPEN_BRACKET); - - final Query.Disjunction disjunction = (Query.Disjunction)criterion; - position = buildWhereClauseForCriterion(entity, disjunction, q,whereClause, logicalName, disjunction.getCriteria(), position, parameters, conversionService, allowJoins, hibernateCompatible); - whereClause.append(CLOSE_BRACKET); - - return position; - } - }); - - queryHandlers.put(Query.Equals.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.Equals eq = (Query.Equals) criterion; - final String name = eq.getProperty(); - PersistentProperty prop = validateProperty(entity, name, Query.Equals.class); - Class propType = prop.getType(); - position = appendCriteriaForOperator(whereClause, logicalName, name, position, "=", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); - return position; - } - }); - - queryHandlers.put(Query.EqualsProperty.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.EqualsProperty eq = (Query.EqualsProperty) criterion; - final String propertyName = eq.getProperty(); - String otherProperty = eq.getOtherProperty(); - - validateProperty(entity, propertyName, Query.EqualsProperty.class); - validateProperty(entity, otherProperty, Query.EqualsProperty.class); - appendPropertyComparison(whereClause, logicalName, propertyName, otherProperty, "="); - return position; - } - }); - - queryHandlers.put(Query.NotEqualsProperty.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.PropertyComparisonCriterion eq = (Query.PropertyComparisonCriterion) criterion; - final String propertyName = eq.getProperty(); - String otherProperty = eq.getOtherProperty(); - - validateProperty(entity, propertyName, Query.NotEqualsProperty.class); - validateProperty(entity, otherProperty, Query.NotEqualsProperty.class); - appendPropertyComparison(whereClause, logicalName, propertyName, otherProperty, "!="); - return position; - } - }); - - queryHandlers.put(Query.GreaterThanProperty.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.PropertyComparisonCriterion eq = (Query.PropertyComparisonCriterion) criterion; - final String propertyName = eq.getProperty(); - String otherProperty = eq.getOtherProperty(); - - validateProperty(entity, propertyName, Query.GreaterThanProperty.class); - validateProperty(entity, otherProperty, Query.GreaterThanProperty.class); - appendPropertyComparison(whereClause, logicalName, propertyName, otherProperty, ">"); - return position; - } - }); - - queryHandlers.put(Query.GreaterThanEqualsProperty.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.PropertyComparisonCriterion eq = (Query.PropertyComparisonCriterion) criterion; - final String propertyName = eq.getProperty(); - String otherProperty = eq.getOtherProperty(); - - validateProperty(entity, propertyName, Query.GreaterThanEqualsProperty.class); - validateProperty(entity, otherProperty, Query.GreaterThanEqualsProperty.class); - appendPropertyComparison(whereClause, logicalName, propertyName, otherProperty, ">="); - return position; - } - }); - - queryHandlers.put(Query.LessThanProperty.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.PropertyComparisonCriterion eq = (Query.PropertyComparisonCriterion) criterion; - final String propertyName = eq.getProperty(); - String otherProperty = eq.getOtherProperty(); - - validateProperty(entity, propertyName, Query.LessThanProperty.class); - validateProperty(entity, otherProperty, Query.LessThanProperty.class); - appendPropertyComparison(whereClause, logicalName, propertyName, otherProperty, "<"); - return position; - } - }); - - queryHandlers.put(Query.LessThanEqualsProperty.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.PropertyComparisonCriterion eq = (Query.PropertyComparisonCriterion) criterion; - final String propertyName = eq.getProperty(); - String otherProperty = eq.getOtherProperty(); - - validateProperty(entity, propertyName, Query.LessThanEqualsProperty.class); - validateProperty(entity, otherProperty, Query.LessThanEqualsProperty.class); - appendPropertyComparison(whereClause, logicalName, propertyName, otherProperty, "<="); - return position; - } - }); - - queryHandlers.put(Query.IsNull.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.IsNull isNull = (Query.IsNull) criterion; - final String name = isNull.getProperty(); - validateProperty(entity, name, Query.IsNull.class); - whereClause.append(logicalName) - .append(DOT) - .append(name) - .append(" IS NULL "); - - return position; - } - }); - - queryHandlers.put(Query.IsNotNull.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.IsNotNull isNotNull = (Query.IsNotNull) criterion; - final String name = isNotNull.getProperty(); - validateProperty(entity, name, Query.IsNotNull.class); - whereClause.append(logicalName) - .append(DOT) - .append(name) - .append(" IS NOT NULL "); - - return position; - } - }); - - queryHandlers.put(Query.IsEmpty.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.IsEmpty isEmpty = (Query.IsEmpty) criterion; - final String name = isEmpty.getProperty(); - validateProperty(entity, name, Query.IsEmpty.class); - whereClause.append(logicalName) - .append(DOT) - .append(name) - .append(" IS EMPTY "); - - return position; - } - }); - - queryHandlers.put(Query.IsNotEmpty.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.IsNotEmpty isNotEmpty = (Query.IsNotEmpty) criterion; - final String name = isNotEmpty.getProperty(); - validateProperty(entity, name, Query.IsNotEmpty.class); - whereClause.append(logicalName) - .append(DOT) - .append(name) - .append(" IS EMPTY "); - - return position; - } - }); - - queryHandlers.put(Query.IsNotNull.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.IsNotNull isNotNull = (Query.IsNotNull) criterion; - final String name = isNotNull.getProperty(); - validateProperty(entity, name, Query.IsNotNull.class); - whereClause.append(logicalName) - .append(DOT) - .append(name) - .append(" IS NOT NULL "); - - return position; - } - }); - - queryHandlers.put(Query.IdEquals.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.IdEquals eq = (Query.IdEquals) criterion; - PersistentProperty prop = entity.getIdentity(); - Class propType = prop.getType(); - position = appendCriteriaForOperator(whereClause, logicalName, prop.getName(), position, "=", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); - return position; - } - }); - - queryHandlers.put(Query.NotEquals.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.NotEquals eq = (Query.NotEquals) criterion; - final String name = eq.getProperty(); - PersistentProperty prop = validateProperty(entity, name, Query.NotEquals.class); - Class propType = prop.getType(); - position = appendCriteriaForOperator(whereClause, logicalName, name, position, " != ", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); - return position; - } - }); - - queryHandlers.put(Query.GreaterThan.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.GreaterThan eq = (Query.GreaterThan) criterion; - final String name = eq.getProperty(); - PersistentProperty prop = validateProperty(entity, name, Query.GreaterThan.class); - Class propType = prop.getType(); - position = appendCriteriaForOperator(whereClause, logicalName, name, position, " > ", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); - return position; - } - }); - - queryHandlers.put(Query.LessThanEquals.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.LessThanEquals eq = (Query.LessThanEquals) criterion; - final String name = eq.getProperty(); - PersistentProperty prop = validateProperty(entity, name, Query.LessThanEquals.class); - Class propType = prop.getType(); - position = appendCriteriaForOperator(whereClause, logicalName, name, position, " <= ", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); - return position; - } - }); - - queryHandlers.put(Query.GreaterThanEquals.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.GreaterThanEquals eq = (Query.GreaterThanEquals) criterion; - final String name = eq.getProperty(); - PersistentProperty prop = validateProperty(entity, name, Query.GreaterThanEquals.class); - Class propType = prop.getType(); - position = appendCriteriaForOperator(whereClause, logicalName, name, position, " >= ", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); - return position; - } - }); - - queryHandlers.put(Query.Between.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.Between between = (Query.Between) criterion; - final Object from = between.getFrom(); - final Object to = between.getTo(); - - final String name = between.getProperty(); - PersistentProperty prop = validateProperty(entity, name, Query.Between.class); - Class propType = prop.getType(); - final String qualifiedName = logicalName + DOT + name; - whereClause.append(OPEN_BRACKET) - .append(qualifiedName) - .append(" >= ") - .append(QUESTIONMARK); - if (!hibernateCompatible) - whereClause.append(++position); - whereClause.append(" AND ") - .append(qualifiedName) - .append(" <= ") - .append(QUESTIONMARK); - if (!hibernateCompatible) - whereClause.append(++position); - whereClause.append(CLOSE_BRACKET); - - parameters.add(conversionService.convert( from, propType )); - parameters.add(conversionService.convert( to, propType )); - return position; - } - }); - - queryHandlers.put(Query.LessThan.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.LessThan eq = (Query.LessThan) criterion; - final String name = eq.getProperty(); - PersistentProperty prop = validateProperty(entity, name, Query.LessThan.class); - Class propType = prop.getType(); - position = appendCriteriaForOperator(whereClause, logicalName, name, position, " < ", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); - return position; - } - }); - - queryHandlers.put(Query.Like.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.Like eq = (Query.Like) criterion; - final String name = eq.getProperty(); - PersistentProperty prop = validateProperty(entity, name, Query.Like.class); - Class propType = prop.getType(); - position = appendCriteriaForOperator(whereClause, logicalName, name, position, " like ", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); - return position; - } - }); - - queryHandlers.put(Query.ILike.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.ILike eq = (Query.ILike) criterion; - final String name = eq.getProperty(); - PersistentProperty prop = validateProperty(entity, name, Query.ILike.class); - Class propType = prop.getType(); - whereClause.append("lower(") - .append(logicalName) - .append(DOT) - .append(name) - .append(")") - .append(" like lower(") - .append(QUESTIONMARK); - if (!hibernateCompatible) - whereClause.append(++position); - whereClause.append(")"); - parameters.add(conversionService.convert( eq.getValue(), propType )); - return position; - } - }); - - queryHandlers.put(Query.In.class, new QueryHandler() { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - Query.In eq = (Query.In) criterion; - final String name = eq.getProperty(); - PersistentProperty prop = validateProperty(entity, name, Query.In.class); - Class propType = prop.getType(); - whereClause.append(logicalName) - .append(DOT) - .append(name) - .append(" IN ("); - for (Iterator i = eq.getValues().iterator(); i.hasNext();) { - Object val = i.next(); - whereClause.append(QUESTIONMARK); - if (!hibernateCompatible) - whereClause.append(++position); - if (i.hasNext()) { - whereClause.append(COMMA); - } - parameters.add(conversionService.convert(val, propType)); - } - whereClause.append(CLOSE_BRACKET); - - return position; - } - }); - } - - private static int handleAssociationCriteria(StringBuilder query, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, Association association, Query.Junction associationCriteria, List associationCriteriaList, boolean hibernateCompatible) { - if (association instanceof ToOne) { - final String associationName = association.getName(); - logicalName = logicalName + DOT + associationName; - return buildWhereClauseForCriterion(association.getAssociatedEntity(), associationCriteria, query, whereClause, logicalName, associationCriteriaList, position, parameters, conversionService, allowJoins, hibernateCompatible); - } - - if (association != null) { - final String associationName = association.getName(); - // TODO: Allow customization of join strategy! - String joinType = " INNER JOIN "; - query.append(joinType) - .append(logicalName) - .append(DOT) - .append(associationName) - .append(SPACE) - .append(associationName); - - return buildWhereClauseForCriterion(association.getAssociatedEntity(), associationCriteria, query, whereClause, associationName, associationCriteriaList, position, parameters, conversionService, allowJoins, hibernateCompatible); - } - - return position; - } - - private void buildUpdateStatement(StringBuilder queryString, Map propertiesToUpdate, List parameters, boolean hibernateCompatible) { - queryString.append(SPACE).append("SET"); - - // keys need to be sorted before query is built - Set keys = new TreeSet(propertiesToUpdate.keySet()); - - Iterator iterator = keys.iterator(); - while (iterator.hasNext()) { - String propertyName = iterator.next(); - PersistentProperty prop = entity.getPropertyByName(propertyName); - if (prop == null) throw new InvalidDataAccessResourceUsageException("Property '"+propertyName+"' of class '"+entity.getName()+"' specified in update does not exist"); - - parameters.add(propertiesToUpdate.get(propertyName)); - queryString.append(SPACE).append(logicalName).append(DOT).append(propertyName).append('=').append(QUESTIONMARK); - if (!hibernateCompatible) - queryString.append(parameters.size()); - if (iterator.hasNext()) { - queryString.append(COMMA); - } - } - } - - private static void appendPropertyComparison(StringBuilder q, String logicalName, String propertyName, String otherProperty, String operator) { - q.append(logicalName) - .append(DOT) - .append(propertyName) - .append(operator) - .append(logicalName) - .append(DOT) - .append(otherProperty); - } - - private static PersistentProperty validateProperty(PersistentEntity entity, String name, Class criterionType) { - if (entity.getIdentity().getName().equals(name)) return entity.getIdentity(); - PersistentProperty prop = entity.getPropertyByName(name); - if (prop == null) { - throw new InvalidDataAccessResourceUsageException("Cannot use [" + - criterionType.getSimpleName() + "] criterion on non-existent property: " + name); - } - return prop; - } - - private static interface QueryHandler { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible); - } - - private List buildWhereClause(PersistentEntity entity, Query.Junction criteria, StringBuilder q, StringBuilder whereClause, String logicalName, boolean allowJoins) { - List parameters = new ArrayList(); - return buildWhereClause(entity, criteria, q, whereClause, logicalName, allowJoins, parameters); - } - - private List buildWhereClause(PersistentEntity entity, Query.Junction criteria, StringBuilder q, StringBuilder whereClause, String logicalName, boolean allowJoins, List parameters) { - int position = parameters.size(); - final List criterionList = criteria.getCriteria(); - whereClause.append(WHERE_CLAUSE); - if (criteria instanceof Query.Negation) { - whereClause.append(NOT_CLAUSE); - } - whereClause.append(OPEN_BRACKET); - position = buildWhereClauseForCriterion(entity, criteria, q, whereClause, logicalName, - criterionList, position, parameters, - conversionService, allowJoins, this.hibernateCompatible); - q.append(whereClause.toString()); - q.append(CLOSE_BRACKET); - return parameters; - } - - protected void appendOrder(StringBuilder queryString, String logicalName) { - if (!orders.isEmpty()) { - queryString.append( ORDER_BY_CLAUSE); - for (Query.Order order : orders) { - queryString.append(logicalName) - .append(DOT) - .append(order.getProperty()) - .append(SPACE) - .append(order.getDirection().toString()) - .append(SPACE); - } - } - } - - static int buildWhereClauseForCriterion(PersistentEntity entity, - Query.Junction criteria, StringBuilder q, StringBuilder whereClause, String logicalName, - final List criterionList, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - for (Iterator iterator = criterionList.iterator(); iterator.hasNext();) { - Query.Criterion criterion = iterator.next(); - - final String operator = criteria instanceof Query.Conjunction ? LOGICAL_AND : LOGICAL_OR; - QueryHandler qh = queryHandlers.get(criterion.getClass()); - if (qh != null) { - - position = qh.handle(entity, criterion, q, whereClause, logicalName, - position, parameters, conversionService, allowJoins, hibernateCompatible); - } - else if (criterion instanceof AssociationCriteria) { - - if (!allowJoins) { - throw new InvalidDataAccessResourceUsageException("Joins cannot be used in a DELETE or UPDATE operation"); - } - AssociationCriteria ac = (AssociationCriteria) criterion; - Association association = ac.getAssociation(); - List associationCriteriaList = ac.getCriteria(); - handleAssociationCriteria(q, whereClause, logicalName, position, parameters, conversionService, allowJoins, association, new Query.Conjunction(), associationCriteriaList, hibernateCompatible); - } - else { - throw new InvalidDataAccessResourceUsageException("Queries of type "+criterion.getClass().getSimpleName()+" are not supported by this implementation"); - } - - if (iterator.hasNext()) { - whereClause.append(operator); - } - } - - return position; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryInfo.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryInfo.java deleted file mode 100644 index 485de8042..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryInfo.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.grails.datastore.mapping.query.jpa; - -import java.util.List; - -@SuppressWarnings("rawtypes") -public class JpaQueryInfo { - - String query; - List parameters; - - public JpaQueryInfo(String query, List parameters) { - this.query = query; - this.parameters = parameters; - } - - public String getQuery() { - return query; - } - - public List getParameters() { - return parameters; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/order/ManualEntityOrdering.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/order/ManualEntityOrdering.java deleted file mode 100644 index 365e4a6e5..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/order/ManualEntityOrdering.java +++ /dev/null @@ -1,141 +0,0 @@ -/* Copyright (C) 2010 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.mapping.query.order; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.query.Query; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.PropertyAccessorFactory; -import org.springframework.util.ReflectionUtils; - -/** - * Manual implementation of query ordering for datastores that don't support native ordering. Not all - * NoSQL datastores support the SQL equivalent of ORDER BY, hence manual in-memory ordering is the - * only way to simulate such queries. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class ManualEntityOrdering { - - PersistentEntity entity; - private static Map cachedReadMethods = new ConcurrentHashMap(); - - public ManualEntityOrdering(PersistentEntity entity) { - this.entity = entity; - } - - public PersistentEntity getEntity() { - return entity; - } - - public List applyOrder(List results, List orderDefinition) { - if (results == null) return null; - if (orderDefinition == null) return results; - for (Query.Order order : orderDefinition) { - results = applyOrder(results, order); - } - return results; - } - - /** - * Reverses the list. The result is a new List with the identical contents - * in reverse order. - * - * @param list a List - * @return a reversed List - */ - private static List reverse(List list) { - int size = list.size(); - List answer = new ArrayList(size); - ListIterator iter = list.listIterator(size); - while (iter.hasPrevious()) { - answer.add(iter.previous()); - } - return answer; - } - - public List applyOrder(List results, Query.Order order) { - final String name = order.getProperty(); - - final PersistentEntity entity = getEntity(); - PersistentProperty property = entity.getPropertyByName(name); - if (property == null) { - final PersistentProperty identity = entity.getIdentity(); - if (name.equals(identity.getName())) { - property = identity; - } - } - - if (property != null) { - final PersistentProperty finalProperty = property; - Collections.sort(results, new Comparator() { - - public int compare(Object o1, Object o2) { - - if (entity.isInstance(o1) && entity.isInstance(o2)) { - final String propertyName = finalProperty.getName(); - Method readMethod = cachedReadMethods.get(propertyName); - if (readMethod == null) { - BeanWrapper b = PropertyAccessorFactory.forBeanPropertyAccess(o1); - final PropertyDescriptor pd = b.getPropertyDescriptor(propertyName); - if (pd != null) { - readMethod = pd.getReadMethod(); - if (readMethod != null) { - ReflectionUtils.makeAccessible(readMethod); - cachedReadMethods.put(propertyName, readMethod); - } - } - } - - if (readMethod != null) { - final Class declaringClass = readMethod.getDeclaringClass(); - if (declaringClass.isInstance(o1) && declaringClass.isInstance(o2)) { - Object left = ReflectionUtils.invokeMethod(readMethod, o1); - Object right = ReflectionUtils.invokeMethod(readMethod, o2); - - if (left == null && right == null) return 0; - if (left != null && right == null) return 1; - if (left == null) return -1; - if ((left instanceof Comparable) && (right instanceof Comparable)) { - return ((Comparable)left).compareTo(right); - } - } - } - } - return 0; - } - }); - } - - if (order.getDirection() == Query.Order.Direction.DESC) { - results = reverse(results); - } - - return results; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/projections/ManualProjections.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/projections/ManualProjections.java deleted file mode 100644 index 1f65f86f4..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/projections/ManualProjections.java +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (C) 2010 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.mapping.query.projections; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.codehaus.groovy.runtime.DefaultGroovyMethods; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.order.ManualEntityOrdering; - -/** - * Implements common projections in-memory given a set of results. Not all - * NoSQL datastores support projections like SQL min(..), max(..) etc. - * This class provides support for those that don't. - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class ManualProjections { - - PersistentEntity entity; - private ManualEntityOrdering order; - - public ManualProjections(PersistentEntity entity) { - this.entity = entity; - this.order = new ManualEntityOrdering(entity); - } - - /** - * Calculates the minimum value of a property - * - * @param results The results - * @param property The property to calculate - * @return The minimum value or null if there are no results - */ - public Object min(Collection results, String property) { - if (results == null || results.isEmpty()) { - return null; - } - - final List sorted = order.applyOrder(new ArrayList(results), Query.Order.asc(property)); - final Object o = sorted.get(0); - if (entity.isInstance(o)) { - return new EntityAccess(entity, o).getProperty(property); - } - return o; - } - - /** - * Counts the number of distinct values - * - * @param results The results - * @param property The property - * @return A count of the distinct values - */ - public int countDistinct(Collection results, String property) { - Collection propertyValues = distinct(results, property); - return propertyValues.size(); - } - - public Collection distinct(Collection results, String property) { - List propertyValues = property(results, property); - - return DefaultGroovyMethods.unique(propertyValues); - } - - /** - * Calculates the maximum value of a property - * - * @param results The results - * @param property The property to calculate - * @return The maximum value or null if there are no results - */ - public Object max(Collection results, String property) { - if (results == null || results.isEmpty()) { - return null; - } - - final List sorted = order.applyOrder(new ArrayList(results), Query.Order.asc(property)); - final Object o = sorted.get(results.size()-1); - if (entity.isInstance(o)) { - return new EntityAccess(entity, o).getProperty(property); - } - return o; - } - - /** - * Obtains a properties value from the results - * - * @param results The results - * @param property The property - * @return A list of results - */ - public List property(Collection results, String property) { - List projectedResults = new ArrayList(); - if (results == null || results.isEmpty()) { - return projectedResults; - } - - for (Object o : results) { - EntityAccess ea = new EntityAccess(entity, o); - if (entity.isInstance(o)) { - projectedResults.add(ea.getProperty(property)); - } - else { - projectedResults.add(null); - } - } - - return projectedResults; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/rdbms/RelationalDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/rdbms/RelationalDatastore.java deleted file mode 100644 index c75546e50..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/rdbms/RelationalDatastore.java +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (C) 2010 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.mapping.rdbms; - -import org.grails.datastore.mapping.core.Datastore; - -/** - * @author Guillaume Laforge - */ -public interface RelationalDatastore extends Datastore {} \ No newline at end of file diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClassPropertyFetcher.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClassPropertyFetcher.java deleted file mode 100644 index 20e8ad335..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClassPropertyFetcher.java +++ /dev/null @@ -1,432 +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.grails.datastore.mapping.reflect; - -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.*; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Reads the properties of a class in an optimized manner avoiding exceptions. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class ClassPropertyFetcher { - private static final Logger LOG = LoggerFactory.getLogger(ClassPropertyFetcher.class); - - private final Class clazz; - // static fetchers for this class, but also for all super classes with the property. - // first item in each list is most derived version of static property. - final Map> staticFetchers = new HashMap>(); - final Map instanceFetchers = new HashMap(); - private final ReferenceInstanceCallback callback; - private PropertyDescriptor[] propertyDescriptors; - private Map propertyDescriptorsByName = new HashMap(); - private Map fieldsByName = new HashMap(); - private Map> typeToPropertyMap = new HashMap>(); - - private static Map cachedClassPropertyFetchers = new WeakHashMap(); - - public static ClassPropertyFetcher forClass(final Class c) { - ClassPropertyFetcher cpf = cachedClassPropertyFetchers.get(c); - if (cpf == null) { - cpf = new ClassPropertyFetcher(c); - cachedClassPropertyFetchers.put(c, cpf); - } - return cpf; - } - - public static void clearCache() { - cachedClassPropertyFetchers.clear(); - } - - ClassPropertyFetcher(final Class clazz) { - this.clazz = clazz; - this.callback = new ReferenceInstanceCallback() { - public Object getReferenceInstance() { - return ReflectionUtils.instantiate(clazz); - } - }; - init(); - } - - /** - * @return The Java that this ClassPropertyFetcher was constructor for - */ - public Class getJavaClass() { - return clazz; - } - - public Object getReference() { - return callback == null ? null : callback.getReferenceInstance(); - } - - public PropertyDescriptor[] getPropertyDescriptors() { - return propertyDescriptors; - } - - public boolean isReadableProperty(String name) { - return staticFetchers.containsKey(name) || - instanceFetchers.containsKey(name); - } - - private void init() { - - List allClasses = resolveAllClasses(clazz); - for (Class c : allClasses) { - Field[] fields = c.getDeclaredFields(); - for (Field field : fields) { - processField(field); - } - Method[] methods = c.getDeclaredMethods(); - for (Method method : methods) { - processMethod(method); - } - } - - try { - propertyDescriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors(); - } catch (IntrospectionException e) { - // ignore - } - - if (propertyDescriptors == null) { - return; - } - - for (PropertyDescriptor desc : propertyDescriptors) { - propertyDescriptorsByName.put(desc.getName(),desc); - final Class propertyType = desc.getPropertyType(); - if (propertyType == null) continue; - List pds = typeToPropertyMap.get(propertyType); - if (pds == null) { - pds = new ArrayList(); - typeToPropertyMap.put(propertyType, pds); - } - pds.add(desc); - - Method readMethod = desc.getReadMethod(); - if (readMethod != null) { - boolean staticReadMethod = Modifier.isStatic(readMethod.getModifiers()); - if (staticReadMethod) { - List propertyFetchers = staticFetchers.get(desc.getName()); - if (propertyFetchers == null) { - staticFetchers.put(desc.getName(), propertyFetchers = new ArrayList()); - } - propertyFetchers.add( - new GetterPropertyFetcher(readMethod, true)); - } else { - instanceFetchers.put(desc.getName(), - new GetterPropertyFetcher(readMethod, false)); - } - } - } - } - - private void processMethod(Method method) { - if (method.isSynthetic()) { - return; - } - if (!Modifier.isPublic(method.getModifiers())) { - return; - } - if (Modifier.isStatic(method.getModifiers()) && - method.getReturnType() != Void.class) { - if (method.getParameterTypes().length == 0) { - String name = method.getName(); - if (name.indexOf('$') == -1) { - if (name.length() > 3 && name.startsWith("get") && - Character.isUpperCase(name.charAt(3))) { - name = name.substring(3); - } else if (name.length() > 2 && - name.startsWith("is") && - Character.isUpperCase(name.charAt(2)) && - (method.getReturnType() == Boolean.class || - method.getReturnType() == boolean.class)) { - name = name.substring(2); - } - PropertyFetcher fetcher = new GetterPropertyFetcher(method, true); - List propertyFetchers = staticFetchers.get(name); - if (propertyFetchers == null) { - staticFetchers.put(name, propertyFetchers = new ArrayList()); - } - propertyFetchers.add(fetcher); - String decapitalized = Introspector.decapitalize(name); - if (!decapitalized.equals(name)) { - propertyFetchers = staticFetchers.get(decapitalized); - if (propertyFetchers == null) { - staticFetchers.put(decapitalized, propertyFetchers = new ArrayList()); - } - propertyFetchers.add(fetcher); - } - } - } - } - } - - private void processField(Field field) { - if (field.isSynthetic()) { - return; - } - final int modifiers = field.getModifiers(); - final String name = field.getName(); - if (!Modifier.isPublic(modifiers)) { - if (name.indexOf('$') == -1) { - fieldsByName.put(name, field); - } - } - else { - if (name.indexOf('$') == -1) { - boolean staticField = Modifier.isStatic(modifiers); - if (staticField) { - List propertyFetchers = staticFetchers.get(name); - if (propertyFetchers == null) { - staticFetchers.put(name, propertyFetchers = new ArrayList()); - } - propertyFetchers.add(new FieldReaderFetcher(field, staticField)); - } else { - instanceFetchers.put(name, new FieldReaderFetcher(field, staticField)); - } - } - } - } - - private List resolveAllClasses(Class c) { - List list = new ArrayList(); - Class currentClass = c; - while (currentClass != null) { - list.add(currentClass); - currentClass = currentClass.getSuperclass(); - } - Collections.reverse(list); - return list; - } - - public Object getPropertyValue(String name) { - return getPropertyValue(name, false); - } - - public Object getPropertyValue(String name, boolean onlyInstanceProperties) { - PropertyFetcher fetcher = resolveFetcher(name, onlyInstanceProperties); - return getPropertyValueWithFetcher(name, fetcher); - } - - public Object getPropertyValue(final Object instance, String name) { - PropertyFetcher fetcher = resolveFetcher(name, true); - return getPropertyValueWithFetcher(name, fetcher,new ReferenceInstanceCallback() { - @Override - public Object getReferenceInstance() { - return instance; - } - }); - } - - private Object getPropertyValueWithFetcher(String name, PropertyFetcher fetcher) { - ReferenceInstanceCallback thisCallback = callback; - return getPropertyValueWithFetcher(name, fetcher, thisCallback); - } - - private Object getPropertyValueWithFetcher(String name, PropertyFetcher fetcher, ReferenceInstanceCallback thisCallback) { - if (fetcher != null) { - try { - return fetcher.get(thisCallback); - } catch (Exception e) { - LOG.warn("Error fetching property's " - + name + " value from class " + clazz.getName(), e); - } - } - return null; - } - - public T getStaticPropertyValue(String name, Class c) { - List propertyFetchers = staticFetchers.get(name); - if (propertyFetchers == null) { - return null; - } - PropertyFetcher fetcher = propertyFetchers.get(0); - - Object v = getPropertyValueWithFetcher(name, fetcher); - return returnOnlyIfInstanceOf(v, c); - } - - /** - * Get the list of property values for this static property from the whole inheritance hierarchy, starting - * from the most derived version of the property ending with the base class. There are entries for each extant - * version of the property in turn, so if you have a 10-deep inheritance hierarchy, you may get 0+ values returned, - * one per class in the hierarchy that has the property declared (and of the correct type). - * @param name Name of the property. - * @param c Required type of the property (including derived types) - * @param Required type of the property. - * @return The list, with 0+ values (never null). Do not modify the returned list. - */ - public List getStaticPropertyValuesFromInheritanceHierarchy(String name, Class c) { - List propertyFetchers = staticFetchers.get(name); - if (propertyFetchers == null) { - return Collections.emptyList(); - } - List values = new ArrayList(propertyFetchers.size()); - for (PropertyFetcher fetcher : propertyFetchers) { - Object v = getPropertyValueWithFetcher(name, fetcher); - T t = returnOnlyIfInstanceOf(v, c); - if (t != null) { - values.add(t); - } - } - return values; - } - - public T getPropertyValue(String name, Class c) { - return returnOnlyIfInstanceOf(getPropertyValue(name, false), c); - } - - @SuppressWarnings("unchecked") - private T returnOnlyIfInstanceOf(Object value, Class type) { - if (value != null && (type == Object.class || ReflectionUtils.isAssignableFrom(type, value.getClass()))) { - return (T)value; - } - return null; - } - - private PropertyFetcher resolveFetcher(String name, boolean onlyInstanceProperties) { - PropertyFetcher fetcher = null; - if (!onlyInstanceProperties) { - List f = staticFetchers.get(name); - fetcher = f == null ? null : f.get(0); - } - if (fetcher == null) { - fetcher = instanceFetchers.get(name); - } - return fetcher; - } - - public Class getPropertyType(String name) { - return getPropertyType(name, false); - } - - public Class getPropertyType(String name, boolean onlyInstanceProperties) { - PropertyFetcher fetcher = resolveFetcher(name, onlyInstanceProperties); - return fetcher == null ? null : fetcher.getPropertyType(name); - } - - public PropertyDescriptor getPropertyDescriptor(String name) { - return propertyDescriptorsByName.get(name); - } - - public List getPropertiesOfType(Class javaClass) { - final List propertyDescriptorList = typeToPropertyMap.get(javaClass); - if (propertyDescriptorList == null) return Collections.emptyList(); - return propertyDescriptorList; - } - - @SuppressWarnings("unchecked") - public List getPropertiesAssignableToType(Class assignableType) { - List properties = new ArrayList(); - for (Class type : typeToPropertyMap.keySet()) { - if (assignableType.isAssignableFrom(type)) { - properties.addAll(typeToPropertyMap.get(type)); - } - } - return properties; - } - - @SuppressWarnings("unchecked") - public List getPropertiesAssignableFromType(Class assignableType) { - List properties = new ArrayList(); - for (Class type : typeToPropertyMap.keySet()) { - if (type.isAssignableFrom( assignableType )) { - properties.addAll(typeToPropertyMap.get(type)); - } - } - return properties; - } - - public static interface ReferenceInstanceCallback { - Object getReferenceInstance(); - } - - static interface PropertyFetcher { - Object get(ReferenceInstanceCallback callback) - throws IllegalArgumentException, IllegalAccessException, - InvocationTargetException; - - Class getPropertyType(String name); - } - - static class GetterPropertyFetcher implements PropertyFetcher { - private final Method readMethod; - private final boolean staticMethod; - - GetterPropertyFetcher(Method readMethod, boolean staticMethod) { - this.readMethod = readMethod; - this.staticMethod = staticMethod; - ReflectionUtils.makeAccessible(readMethod); - } - - public Object get(ReferenceInstanceCallback callback) - throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - if (staticMethod) { - return readMethod.invoke(null, (Object[]) null); - } - if (callback != null) { - return readMethod.invoke(callback.getReferenceInstance(), (Object[]) null); - } - return null; - } - - public Class getPropertyType(String name) { - return readMethod.getReturnType(); - } - } - - static class FieldReaderFetcher implements PropertyFetcher { - private final Field field; - private final boolean staticField; - - public FieldReaderFetcher(Field field, boolean staticField) { - this.field = field; - this.staticField = staticField; - ReflectionUtils.makeAccessible(field); - } - - public Object get(ReferenceInstanceCallback callback) - throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - if (staticField) { - return field.get(null); - } - if (callback != null) { - return field.get(callback.getReferenceInstance()); - } - return null; - } - - public Class getPropertyType(String name) { - return field.getType(); - } - } - - public Field getDeclaredField(String name) { - return fieldsByName.get(name); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/InstantiationException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/InstantiationException.java deleted file mode 100644 index b008af363..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/InstantiationException.java +++ /dev/null @@ -1,30 +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.grails.datastore.mapping.reflect; - -/** - * Runtime exception equivalent of java.lang.InstantiationException - * - * @author Graeme Rocher - * @since 1.0 - */ -public class InstantiationException extends RuntimeException { - - private static final long serialVersionUID = 1; - - public InstantiationException(String s, Throwable throwable) { - super(s, throwable); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/NameUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/NameUtils.java deleted file mode 100644 index 1151b2894..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/NameUtils.java +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright (C) 2010 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.mapping.reflect; - -import java.beans.Introspector; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public class NameUtils { - - private static final String PROPERTY_SET_PREFIX = "set"; - private static final String PROPERTY_GET_PREFIX = "get"; - - /** - * Retrieves the name of a setter for the specified property name - * @param propertyName The property name - * @return The setter equivalent - */ - public static String getSetterName(String propertyName) { - return PROPERTY_SET_PREFIX + propertyName.substring(0,1).toUpperCase()+ propertyName.substring(1); - } - - /** - * Retrieves the name of a setter for the specified property name - * @param propertyName The property name - * @return The setter equivalent - */ - public static String getGetterName(String propertyName) { - return PROPERTY_GET_PREFIX + propertyName.substring(0,1).toUpperCase()+ propertyName.substring(1); - } - - /** - * Returns the property name for a getter or setter - * @param getterOrSetterName The getter or setter name - * @return The property name - */ - public static String getPropertyNameForGetterOrSetter(String getterOrSetterName) { - String propertyName = getterOrSetterName.substring(3); - if(propertyName.length() == 1) return propertyName.toLowerCase(); - else { - if(Character.isUpperCase(propertyName.charAt(0)) && Character.isUpperCase(propertyName.charAt(1))) { - return propertyName; - } - else { - return propertyName.substring(0,1).toLowerCase() + propertyName.substring(1); - } - } - } - /** - * Converts class name to property name using JavaBean decaplization - * - * @param name The class name - * @return The decapitalized name - */ - public static String decapitalize(String name) { - return Introspector.decapitalize(name); - } - - /** - * Converts a property name to class name according to the JavaBean convention - * - * @param name The property name - * @return The class name - */ - public static String capitalize(String name) { - return name.substring(0,1).toUpperCase() + name.substring(1); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ReflectionUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ReflectionUtils.java deleted file mode 100644 index 8d15ffee4..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ReflectionUtils.java +++ /dev/null @@ -1,196 +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.grails.datastore.mapping.reflect; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.springframework.beans.BeanUtils; - -/** - * Provides methods to help with reflective operations - * - * @author Graeme Rocher - * @since 1.0 - */ -public class ReflectionUtils { - - public static final Map, Class> PRIMITIVE_TYPE_COMPATIBLE_CLASSES = new HashMap, Class>(); - @SuppressWarnings("rawtypes") - private static final Class[] EMPTY_CLASS_ARRAY = {}; - - /** - * Just add two entries to the class compatibility map - * @param left - * @param right - */ - private static void registerPrimitiveClassPair(Class left, Class right) { - PRIMITIVE_TYPE_COMPATIBLE_CLASSES.put(left, right); - PRIMITIVE_TYPE_COMPATIBLE_CLASSES.put(right, left); - } - - static { - registerPrimitiveClassPair(Boolean.class, boolean.class); - registerPrimitiveClassPair(Integer.class, int.class); - registerPrimitiveClassPair(Short.class, short.class); - registerPrimitiveClassPair(Byte.class, byte.class); - registerPrimitiveClassPair(Character.class, char.class); - registerPrimitiveClassPair(Long.class, long.class); - registerPrimitiveClassPair(Float.class, float.class); - registerPrimitiveClassPair(Double.class, double.class); - } - - /** - * Make the given field accessible, explicitly setting it accessible if necessary. - * The setAccessible(true) method is only called when actually necessary, - * to avoid unnecessary conflicts with a JVM SecurityManager (if active). - * - * Based on the same method in Spring core. - * - * @param field the field to make accessible - * @see java.lang.reflect.Field#setAccessible - */ - public static void makeAccessible(Field field) { - if (!Modifier.isPublic(field.getModifiers()) || - !Modifier.isPublic(field.getDeclaringClass().getModifiers())) { - field.setAccessible(true); - } - } - - /** - * Make the given method accessible, explicitly setting it accessible if necessary. - * The setAccessible(true) method is only called when actually necessary, - * to avoid unnecessary conflicts with a JVM SecurityManager (if active). - * - * Based on the same method in Spring core. - * - * @param method the method to make accessible - * @see java.lang.reflect.Method#setAccessible - */ - public static void makeAccessible(Method method) { - if (!Modifier.isPublic(method.getModifiers()) || - !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { - method.setAccessible(true); - } - } - - /** - *

    Tests whether or not the left hand type is compatible with the right hand type in Groovy - * terms, i.e. can the left type be assigned a value of the right hand type in Groovy.

    - *

    This handles Java primitive type equivalence and uses isAssignableFrom for all other types, - * with a bit of magic for native types and polymorphism i.e. Number assigned an int. - * If either parameter is null an exception is thrown

    - * - * @param leftType The type of the left hand part of a notional assignment - * @param rightType The type of the right hand part of a notional assignment - * @return True if values of the right hand type can be assigned in Groovy to variables of the left hand type. - */ - public static boolean isAssignableFrom(final Class leftType, final Class rightType) { - if (leftType == null) { - throw new NullPointerException("Left type is null!"); - } - if (rightType == null) { - throw new NullPointerException("Right type is null!"); - } - if (leftType == Object.class) { - return true; - } - if (leftType == rightType) { - return true; - } - // check for primitive type equivalence - Class r = PRIMITIVE_TYPE_COMPATIBLE_CLASSES.get(leftType); - boolean result = r == rightType; - - if (!result) { - // If no primitive <-> wrapper match, it may still be assignable - // from polymorphic primitives i.e. Number -> int (AKA Integer) - if (rightType.isPrimitive()) { - // see if incompatible - r = PRIMITIVE_TYPE_COMPATIBLE_CLASSES.get(rightType); - if (r != null) { - result = leftType.isAssignableFrom(r); - } - } - else { - // Otherwise it may just be assignable using normal Java polymorphism - result = leftType.isAssignableFrom(rightType); - } - } - return result; - } - - /** - * Instantiates an object catching any relevant exceptions and rethrowing as a runtime exception - * - * @param clazz The class - * @return The instantiated object or null if the class parameter was null - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - public static Object instantiate(Class clazz) { - if (clazz == null) return null; - try { - return clazz.getConstructor(EMPTY_CLASS_ARRAY).newInstance(); - } catch (IllegalAccessException e) { - throw new InstantiationException(e.getClass().getName() + " error creating instance of class ["+e.getMessage()+"]: " + e.getMessage(), e); - } catch (InvocationTargetException e) { - throw new InstantiationException(e.getClass().getName() + " error creating instance of class ["+e.getMessage()+"]: " + e.getMessage(), e); - } catch (NoSuchMethodException e) { - throw new InstantiationException(e.getClass().getName() + " error creating instance of class ["+e.getMessage()+"]: " + e.getMessage(), e); - } catch (java.lang.InstantiationException e) { - throw new InstantiationException(e.getClass().getName() + " error creating instance of class ["+e.getMessage()+"]: " + e.getMessage(), e); - } - } - - /** - * Retrieves all the properties of the given class for the given type - * - * @param clazz The class to retrieve the properties from - * @param propertyType The type of the properties you wish to retrieve - * - * @return An array of PropertyDescriptor instances - */ - public static PropertyDescriptor[] getPropertiesOfType(Class clazz, Class propertyType) { - if (clazz == null || propertyType == null) { - return new PropertyDescriptor[0]; - } - - Set properties = new HashSet(); - try { - for (PropertyDescriptor descriptor : BeanUtils.getPropertyDescriptors(clazz)) { - Class currentPropertyType = descriptor.getPropertyType(); - if (isTypeInstanceOfPropertyType(propertyType, currentPropertyType)) { - properties.add(descriptor); - } - } - } - catch (Exception e) { - // if there are any errors in instantiating just return null for the moment - return new PropertyDescriptor[0]; - } - return properties.toArray(new PropertyDescriptor[properties.size()]); - } - - private static boolean isTypeInstanceOfPropertyType(Class type, Class propertyType) { - return propertyType.isAssignableFrom(type) && !propertyType.equals(Object.class); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/DatastoreTransactionManager.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/DatastoreTransactionManager.java deleted file mode 100644 index 2e102e11f..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/DatastoreTransactionManager.java +++ /dev/null @@ -1,194 +0,0 @@ -/* Copyright (C) 2010 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.mapping.transactions; - -import javax.persistence.FlushModeType; - -import org.springframework.dao.DataAccessException; -import org.springframework.dao.DataAccessResourceFailureException; -import org.grails.datastore.mapping.core.ConnectionNotFoundException; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.core.DatastoreUtils; -import org.grails.datastore.mapping.core.Session; -import org.springframework.transaction.CannotCreateTransactionException; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionException; -import org.springframework.transaction.TransactionSystemException; -import org.springframework.transaction.support.AbstractPlatformTransactionManager; -import org.springframework.transaction.support.DefaultTransactionStatus; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.util.Assert; - -/** - * A {@link org.springframework.transaction.PlatformTransactionManager} instance that - * works with the Spring datastore abstraction - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("serial") -public class DatastoreTransactionManager extends AbstractPlatformTransactionManager { - - private Datastore datastore; - private boolean datastoreManagedSession; - - public void setDatastore(Datastore datastore) { - this.datastore = datastore; - } - - public Datastore getDatastore() { - Assert.notNull(datastore, "Cannot use DatastoreTransactionManager without a datastore set!"); - return datastore; - } - - public void setDatastoreManagedSession(boolean datastoreManagedSession) { - this.datastoreManagedSession = datastoreManagedSession; - } - - @Override - protected Object doGetTransaction() throws TransactionException { - TransactionObject txObject = new TransactionObject(); - - SessionHolder sessionHolder = - (SessionHolder) TransactionSynchronizationManager.getResource(getDatastore()); - if (sessionHolder != null) { - if (logger.isDebugEnabled()) { - logger.debug("Found thread-bound Session [" + - sessionHolder.getSession() + "] for Datastore transaction"); - } - txObject.setSessionHolder(sessionHolder); - } - else if (datastoreManagedSession) { - try { - Session session = getDatastore().getCurrentSession(); - if (logger.isDebugEnabled()) { - logger.debug("Found Datastore-managed Session [" + - session + "] for Spring-managed transaction"); - } - txObject.setExistingSession(session); - } - catch (ConnectionNotFoundException ex) { - throw new DataAccessResourceFailureException( - "Could not obtain Datastore-managed Session for Spring-managed transaction", ex); - } - } - else { - Session session = getDatastore().connect(); - txObject.setSession(session); - } - - return txObject; - } - - @Override - protected void doBegin(Object o, TransactionDefinition definition) throws TransactionException { - TransactionObject txObject = (TransactionObject) o; - - Session session = null; - try { - session = txObject.getSessionHolder().getSession(); - - if (definition.isReadOnly()) { - // Just set to NEVER in case of a new Session for this transaction. - session.setFlushMode(FlushModeType.COMMIT); - } - - Transaction tx = session.beginTransaction(); - // Register transaction timeout. - int timeout = determineTimeout(definition); - if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { - tx.setTimeout(timeout); - } - - // Add the Datastore transaction to the session holder. - txObject.setTransaction(tx); - - // Bind the session holder to the thread. - if (txObject.isNewSessionHolder()) { - TransactionSynchronizationManager.bindResource(getDatastore(), txObject.getSessionHolder()); - } - txObject.getSessionHolder().setSynchronizedWithTransaction(true); - } - catch (Exception ex) { - if (txObject.isNewSession()) { - try { - if (session != null && session.getTransaction().isActive()) { - session.getTransaction().rollback(); - } - } - catch (Throwable ex2) { - logger.debug("Could not rollback Session after failed transaction begin", ex); - } - finally { - DatastoreUtils.closeSession(session); - } - } - throw new CannotCreateTransactionException("Could not open Datastore Session for transaction", ex); - } - } - - @Override - protected void doCommit(DefaultTransactionStatus status) throws TransactionException { - TransactionObject txObject = (TransactionObject) status.getTransaction(); - final SessionHolder sessionHolder = txObject.getSessionHolder(); - if (status.isDebug()) { - logger.debug("Committing Datastore transaction on Session [" + sessionHolder.getSession() + "]"); - } - try { - if (sessionHolder.getSession() != null) { - sessionHolder.getSession().flush(); - } - txObject.getTransaction().commit(); - } - catch (DataAccessException ex) { - throw new TransactionSystemException("Could not commit Datastore transaction", ex); - } - } - - @Override - protected void doRollback(DefaultTransactionStatus status) throws TransactionException { - TransactionObject txObject = (TransactionObject) status.getTransaction(); - final SessionHolder sessionHolder = txObject.getSessionHolder(); - if (status.isDebug()) { - logger.debug("Rolling back Datastore transaction on Session [" + - sessionHolder.getSession() + "]"); - } - try { - txObject.getTransaction().rollback(); - } - catch (DataAccessException ex) { - throw new TransactionSystemException("Could not rollback Datastore transaction", ex); - } - finally { - // Clear all pending inserts/updates/deletes in the Session. - // Necessary for pre-bound Sessions, to avoid inconsistent state. - if (sessionHolder.getSession() != null) { - sessionHolder.getSession().clear(); - } - } - } - - @Override - protected void doCleanupAfterCompletion(Object transaction) { - TransactionObject txObject = (TransactionObject) transaction; - - // Un-bind the session holder from the thread. - if (txObject.isNewSessionHolder()) { - TransactionSynchronizationManager.unbindResource(getDatastore()); - } - txObject.getSessionHolder().setSynchronizedWithTransaction(false); - - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionHolder.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionHolder.java deleted file mode 100644 index ddbf132b2..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionHolder.java +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright (C) 2010 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.mapping.transactions; - -import java.util.Deque; -import java.util.concurrent.LinkedBlockingDeque; - -import org.grails.datastore.mapping.core.Session; -import org.springframework.transaction.support.ResourceHolderSupport; - -/** - * Holds a reference to one or more sessions. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class SessionHolder extends ResourceHolderSupport { - - private Deque sessions = new LinkedBlockingDeque(); - private Transaction transaction; - - public SessionHolder(Session session) { - sessions.add(session); - } - - public Transaction getTransaction() { - return transaction; - } - - public void setTransaction(Transaction transaction) { - this.transaction = transaction; - } - - public Session getSession() { - return sessions.peekLast(); - } - - public boolean isEmpty() { - return sessions.isEmpty(); - } - - public boolean doesNotHoldNonDefaultSession() { - return isEmpty(); - } - - public void addSession(Session session) { - sessions.add(session); - } - - public void removeSession(Session session) { - sessions.remove(session); - } - - public boolean containsSession(Session session) { - return sessions.contains(session); - } - - public int size() { - return sessions.size(); - } - - public Session getValidatedSession() { - Session session = getSession(); - if (session != null && !session.isConnected()) { - removeSession(session); - session = null; - } - return session; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionOnlyTransaction.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionOnlyTransaction.java deleted file mode 100644 index cc3b08594..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionOnlyTransaction.java +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (C) 2010 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.mapping.transactions; - -import org.grails.datastore.mapping.core.Session; - -/** - *

    An implementation that provides Session only transaction management. Essentially when {@link #rollback()} is called - * the {@link Session}'s clear() method is called and when {@link #commit()} is called the flush() method is called. - *

    - * - *

    - * No other resource level transaction management is provided. - *

    - * - * @author graemerocher - * - * @param - */ -public class SessionOnlyTransaction implements Transaction { - - private T nativeInterface; - private Session session; - private boolean active = true; - - public SessionOnlyTransaction(T nativeInterface, Session session) { - this.nativeInterface = nativeInterface; - this.session = session; - } - - public void commit() { - if (active) { - try { - session.flush(); - } - finally { - active = false; - } - } - } - - public void rollback() { - if (active) { - try { - session.clear(); - } - finally { - active = false; - } - } - } - - public T getNativeTransaction() { - return nativeInterface; - } - - public boolean isActive() { - return active; - } - - public void setTimeout(int timeout) { - // do nothing - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/Transaction.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/Transaction.java deleted file mode 100644 index f7b9021d4..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/Transaction.java +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (C) 2010 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.mapping.transactions; - -/** - * Class giving the ability to start, commit and rollback a transaction. - * - * @author Guillaume Laforge - * @author Graeme Rocher - * @since 1.0 - * - */ -public interface Transaction { - - /** - * Commit the transaction. - */ - void commit(); - - /** - * Rollback the transaction. - */ - void rollback(); - - /** - * @return the native transaction object. - */ - T getNativeTransaction(); - - /** - * Whether the transaction is active - * @return True if it is - */ - boolean isActive(); - - /** - * Sets the transaction timeout period - * @param timeout The timeout - */ - void setTimeout(int timeout); -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionObject.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionObject.java deleted file mode 100644 index 737e106fa..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionObject.java +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (C) 2010 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.mapping.transactions; - -import org.grails.datastore.mapping.core.Session; - -/** - * A transaction object returned when the transaction is created. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class TransactionObject { - private SessionHolder sessionHolder; - private boolean newSessionHolder; - private boolean newSession; - - public SessionHolder getSessionHolder() { - return sessionHolder; - } - - public Transaction getTransaction() { - return getSessionHolder().getTransaction(); - } - - public void setTransaction(Transaction transaction) { - getSessionHolder().setTransaction(transaction); - } - - public void setSession(Session session) { - this.sessionHolder = new SessionHolder(session); - this.newSessionHolder = true; - this.newSession = true; - } - - public void setExistingSession(Session session) { - this.sessionHolder = new SessionHolder(session); - this.newSessionHolder = true; - this.newSession = false; - } - - public void setSessionHolder(SessionHolder sessionHolder) { - this.sessionHolder = sessionHolder; - this.newSessionHolder = false; - this.newSession = false; - } - - public boolean isNewSessionHolder() { - return newSessionHolder; - } - - public boolean isNewSession() { - return newSession; - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionUtils.java deleted file mode 100644 index df89d75c1..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 2010 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.mapping.transactions; - -import org.grails.datastore.mapping.core.Datastore; -import org.springframework.transaction.NoTransactionException; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -/** - * Utility methods for Transactions. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class TransactionUtils { - - public static boolean isTransactionPresent(Datastore datastore) { - return getTransaction(datastore) != null; - } - - public static Transaction currentTransaction(Datastore datastore) { - final Transaction transaction = getTransaction(datastore); - if (transaction == null) { - throw new NoTransactionException("No transaction started."); - } - return transaction; - } - - public static Transaction getTransaction(Datastore datastore) { - final SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(datastore); - return sessionHolder == null ? null : sessionHolder.getTransaction(); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/support/SpringSessionSynchronization.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/support/SpringSessionSynchronization.java deleted file mode 100644 index 84e9fc2d7..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/support/SpringSessionSynchronization.java +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright (C) 2010 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.mapping.transactions.support; - -import org.springframework.dao.DataAccessException; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.core.DatastoreUtils; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.transactions.SessionHolder; -import org.springframework.transaction.support.TransactionSynchronization; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -/** - * An instance of {@link org.springframework.transaction.support.TransactionSynchronization} - * for the Datastore abstraction. Based on similar work for Hibernate - * - * @author Juergen Hoeller - * @author Graeme Rocher - */ -public class SpringSessionSynchronization implements TransactionSynchronization { - - private final SessionHolder sessionHolder; - private final Datastore datastore; - private final boolean newSession; - private boolean holderActive = true; - - public SpringSessionSynchronization(SessionHolder sessionHolder, - Datastore datastore, boolean newSession) { - this.sessionHolder = sessionHolder; - this.datastore = datastore; - this.newSession = newSession; - } - - /** - * Check whether there is a Hibernate Session for the current JTA - * transaction. Else, fall back to the default thread-bound Session. - */ - private Session getCurrentSession() { - return sessionHolder.getSession(); - } - - public void suspend() { - if (holderActive) { - TransactionSynchronizationManager.unbindResource(datastore); - getCurrentSession().disconnect(); - } - } - - public void resume() { - if (holderActive) { - TransactionSynchronizationManager.bindResource(datastore, sessionHolder); - } - } - - public void flush() { - // do nothing - } - - public void beforeCommit(boolean readOnly) throws DataAccessException { - // do nothing - } - - public void beforeCompletion() { - if (newSession) { - // Default behavior: unbind and close the thread-bound Hibernate Session. - TransactionSynchronizationManager.unbindResource(datastore); - holderActive = false; - } - } - - public void afterCommit() { - } - - public void afterCompletion(int status) { - // No Hibernate TransactionManagerLookup: apply afterTransactionCompletion callback. - // Always perform explicit afterTransactionCompletion callback for pre-bound Session, - // even with Hibernate TransactionManagerLookup (which only applies to new Sessions). - Session session = sessionHolder.getSession(); - // Close the Hibernate Session here if necessary - // (closed in beforeCompletion in case of TransactionManagerLookup). - if (newSession) { - DatastoreUtils.closeSessionOrRegisterDeferredClose(session, datastore); - } - else { - session.disconnect(); - } - if (sessionHolder.doesNotHoldNonDefaultSession()) { - sessionHolder.setSynchronizedWithTransaction(false); - } - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidatingEventListener.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidatingEventListener.java deleted file mode 100644 index 5d9d69646..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidatingEventListener.java +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright (C) 2010 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.mapping.validation; - -import javax.persistence.FlushModeType; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener; -import org.grails.datastore.mapping.engine.event.PersistenceEventListener; -import org.grails.datastore.mapping.engine.event.PreInsertEvent; -import org.grails.datastore.mapping.engine.event.PreUpdateEvent; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.springframework.context.ApplicationEvent; -import org.springframework.validation.Errors; -import org.springframework.validation.Validator; - -/** - * A {@link PersistenceEventListener} that uses - * Spring's validation mechanism to evict objects if an error occurs - * - * @author Graeme Rocher - * @since 1.0 - */ -public class ValidatingEventListener extends AbstractPersistenceEventListener { - - public ValidatingEventListener(Datastore datastore) { - super(datastore); - } - - @Override - protected void onPersistenceEvent(final AbstractPersistenceEvent event) { - if (event instanceof PreInsertEvent) { - beforeInsert(event.getEntity(), event.getEntityAccess()); - } - else if (event instanceof PreUpdateEvent) { - beforeUpdate(event.getEntity(), event.getEntityAccess()); - } - } - - public boolean supportsEventType(Class eventType) { - return PreInsertEvent.class.isAssignableFrom(eventType) || - PreUpdateEvent.class.isAssignableFrom(eventType); - } - - public boolean beforeInsert(PersistentEntity entity, EntityAccess e) { - return doValidate(entity, e.getEntity()); - } - - public boolean beforeUpdate(PersistentEntity entity, EntityAccess e) { - return doValidate(entity, e.getEntity()); - } - - private boolean doValidate(PersistentEntity entity, Object o) { - Validator v = datastore.getMappingContext().getEntityValidator(entity); - if (v == null) { - return true; - } - - if (datastore.skipValidation(o)) { - return true; - } - - Session currentSession = datastore.getCurrentSession(); - FlushModeType flushMode = currentSession.getFlushMode(); - try { - currentSession.setFlushMode(FlushModeType.COMMIT); - - Errors result = new ValidationErrors(o); - v.validate(o, result); - if (result.hasErrors()) { - onErrors(o, result); - return false; - } - - return true; - } finally { - currentSession.setFlushMode(flushMode); - } - } - - /** - * Sub classes should override to receive error notifications - * - * @param object The object being validated - * @param errors The errors instance - */ - protected void onErrors(Object object, Errors errors) { - datastore.setObjectErrors(object, errors); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationErrors.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationErrors.java deleted file mode 100644 index c77bd5e31..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationErrors.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 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.mapping.validation; - -import org.springframework.validation.BeanPropertyBindingResult; - -/** - * Models validation errors - * - * @author Graeme Rocher - * @since 2.0 - */ -public class ValidationErrors extends BeanPropertyBindingResult { - private static final long serialVersionUID = 1; - - /** - * Creates a new instance of the {@link org.springframework.validation.BeanPropertyBindingResult} class. - * - * @param target the target bean to bind onto - * @param objectName the name of the target object - */ - public ValidationErrors(Object target, String objectName) { - super(target, objectName); - } - /** - * Creates a new instance of the {@link org.springframework.validation.BeanPropertyBindingResult} class. - * - * @param target the target bean to bind onto - */ - public ValidationErrors(Object target) { - super(target, target.getClass().getName()); - } - - public Object getAt(String field) { - return getFieldError(field); - } - - public void putAt(String field, String errorCode) { - rejectValue(field, errorCode); - } -} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationException.java deleted file mode 100644 index 3ec791d65..000000000 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationException.java +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (C) 2010 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.mapping.validation; - -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.validation.Errors; -import org.springframework.validation.ObjectError; - -/** - * Exception thrown when a validation error occurs - */ -public class ValidationException extends DataIntegrityViolationException { - - private static final long serialVersionUID = 1; - - private String fullMessage; - - public ValidationException(String msg, Errors errors) { - super(msg); - fullMessage = formatErrors(errors, msg); - } - - @Override - public String getMessage() { - return fullMessage; - } - - public static String formatErrors(Errors errors, String msg ) { - String ls = System.getProperty("line.separator"); - StringBuilder b = new StringBuilder(); - if (msg != null) { - b.append(msg).append(" : ").append(ls); - } - - for (ObjectError error : errors.getAllErrors()) { - b.append(ls) - .append(" - ") - .append(error) - .append(ls); - } - return b.toString(); - } -} 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 725fbaf53..000000000 --- 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-core/src/test/groovy/org/grails/datastore/mapping/keyvalue/mapping/KeyValueMappingFactoryTests.groovy b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/keyvalue/mapping/KeyValueMappingFactoryTests.groovy deleted file mode 100644 index d99b9f7b5..000000000 --- a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/keyvalue/mapping/KeyValueMappingFactoryTests.groovy +++ /dev/null @@ -1,55 +0,0 @@ -package org.grails.datastore.mapping.keyvalue.mapping - -import org.grails.datastore.mapping.keyvalue.mapping.config.Family -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValue -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValuePersistentEntity -import org.junit.Before -import org.junit.Test - -/** - * @author Graeme Rocher - * @since 1.0 - */ -class KeyValueMappingFactoryTests { - def context - - @Before - void setUp() { - context = new KeyValueMappingContext("myspace") - context.addPersistentEntity(TestEntity) - context.addPersistentEntity(AbstractTestEntity) - } - - @Test - void testCreateMappedForm() { - KeyValuePersistentEntity entity = context.getPersistentEntity(TestEntity.name) - assert entity != null - - Family entityMapping = entity.mapping.mappedForm - assert "myspace" == entityMapping.keyspace - assert TestEntity.name == entityMapping.family - assert "id" == entity.mapping.identifier.identifierName[0] - - KeyValue kv = entity.identity.mapping.mappedForm - assert kv != null - assert kv.key == 'id' - } - - @Test - void testParentEntity() { - KeyValuePersistentEntity entity = context.getPersistentEntity(TestEntity.name) - assert entity != null - assert !entity.root - assert entity.parentEntity != null - assert entity.rootEntity != null - } - - abstract class AbstractTestEntity { - Long id - } - - class TestEntity extends AbstractTestEntity { - Long version - } -} diff --git a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/GormMappingInheritanceTests.groovy b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/GormMappingInheritanceTests.groovy deleted file mode 100644 index da60577c6..000000000 --- a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/GormMappingInheritanceTests.groovy +++ /dev/null @@ -1,167 +0,0 @@ -package org.grails.datastore.mapping.model - -import org.junit.Test -import org.grails.datastore.mapping.model.types.* - -import static org.junit.Assert.* - -/** - * Tests for correct mapping of entities with inheritance. - */ -class GormMappingInheritanceTests { - @Test - void testInheritedMappedBy() { - def context = new TestMappingContext() - context.addPersistentEntity(SpecialUser) - assert 2 == context.persistentEntities.size() - - def user = context.getPersistentEntity(SpecialUser.name) - - Association foesAssociation = user.getPropertyByName("foes") - assert (foesAssociation instanceof OneToMany) - assert !foesAssociation.isBidirectional() - - Association friendsAssociation = user.getPropertyByName("friends") - assert (friendsAssociation instanceof OneToMany) - assert !friendsAssociation.isBidirectional() - - Association bestBuddyAssociation = user.getPropertyByName("bestBuddy") - assert (bestBuddyAssociation instanceof OneToOne) - assert !bestBuddyAssociation.isBidirectional() - - Association specialFriendsAssociation = user.getPropertyByName("specialFriends") - assert (specialFriendsAssociation instanceof OneToMany) - assert !specialFriendsAssociation.isBidirectional() - - } - - @Test - void testInheritedTransients() { - def context = new TestMappingContext() - context.addPersistentEntity(DerivedEntity) - assertEquals 2, context.persistentEntities.size() - - def derived = context.getPersistentEntity(DerivedEntity.name) - assertNull derived.getPropertyByName('baz') - assertNull derived.getPropertyByName('bar') - } - - @Test - void testInheritedEmbeddeds() { - def context = new TestMappingContext() - context.addPersistentEntity(DerivedEmbeddedTest) - - def derived = context.getPersistentEntity(DerivedEmbeddedTest.name) - def property = derived.getPropertyByName('testEntity') - assertTrue property instanceof Embedded - property = derived.getPropertyByName('testEntity2') - assertTrue property instanceof Embedded - } - - @Test - void testInheritedAssociations() { - def context = new TestMappingContext() - context.addPersistentEntity(DerivedChild) - assertEquals 3, context.persistentEntities.size() - - def derivedChild = context.getPersistentEntity(DerivedChild.name) - Association parentAssociation = derivedChild.getPropertyByName("parent") - assertTrue parentAssociation instanceof ManyToOne - assertTrue parentAssociation.bidirectional - assertEquals parentAssociation.associatedEntity, context.getPersistentEntity(Parent.name) - assertTrue parentAssociation.inverseSide.owningSide - } - - @Test - void testInheritedMapping() { - def context = new TestMappingContext() - context.addPersistentEntity(MappingTest2) - assertEquals 2, context.persistentEntities.size() - - def test = context.getPersistentEntity(MappingTest2.name) - PersistentProperty property = test.getPropertyByName("toIndex1") - assertTrue property.mapping.mappedForm.index - property = test.getPropertyByName("toIndex2") - assertTrue property.mapping.mappedForm.index - property = test.getPropertyByName("doNotIndex") - assertFalse property.mapping.mappedForm.index - } -} - -@grails.persistence.Entity -class DerivedEntity extends SecondEntity { - String baz - - static transients = ['baz'] -} - -@grails.persistence.Entity -class SpecialUser extends User { - Set specialFriends - - static hasMany = [specialFriends: User] - - // prevent bidirectional associations here - static mappedBy = [specialFriends: null] -} - -@grails.persistence.Entity -class Parent { - Long id - Set children - - static hasMany = [children: BaseChild] -} - -@grails.persistence.Entity -class BaseChild { - Long id - - Parent parent - - static belongsTo = [parent: Parent] -} - -@grails.persistence.Entity -class DerivedChild extends BaseChild { - String prop -} - -@grails.persistence.Entity -class EmbeddedTest { - Long id - - TestEntity testEntity - - static embedded = ['testEntity'] -} - -@grails.persistence.Entity -class DerivedEmbeddedTest extends EmbeddedTest { - TestEntity testEntity2 - static embedded = ['testEntity2'] -} - -@grails.persistence.Entity -class MappingTest { - Long id - - String toIndex1 - - static mapping = { - toIndex1 index: true - } -} - -@grails.persistence.Entity -class MappingTest2 extends MappingTest { - - String toIndex2 - String doNotIndex - - static mapping = { - toIndex2 index: true - doNotIndex index: false - } -} - diff --git a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/GormMappingSyntaxTests.groovy b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/GormMappingSyntaxTests.groovy deleted file mode 100644 index 79c85e5a4..000000000 --- a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/GormMappingSyntaxTests.groovy +++ /dev/null @@ -1,231 +0,0 @@ -package org.grails.datastore.mapping.model - -import static org.junit.Assert.* - -import javax.persistence.Entity - -import org.junit.Test -import org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy -import org.grails.datastore.mapping.model.types.Association -import org.grails.datastore.mapping.model.types.ManyToOne -import org.grails.datastore.mapping.model.types.OneToMany -import org.grails.datastore.mapping.model.types.OneToOne - -/** - * @author Graeme Rocher - * @since 1.1 - */ -class GormMappingSyntaxTests { - - @Test - void testIsEntity() { - - def strategy = new GormMappingConfigurationStrategy(new TestMappedPropertyFactory()) - - assert strategy.isPersistentEntity(TestEntity) - assert strategy.isPersistentEntity(JavaEntity) - assert !strategy.isPersistentEntity(GormMappingSyntaxTests) - } - - @Test - void testGetIdentity() { - def context = new TestMappingContext() - context.addPersistentEntity(TestEntity) - def strategy = context.mappingSyntaxStrategy - def id = strategy.getIdentity(TestEntity, context) - - assert id != null - - assert id.type == Long - assert id.name == 'id' - } - - @Test - void testGetSimplePersistentProperties() { - def context = new TestMappingContext() - context.addPersistentEntity(TestEntity) - context.addPersistentEntity(SecondEntity) - def strategy = context.mappingSyntaxStrategy - def props = strategy.getPersistentProperties(TestEntity,context) - assert props.size() == 3 - } - - @Test - void testUnidirectionalOneToOneAssociation() { - def context = new TestMappingContext() - context.addPersistentEntity(TestEntity) - - assert 2 == context.persistentEntities.size() - - def testEntity = context.getPersistentEntity(TestEntity.name) - - def association = testEntity.getPropertyByName("second") - - assert association != null - - assert (association instanceof OneToOne) - - OneToOne toOne = association - assert toOne.foreignKeyInChild - assert toOne.associatedEntity != null - - assert toOne.associatedEntity == context.getPersistentEntity(SecondEntity.name) - assert toOne.referencedPropertyName == null - assert toOne.bidirectional == false - assert toOne.owningSide == false - } - - @Test - void testUnidirectionalOneToMany() { - def context = new TestMappingContext() - context.addPersistentEntity(Publisher) - - assert 3 == context.persistentEntities.size() - - def publisher = context.getPersistentEntity(Publisher.name) - - assert publisher != null - - Association oneToMany = publisher.getPropertyByName("authors") - assert oneToMany != null - assert !oneToMany.bidirectional - assert !oneToMany.owningSide - assert (oneToMany instanceof OneToMany) - } - - @Test - void testManyToOneAssociation() { - def context = new TestMappingContext() - context.addPersistentEntity(Book) - - assert 2 == context.persistentEntities.size() - - def book = context.getPersistentEntity(Book.name) - - assert book != null - Association authorAssociation = book.getPropertyByName("author") - - assert authorAssociation != null - assert (authorAssociation instanceof ManyToOne) - assert authorAssociation.bidirectional - assert !authorAssociation.owningSide - - Association inverse = authorAssociation.inverseSide - assert inverse != null - - assert "books" == inverse.name - assert Author == inverse.owner.javaClass - assert inverse.inverseSide != null - assert inverse.bidirectional - assert (inverse instanceof OneToMany) - assert inverse.owningSide - } - - @Test - void testIndexedProperty() { - def context = new TestMappingContext() - context.addPersistentEntity(EntityWithIndexedProperty) - - assertEquals 1, context.persistentEntities.size() - - assertNotNull context.getPersistentEntity(EntityWithIndexedProperty.name) - - assertEquals 3, context.mappingSyntaxStrategy.getPersistentProperties(EntityWithIndexedProperty, context).size() - } - - @Test - void testForceUnidirectional() { - def context = new TestMappingContext() - context.addPersistentEntity(User) - assert 1 == context.persistentEntities.size() - - def user = context.getPersistentEntity(User.name) - - Association foesAssociation = user.getPropertyByName("foes") - assert (foesAssociation instanceof OneToMany) - assert !foesAssociation.isBidirectional() - - Association friendsAssociation = user.getPropertyByName("friends") - assert (friendsAssociation instanceof OneToMany) - assert !friendsAssociation.isBidirectional() - - Association bestBuddyAssociation = user.getPropertyByName("bestBuddy") - assert (bestBuddyAssociation instanceof OneToOne) - assert !bestBuddyAssociation.isBidirectional() - - } - - @Entity - class JavaEntity {} -} - -@grails.persistence.Entity -class Book { - Long id - String title - Author author - static belongsTo = [author:Author] -} - -@grails.persistence.Entity -class Author { - Long id - String name - Set books - def shouldBeIgnored - static hasMany = [books:Book] -} - -@grails.persistence.Entity -class Publisher { - Long id - Set authors - static hasMany = [authors:Author] -} - -@grails.persistence.Entity -class TestEntity { - Long id - Long version - String name - String bar - - SecondEntity second - static hasOne = [second:SecondEntity] - static transients = ['bar'] -} - -@grails.persistence.Entity -class SecondEntity { - Long id - String name - String bar - - static transients = ['bar'] -} - -@grails.persistence.Entity -class EntityWithIndexedProperty { - Long id - Long version - String name - String bar - - String getSectionContent(int section) {} - void setSectionContent(int section, String content) {} -} - -@grails.persistence.Entity -class User { - Long id - Long version - String name - User bestBuddy - Set foes - Set friends - static hasMany = [ foes: User, friends: User] - - // prevent bidirectional associations here - static mappedBy = [ bestBuddy:null, foes:null, friends:null] -} - diff --git a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/TestMappedPropertyFactory.groovy b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/TestMappedPropertyFactory.groovy deleted file mode 100644 index 3b1090fb3..000000000 --- a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/TestMappedPropertyFactory.groovy +++ /dev/null @@ -1,22 +0,0 @@ -package org.grails.datastore.mapping.model - -import org.grails.datastore.mapping.config.AbstractGormMappingFactory -import org.grails.datastore.mapping.config.Entity -import org.grails.datastore.mapping.config.Property - -/** - * @author Graeme Rocher - * @since 1.1 - */ -class TestMappedPropertyFactory extends AbstractGormMappingFactory { - - @Override - protected Class getPropertyMappedFormType() { - Property - } - - @Override - protected Class getEntityMappedFormType() { - Entity - } -} diff --git a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/TestMappingContext.groovy b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/TestMappingContext.groovy deleted file mode 100644 index 9d8453d9e..000000000 --- a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/TestMappingContext.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package org.grails.datastore.mapping.model - -import org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy - -/** - * @author Graeme Rocher - * @since 1.0 - */ -class TestMappingContext extends AbstractMappingContext { - MappingFactory mappingFactory = new TestMappedPropertyFactory() - MappingConfigurationStrategy mappingSyntaxStrategy = new GormMappingConfigurationStrategy(mappingFactory) - - protected PersistentEntity createPersistentEntity(Class javaClass) { - return new TestPersistentEntity(javaClass, this) - } -} diff --git a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/TestPersistentEntity.groovy b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/TestPersistentEntity.groovy deleted file mode 100644 index 91231daa1..000000000 --- a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/TestPersistentEntity.groovy +++ /dev/null @@ -1,34 +0,0 @@ -package org.grails.datastore.mapping.model - -import org.grails.datastore.mapping.config.Entity - -/** - * @author Graeme Rocher - * @since 1.1 - */ -@SuppressWarnings("unchecked") -class TestPersistentEntity extends AbstractPersistentEntity { - private TestClassMapping classMapping - - TestPersistentEntity(Class type, MappingContext ctx) { - super(type, ctx) - classMapping = new TestClassMapping(this, ctx) - } - - @Override - ClassMapping getMapping() { classMapping } - - public class TestClassMapping extends AbstractClassMapping { - private Entity mappedForm; - - TestClassMapping(PersistentEntity entity, MappingContext context) { - super(entity, context) - mappedForm = context.mappingFactory.createMappedForm(TestPersistentEntity.this) - } - - @Override - public Entity getMappedForm() { - return mappedForm; - } - } -} diff --git a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/types/conversion/DefaultConversionServiceSpec.groovy b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/types/conversion/DefaultConversionServiceSpec.groovy deleted file mode 100644 index 5ff081c0f..000000000 --- a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/model/types/conversion/DefaultConversionServiceSpec.groovy +++ /dev/null @@ -1,25 +0,0 @@ -package org.grails.datastore.mapping.model.types.conversion - -import spock.lang.Specification - -class DefaultConversionServiceSpec extends Specification { - - DefaultConversionService conversionService = new DefaultConversionService() - - def "CharSequence conversions should be supported"() { - expect: - conversionService.convert("${'123'}", Integer) == 123 - } - - def "enum conversions should be supported"() { - expect: - conversionService.convert("ONE", MyEnum) == MyEnum.ONE - conversionService.convert(MyEnum.THREE, String) == "THREE" - } - - enum MyEnum { - ONE, - TWO, - THREE - } -} diff --git a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/reflect/ClassPropertyFetcherTests.groovy b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/reflect/ClassPropertyFetcherTests.groovy deleted file mode 100644 index 73969d8e1..000000000 --- a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/reflect/ClassPropertyFetcherTests.groovy +++ /dev/null @@ -1,25 +0,0 @@ -package org.grails.datastore.mapping.reflect - -import org.junit.Test - -/** - * @author Graeme Rocher - * @since 1.1 - */ -class ClassPropertyFetcherTests { - - @Test - void testGetProperty() { - def cpf = ClassPropertyFetcher.forClass(Foo) - - assert 'foo' == cpf.getPropertyValue("name") - assert cpf.getPropertiesAssignableToType(CharSequence).size() == 1 - assert cpf.getPropertiesAssignableToType(String).size() == 1 - } - - static class Foo { - static String name = "foo" - - String bar - } -} diff --git a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/validation/ValidationErrorsSpec.groovy b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/validation/ValidationErrorsSpec.groovy deleted file mode 100644 index 283bde695..000000000 --- a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/validation/ValidationErrorsSpec.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package org.grails.datastore.mapping.validation - -import spock.lang.Specification - -/** - * Tests for validation errors object - */ -class ValidationErrorsSpec extends Specification{ - - void "Test retrieve errors using subscript operator"() { - given:"A validation errors object" - def errors = new ValidationErrors(new Person()) - - when:"errors are stored" - errors['name'] = "error.code" - - then:"They can be retrieved" - errors['name'].code == 'error.code' - } -} -class Person { String name } diff --git a/grails-datastore-dynamodb/build.gradle b/grails-datastore-dynamodb/build.gradle deleted file mode 100644 index 3fa5c4544..000000000 --- a/grails-datastore-dynamodb/build.gradle +++ /dev/null @@ -1,12 +0,0 @@ -version = "0.1.2.BUILD-SNAPSHOT" - -dependencies { - compile project(":grails-datastore-core") - compile('com.amazonaws:aws-java-sdk:1.3.30') { - exclude group:'commons-logging', module:'commons-logging' - exclude group:'org.apache.httpcomponents', module:'httpclient' - } - compile('org.apache.httpcomponents:httpclient:4.1'){ - exclude group:'commons-logging', module:'commons-logging' - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/DelayAfterWriteDynamoDBSession.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/DelayAfterWriteDynamoDBSession.java deleted file mode 100644 index daa169e90..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/DelayAfterWriteDynamoDBSession.java +++ /dev/null @@ -1,44 +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.mapping.dynamodb; - -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; -import org.grails.datastore.mapping.model.MappingContext; -import org.springframework.context.ApplicationEventPublisher; - -/** - * Simple extension used in testing to fight eventual consistency of DynamoDB. - */ -public class DelayAfterWriteDynamoDBSession extends DynamoDBSession { - - private long delayMillis; - - public DelayAfterWriteDynamoDBSession(DynamoDBDatastore datastore, MappingContext mappingContext, - ApplicationEventPublisher publisher, long delayMillis, TPCacheAdapterRepository cacheAdapterRepository) { - super(datastore, mappingContext, publisher, cacheAdapterRepository); - this.delayMillis = delayMillis; - } - - @Override - protected void postFlush(boolean hasUpdates) { - if (hasUpdates) { - pause(); - } - } - - private void pause() { - try { Thread.sleep(delayMillis); } catch (InterruptedException e) { /* ignored */ } - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/DynamoDBDatastore.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/DynamoDBDatastore.java deleted file mode 100644 index f356d7dd2..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/DynamoDBDatastore.java +++ /dev/null @@ -1,239 +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.mapping.dynamodb; - -import static org.grails.datastore.mapping.config.utils.ConfigUtils.read; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.dynamodb.config.DynamoDBMappingContext; -import org.grails.datastore.mapping.dynamodb.engine.AssociationKey; -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBAssociationInfo; -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBIdGenerator; -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBIdGeneratorFactory; -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBNativeItem; -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBTableResolver; -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBTableResolverFactory; -import org.grails.datastore.mapping.dynamodb.model.types.DynamoDBTypeConverterRegistrar; -import org.grails.datastore.mapping.dynamodb.util.DelayAfterWriteDynamoDBTemplateDecorator; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBTemplate; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBTemplateImpl; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.model.types.OneToMany; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.convert.converter.ConverterRegistry; - -/** - * A Datastore implementation for the AWS DynamoDB document store. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -public class DynamoDBDatastore extends AbstractDatastore implements InitializingBean, MappingContext.Listener { - - public static final String SECRET_KEY = "secretKey"; - public static final String ACCESS_KEY = "accessKey"; - public static final String TABLE_NAME_PREFIX_KEY = "tableNamePrefix"; - public static final String DEFAULT_READ_CAPACITY_UNITS = "defaultReadCapacityUnits"; - public static final String DEFAULT_WRITE_CAPACITY_UNITS = "defaultWriteCapacityUnits"; - public static final String DELAY_AFTER_WRITES_MS = "delayAfterWritesMS"; //used for testing - to fight eventual consistency if this flag value is 'true' it will add specified pause after writes - - private DynamoDBTemplate dynamoDBTemplate; //currently there is no need to create template per entity, we can share same instance - protected Map associationInfoMap = new HashMap(); //contains entries only for those associations that need a dedicated table - protected Map entityDomainResolverMap = new HashMap(); - protected Map entityIdGeneratorMap = new HashMap(); - - private String tableNamePrefix; - - private long defaultReadCapacityUnits; - private long defaultWriteCapacityUnits; - - public DynamoDBDatastore() { - this(new DynamoDBMappingContext(), Collections.emptyMap(), null, null); - } - - /** - * Constructs a DynamoDBDatastore using the given MappingContext and connection details map. - * - * @param mappingContext The DynamoDBMappingContext - * @param connectionDetails The connection details containing the {@link #ACCESS_KEY} and {@link #SECRET_KEY} settings - */ - public DynamoDBDatastore(MappingContext mappingContext, - Map connectionDetails, ConfigurableApplicationContext ctx, TPCacheAdapterRepository adapterRepository) { - super(mappingContext, connectionDetails, ctx, adapterRepository); - - if (mappingContext != null) { - mappingContext.addMappingContextListener(this); - } - - initializeConverters(mappingContext); - - tableNamePrefix = read(String.class, TABLE_NAME_PREFIX_KEY, connectionDetails, null); - defaultReadCapacityUnits = read(Long.class, DEFAULT_READ_CAPACITY_UNITS, connectionDetails, (long)1); //minimum for the account in us-east-1 is 1 - defaultWriteCapacityUnits = read(Long.class, DEFAULT_WRITE_CAPACITY_UNITS, connectionDetails, (long)1); //minimum for the account in us-east-1 is 1 - } - - public DynamoDBDatastore(MappingContext mappingContext, Map connectionDetails) { - this(mappingContext, connectionDetails, null, null); - } - - public DynamoDBDatastore(MappingContext mappingContext) { - this(mappingContext, Collections.emptyMap(), null, null); - } - - public DynamoDBTemplate getDynamoDBTemplate(PersistentEntity entity) { -// return dynamoDBTemplates.get(entity); - return dynamoDBTemplate; - } - - public DynamoDBTemplate getDynamoDBTemplate() { - return dynamoDBTemplate; - } - - @Override - protected Session createSession(Map connDetails) { - String delayAfterWrite = read(String.class, DELAY_AFTER_WRITES_MS, connectionDetails, null); - - if (delayAfterWrite != null && !"".equals(delayAfterWrite)) { - return new DelayAfterWriteDynamoDBSession(this, getMappingContext(), getApplicationEventPublisher(), Integer.parseInt(delayAfterWrite), cacheAdapterRepository); - } - return new DynamoDBSession(this, getMappingContext(), getApplicationEventPublisher(), cacheAdapterRepository); - } - - public void afterPropertiesSet() throws Exception { -// for (PersistentEntity entity : mappingContext.getPersistentEntities()) { - // Only create DynamoDB templates for entities that are mapped with DynamoDB -// if (!entity.isExternal()) { -// createDynamoDBTemplate(entity); -// } -// } - createDynamoDBTemplate(); -} - - protected void createDynamoDBTemplate() { - if (dynamoDBTemplate != null) { - return; - } - - String accessKey = read(String.class, ACCESS_KEY, connectionDetails, null); - String secretKey = read(String.class, SECRET_KEY, connectionDetails, null); - String delayAfterWrite = read(String.class, DELAY_AFTER_WRITES_MS, connectionDetails, null); - - dynamoDBTemplate = new DynamoDBTemplateImpl(accessKey, secretKey); - if (delayAfterWrite != null && !"".equals(delayAfterWrite)) { - dynamoDBTemplate = new DelayAfterWriteDynamoDBTemplateDecorator(dynamoDBTemplate, Integer.parseInt(delayAfterWrite)); - } - } - - /** - * If specified, returns table name prefix so that same AWS account can be used for more than one environment (DEV/TEST/PROD etc). - * @return null if name was not specified in the configuration - */ - public String getTableNamePrefix() { - return tableNamePrefix; - } - - public long getDefaultWriteCapacityUnits() { - return defaultWriteCapacityUnits; - } - - public long getDefaultReadCapacityUnits() { - return defaultReadCapacityUnits; - } - - public void persistentEntityAdded(PersistentEntity entity) { - createDynamoDBTemplate(); - analyzeAssociations(entity); - createEntityDomainResolver(entity); - createEntityIdGenerator(entity); - } - - /** - * If the specified association has a dedicated AWS table, returns info for that association, - * otherwise returns null. - */ - public DynamoDBAssociationInfo getAssociationInfo(Association association) { - return associationInfoMap.get(generateAssociationKey(association)); - } - - /** - * Returns table resolver for the specified entity. - * @param entity - * @return the resolver - */ - public DynamoDBTableResolver getEntityDomainResolver(PersistentEntity entity) { - return entityDomainResolverMap.get(entity); - } - - /** - * Returns id generator for the specified entity. - * @param entity - * @return the generator - */ - public DynamoDBIdGenerator getEntityIdGenerator(PersistentEntity entity) { - return entityIdGeneratorMap.get(entity); - } - - protected void createEntityDomainResolver(PersistentEntity entity) { - DynamoDBTableResolverFactory resolverFactory = new DynamoDBTableResolverFactory(); - DynamoDBTableResolver tableResolver = resolverFactory.buildResolver(entity, this); - - entityDomainResolverMap.put(entity, tableResolver); - } - - protected void createEntityIdGenerator(PersistentEntity entity) { - DynamoDBIdGeneratorFactory factory = new DynamoDBIdGeneratorFactory(); - DynamoDBIdGenerator generator = factory.buildIdGenerator(entity, this); - - entityIdGeneratorMap.put(entity, generator); - } - - @Override - protected void initializeConverters(MappingContext mappingContext) { - final ConverterRegistry conversionService = mappingContext.getConverterRegistry(); - new DynamoDBTypeConverterRegistrar().register(conversionService); - } - - /** - * Analyzes associations and for those associations that need to be stored - * in a dedicated AWS table, creates info object with details for that association. - */ - protected void analyzeAssociations(PersistentEntity entity) { - for (Association association : entity.getAssociations()) { - if (association instanceof OneToMany && !association.isBidirectional()) { - String associationDomainName = generateAssociationDomainName(association); - associationInfoMap.put(generateAssociationKey(association), new DynamoDBAssociationInfo(associationDomainName)); - } - } - } - - protected AssociationKey generateAssociationKey(Association association) { - return new AssociationKey(association.getOwner(), association.getName()); - } - - protected String generateAssociationDomainName(Association association) { - String ownerDomainName = DynamoDBUtil.getMappedTableName(association.getOwner()); - return DynamoDBUtil.getPrefixedTableName(tableNamePrefix, ownerDomainName.toUpperCase() + "_" + association.getName().toUpperCase()); - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/DynamoDBSession.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/DynamoDBSession.java deleted file mode 100644 index b415c7b48..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/DynamoDBSession.java +++ /dev/null @@ -1,82 +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.mapping.dynamodb; - -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; -import org.grails.datastore.mapping.core.AbstractSession; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBEntityPersister; -import org.grails.datastore.mapping.dynamodb.query.DynamoDBQuery; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBTemplate; -import org.grails.datastore.mapping.transactions.SessionOnlyTransaction; -import org.grails.datastore.mapping.transactions.Transaction; -import org.springframework.context.ApplicationEventPublisher; - -/** - * A {@link org.grails.datastore.mapping.core.Session} implementation - * for the AWS DynamoDB store. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class DynamoDBSession extends AbstractSession { - - DynamoDBDatastore dynamoDBDatastore; - - public DynamoDBSession(DynamoDBDatastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher, TPCacheAdapterRepository cacheAdapterRepository) { - super(datastore, mappingContext, publisher, cacheAdapterRepository); - this.dynamoDBDatastore = datastore; - } - - @Override - public DynamoDBQuery createQuery(Class type) { - return (DynamoDBQuery) super.createQuery(type); - } - -/* @Override - @SuppressWarnings({"rawtypes", "unchecked"}) - protected void flushPendingInserts(Map> inserts) { - //todo - optimize multiple inserts using batch put (make the number of threshold objects configurable) - for (final PersistentEntity entity : inserts.keySet()) { - final DynamoDBTemplate template = getDynamoDBTemplate(entity.isRoot() ? entity : entity.getRootEntity()); - - throw new RuntimeException("not implemented yet"); -// template.persist(null); //todo - :) - } - } - */ - - public Object getNativeInterface() { - return null; //todo - } - - @Override - protected Persister createPersister(Class cls, MappingContext mappingContext) { - final PersistentEntity entity = mappingContext.getPersistentEntity(cls.getName()); - return entity == null ? null : new DynamoDBEntityPersister(mappingContext, entity, this, publisher, cacheAdapterRepository); - } - - @Override - protected Transaction beginTransactionInternal() { - return new SessionOnlyTransaction(null, this); - } - - public DynamoDBTemplate getDynamoDBTemplate() { - return dynamoDBDatastore.getDynamoDBTemplate(); - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/DynamoDBDomainClassMappedForm.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/DynamoDBDomainClassMappedForm.java deleted file mode 100644 index 7cac40f2c..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/DynamoDBDomainClassMappedForm.java +++ /dev/null @@ -1,94 +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.mapping.dynamodb.config; - -import java.util.Map; - -import org.grails.datastore.mapping.keyvalue.mapping.config.Family; - -/** - * Mapping for - * {@link org.grails.datastore.mapping.dynamodb.config.DynamoDBPersistentEntity} - * with the DynamoDB specific properties so that the following can be used in - * the mapping: - * - *
    - *      static mapping = {
    - *          table 'Person'
    - *          id_generator type:'hilo', maxLo:100  //optional, if not specified UUID is used
    - *          throughput read:10, write:5 //optional, if not specified default values will be used
    - *      }
    - * 
    - * @author Roman Stepanenko - * @since 0.1 - */ -public class DynamoDBDomainClassMappedForm extends Family { - - protected String table; - protected Map id_generator; //id generation configuration - protected Map throughput; //throughput configuration - - public DynamoDBDomainClassMappedForm() { - } - - public DynamoDBDomainClassMappedForm(String table) { - this.table = table; - } - - public DynamoDBDomainClassMappedForm(String keyspace, String table) { - super(keyspace, table); - this.table = table; - } - - public String getTable() { - return table; - } - - public void setTable(String table) { - this.table = table; - super.setFamily(table); - } - - @Override - public void setFamily(String family) { - super.setFamily(family); - table = family; - } - - public Map getId_generator() { - return id_generator; - } - - public void setId_generator(Map id_generator) { - this.id_generator = id_generator; - } - - public Map getThroughput() { - return throughput; - } - - public void setThroughput(Map throughput) { - this.throughput = throughput; - } - - @Override - public String toString() { - return "DynamoDBDomainClassMappedForm{" + - "table='" + table + '\'' + - ", id_generator=" + id_generator + - ", throughput=" + throughput + - '}'; - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/DynamoDBMappingContext.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/DynamoDBMappingContext.java deleted file mode 100644 index 6f0e914b6..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/DynamoDBMappingContext.java +++ /dev/null @@ -1,65 +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.mapping.dynamodb.config; - -import org.grails.datastore.mapping.document.config.Attribute; -import org.grails.datastore.mapping.document.config.Collection; -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; - -/** - * Models a {@link org.grails.datastore.mapping.model.MappingContext} for DynamoDB. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class DynamoDBMappingContext extends AbstractMappingContext { - - protected MappingConfigurationStrategy syntaxStrategy; - MappingFactory mappingFactory; - - public DynamoDBMappingContext() { - mappingFactory = createMappingFactory(); - syntaxStrategy = new GormMappingConfigurationStrategy(mappingFactory); - } - - protected MappingFactory createMappingFactory() { - return new GormDynamoDBMappingFactory(); - } - - @Override - protected PersistentEntity createPersistentEntity(Class javaClass) { - DynamoDBPersistentEntity dynamoDBPersistentEntity = new DynamoDBPersistentEntity(javaClass, this); - - //initialize mapping form for DynamoDBPersistentEntity here - otherwise there are some - //problems with the initialization sequence when some properties have OneToOne - //(FindOrCreateWhereSpec, FindOrSaveWhereSpec, FindOrSaveWhereSpec was failing) - mappingFactory.createMappedForm(dynamoDBPersistentEntity); - - return dynamoDBPersistentEntity; - } - - public MappingConfigurationStrategy getMappingSyntaxStrategy() { - return syntaxStrategy; - } - - public MappingFactory getMappingFactory() { - return mappingFactory; - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/DynamoDBPersistentEntity.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/DynamoDBPersistentEntity.java deleted file mode 100644 index 52c7e680a..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/DynamoDBPersistentEntity.java +++ /dev/null @@ -1,48 +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.mapping.dynamodb.config; - -import org.grails.datastore.mapping.model.*; - -/** - * Models a DynamoDB-mapped entity. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class DynamoDBPersistentEntity extends AbstractPersistentEntity { - - public DynamoDBPersistentEntity(Class javaClass, MappingContext context) { - super(javaClass, context); - } - - @SuppressWarnings("unchecked") - @Override - public ClassMapping getMapping() { - return new DynamoDBClassMapping(this, context); - } - - public class DynamoDBClassMapping extends AbstractClassMapping { - - public DynamoDBClassMapping(PersistentEntity entity, MappingContext context) { - super(entity, context); - } - - @Override - public DynamoDBDomainClassMappedForm getMappedForm() { - return (DynamoDBDomainClassMappedForm) context.getMappingFactory().createMappedForm(DynamoDBPersistentEntity.this); - } - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/GormDynamoDBMappingFactory.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/GormDynamoDBMappingFactory.java deleted file mode 100644 index adbea1061..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/config/GormDynamoDBMappingFactory.java +++ /dev/null @@ -1,58 +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.mapping.dynamodb.config; - -import groovy.lang.Closure; -import org.grails.datastore.mapping.config.groovy.MappingConfigurationBuilder; -import org.grails.datastore.mapping.keyvalue.mapping.config.Family; -import org.grails.datastore.mapping.keyvalue.mapping.config.GormKeyValueMappingFactory; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; - -/** - * MappingFactory for DynamoDB. - * - * @author Roman Stepanenko - * @since 0.l - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class GormDynamoDBMappingFactory extends GormKeyValueMappingFactory { - - public GormDynamoDBMappingFactory() { - super(null); - } - - @Override - public Family createMappedForm(PersistentEntity entity) { - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass()); - - Closure value = cpf.getStaticPropertyValue(GormProperties.MAPPING, Closure.class); - if (value == null) { - return new DynamoDBDomainClassMappedForm(entity.getName()); - } - - Family family = new DynamoDBDomainClassMappedForm(); - MappingConfigurationBuilder builder = new MappingConfigurationBuilder(family, getPropertyMappedFormType()); - - builder.evaluate(value); - value = cpf.getStaticPropertyValue(GormProperties.CONSTRAINTS, Closure.class); - if (value != null) { - builder.evaluate(value); - } - entityToPropertyMap.put(entity, builder.getProperties()); - return family; - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/AbstractDynamoDBTableResolver.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/AbstractDynamoDBTableResolver.java deleted file mode 100644 index 820efb7b2..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/AbstractDynamoDBTableResolver.java +++ /dev/null @@ -1,39 +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.mapping.dynamodb.engine; - -import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil; - -/** - * @author Roman Stepanenko - */ -public abstract class AbstractDynamoDBTableResolver implements DynamoDBTableResolver { - - protected String entityFamily; - protected String tableNamePrefix; - - public AbstractDynamoDBTableResolver(String entityFamily, String tableNamePrefix) { - this.tableNamePrefix = tableNamePrefix; - this.entityFamily = DynamoDBUtil.getPrefixedTableName(tableNamePrefix, entityFamily); - } - - /** - * Helper getter for subclasses. - * @return entityFamily - */ - protected String getEntityFamily() { - return entityFamily; - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/AssociationKey.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/AssociationKey.java deleted file mode 100644 index 33e234412..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/AssociationKey.java +++ /dev/null @@ -1,62 +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.mapping.dynamodb.engine; - -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Simple key object for looking up Associations from a map. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class AssociationKey { - - private PersistentEntity owner; - private String name; - - public AssociationKey(PersistentEntity owner, String name) { - this.owner = owner; - this.name = name; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - AssociationKey that = (AssociationKey) o; - - if (name != null ? !name.equals(that.name) : that.name != null) { - return false; - } - if (owner != null ? !owner.equals(that.owner) : that.owner != null) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = owner != null ? owner.hashCode() : 0; - result = 31 * result + (name != null ? name.hashCode() : 0); - return result; - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/ConstDynamoDBTableResolver.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/ConstDynamoDBTableResolver.java deleted file mode 100644 index 1bda07a36..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/ConstDynamoDBTableResolver.java +++ /dev/null @@ -1,42 +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.mapping.dynamodb.engine; - -import java.util.LinkedList; -import java.util.List; - -/** - * An implementation of the table resolver which assumes there is no sharding - - * i.e. always the same table name for all the primary keys (for the same type - * of {@link org.grails.datastore.mapping.model.PersistentEntity} - */ -public class ConstDynamoDBTableResolver extends AbstractDynamoDBTableResolver { - - private List tables; - - public ConstDynamoDBTableResolver(String entityFamily, String tableNamePrefix) { - super(entityFamily, tableNamePrefix); //parent contains the logic for figuring out the final entityFamily - tables = new LinkedList(); - tables.add(getEntityFamily()); // without sharding there is just one table - } - - public String resolveTable(String id) { - return entityFamily; // without sharding it is always the same one per PersistentEntity - } - - public List getAllTablesForEntity() { - return tables; - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBAssociationIndexer.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBAssociationIndexer.java deleted file mode 100644 index 1b52a0576..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBAssociationIndexer.java +++ /dev/null @@ -1,132 +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.mapping.dynamodb.engine; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.grails.datastore.mapping.dynamodb.DynamoDBDatastore; -import org.grails.datastore.mapping.dynamodb.DynamoDBSession; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil; -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.types.Association; - -import com.amazonaws.services.dynamodb.model.AttributeAction; -import com.amazonaws.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodb.model.AttributeValueUpdate; -import com.amazonaws.services.dynamodb.model.ComparisonOperator; -import com.amazonaws.services.dynamodb.model.Condition; - -/** - * An {@link org.grails.datastore.mapping.engine.AssociationIndexer} implementation for the DynamoDB store. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@SuppressWarnings("rawtypes") -public class DynamoDBAssociationIndexer implements AssociationIndexer { - public static final String FOREIGN_KEY_ATTRIBUTE_NAME = "FK"; - - private Association association; - private DynamoDBSession session; - - public DynamoDBAssociationIndexer(DynamoDBNativeItem nativeEntry, Association association, DynamoDBSession session) { - this.association = association; - this.session = session; - } - - public PersistentEntity getIndexedEntity() { - return association.getAssociatedEntity(); - } - - public void preIndex(Object primaryKey, List foreignKeys) { - // handled by index below. - } - - public void index(Object primaryKey, List foreignKeys) { -// System.out.println("INDEX: index for id: "+primaryKey+", keys: "+foreignKeys+". entry: "+nativeEntry+", association: "+association); - if (association.isBidirectional()) { //we use additional table only for unidirectional - return; - } - - DynamoDBAssociationInfo associationInfo = getDatastore().getAssociationInfo(association); - //we store them in a multi-value attribute - //and key this collection by the primary key of the entity - - Map updateItems = new HashMap(); - //collect all foreign keys into string list - List fks = new ArrayList(); - for (Object foreignKey : foreignKeys) { - fks.add(foreignKey.toString()); - } - - if (fks.isEmpty()) { - //we can't create dynamodb entry without any attributes, so we must kill it - session.getDynamoDBTemplate().deleteItem(associationInfo.getTableName(), DynamoDBUtil.createIdKey(primaryKey.toString())); - } else { - updateItems.put(FOREIGN_KEY_ATTRIBUTE_NAME, - new AttributeValueUpdate() - .withAction(AttributeAction.PUT) - .withValue(new AttributeValue().withSS(fks))); - session.getDynamoDBTemplate().updateItem(associationInfo.getTableName(), DynamoDBUtil.createIdKey(primaryKey.toString()), updateItems); - } - - } - - public List query(Object primaryKey) { -// System.out.println("INDEX: query for id: "+primaryKey+". entry: "+nativeEntry+", association: "+association); - if (!association.isBidirectional()) { //we use additional table only for unidirectional - DynamoDBAssociationInfo associationInfo = getDatastore().getAssociationInfo(association); - Map item = session.getDynamoDBTemplate().get(associationInfo.getTableName(), DynamoDBUtil.createIdKey(primaryKey.toString())); - if (item == null) { - return Collections.EMPTY_LIST; - } else { - return DynamoDBUtil.getAttributeValues(item, FOREIGN_KEY_ATTRIBUTE_NAME); - } - } - - //for bidirectional onToMany association the use the other entity to refer to this guy's PK via FK - DynamoDBTableResolver tableResolver = getDatastore().getEntityDomainResolver(association.getAssociatedEntity()); - - Map filter = new HashMap(); - DynamoDBUtil.addSimpleComparison(filter, - association.getInverseSide().getName(), - ComparisonOperator.EQ.toString(), - primaryKey.toString(), false); - - List> items = session.getDynamoDBTemplate().scan(tableResolver.getAllTablesForEntity().get(0), filter, Integer.MAX_VALUE); - if (items.isEmpty()) { - return Collections.EMPTY_LIST; - } - return DynamoDBUtil.collectIds(items); - } - - private DynamoDBDatastore getDatastore() { - return ((DynamoDBDatastore) session.getDatastore()); - } - - public void index(Object primaryKey, Object foreignKey) { -// System.out.println("INDEX: index for id: "+primaryKey+", KEY: "+foreignKey+". entry: "+nativeEntry+", association: "+association); - if (association.isBidirectional()) { //we use additional table only for unidirectional - return; - } - - throw new RuntimeException("not implemented: index(Object primaryKey, Object foreignKey)"); - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBAssociationInfo.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBAssociationInfo.java deleted file mode 100644 index af50df5d4..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBAssociationInfo.java +++ /dev/null @@ -1,39 +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.mapping.dynamodb.engine; - -/** - * For associations that are stored in dedicated tables (unidirectional onToMany), contains - * table name for each association. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class DynamoDBAssociationInfo { - - private String tableName; - - public DynamoDBAssociationInfo(String tableName) { - this.tableName = tableName; - } - - public String getTableName() { - return tableName; - } - - public void setTableName(String tableName) { - this.tableName = tableName; - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBEntityPersister.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBEntityPersister.java deleted file mode 100644 index 7780f6e37..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBEntityPersister.java +++ /dev/null @@ -1,279 +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.mapping.dynamodb.engine; - -import com.amazonaws.services.dynamodb.model.AttributeAction; -import com.amazonaws.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodb.model.AttributeValueUpdate; -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil; -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.NativeEntryEntityPersister; -import org.grails.datastore.mapping.engine.PropertyValueIndexer; -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.Association; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.dynamodb.DynamoDBDatastore; -import org.grails.datastore.mapping.dynamodb.DynamoDBSession; -import org.grails.datastore.mapping.dynamodb.query.DynamoDBQuery; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBConverterUtil; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBTemplate; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.dao.DataAccessException; - -import java.io.Serializable; -import java.util.*; - -/** - * A {@link org.grails.datastore.mapping.engine.EntityPersister} implementation for the DynamoDB store. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -public class DynamoDBEntityPersister extends NativeEntryEntityPersister { - - protected DynamoDBTemplate dynamoDBTemplate; - protected String entityFamily; - protected DynamoDBTableResolver tableResolver; - protected DynamoDBIdGenerator idGenerator; - protected boolean hasNumericalIdentifier = false; - protected boolean hasStringIdentifier = false; - - public DynamoDBEntityPersister(MappingContext mappingContext, PersistentEntity entity, - DynamoDBSession dynamoDBSession, ApplicationEventPublisher publisher, TPCacheAdapterRepository cacheAdapterRepository) { - super(mappingContext, entity, dynamoDBSession, publisher, cacheAdapterRepository); - DynamoDBDatastore datastore = (DynamoDBDatastore) dynamoDBSession.getDatastore(); - dynamoDBTemplate = datastore.getDynamoDBTemplate(entity); - - hasNumericalIdentifier = Long.class.isAssignableFrom(entity.getIdentity().getType()); - hasStringIdentifier = String.class.isAssignableFrom(entity.getIdentity().getType()); - tableResolver = datastore.getEntityDomainResolver(entity); - idGenerator = datastore.getEntityIdGenerator(entity); - } - - public Query createQuery() { - return new DynamoDBQuery(getSession(), getPersistentEntity(), tableResolver, this, dynamoDBTemplate); - } - - public DynamoDBTableResolver getTableResolver() { - return tableResolver; - } - - @Override - protected boolean doesRequirePropertyIndexing() { - return false; - } - - @Override - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected List retrieveAllEntities(PersistentEntity persistentEntity, - Iterable keys) { - - Query query = session.createQuery(persistentEntity.getJavaClass()); - - if (keys instanceof List) { - if (((List)keys).isEmpty()) { - return Collections.EMPTY_LIST; - } - query.in(persistentEntity.getIdentity().getName(), (List)keys); - } - else { - List keyList = new ArrayList(); - for (Serializable key : keys) { - keyList.add(key); - } - if (keyList.isEmpty()) { - return Collections.EMPTY_LIST; - } - query.in(persistentEntity.getIdentity().getName(), keyList); - } - - List entityResults = new ArrayList(); - Iterator keyIterator = keys.iterator(); - Iterator listIterator = query.list().iterator(); - while (keyIterator.hasNext() && listIterator.hasNext()) { - Serializable key = keyIterator.next(); - Object next = listIterator.next(); - if (next instanceof DynamoDBNativeItem) { - entityResults.add(createObjectFromNativeEntry(getPersistentEntity(), key, (DynamoDBNativeItem)next)); - } - else { - entityResults.add(next); - } - } - - return entityResults; - } - - @Override - protected List retrieveAllEntities(PersistentEntity persistentEntity, Serializable[] keys) { - return retrieveAllEntities(persistentEntity, Arrays.asList(keys)); - } - - @Override - public String getEntityFamily() { - return entityFamily; - } - - @Override - protected void deleteEntry(String family, Object key, Object entry) { - String domain = tableResolver.resolveTable((String) key); - dynamoDBTemplate.deleteItem(domain, DynamoDBUtil.createIdKey((String) key)); - } - - @Override - protected Object generateIdentifier(final PersistentEntity persistentEntity, - final DynamoDBNativeItem nativeEntry) { - return idGenerator.generateIdentifier(persistentEntity, nativeEntry); - } - - @SuppressWarnings("rawtypes") - @Override - public PropertyValueIndexer getPropertyIndexer(PersistentProperty property) { - // We don't need to implement this for DynamoDB since DynamoDB automatically creates indexes for us - return null; - } - - @Override - @SuppressWarnings("rawtypes") - public AssociationIndexer getAssociationIndexer(DynamoDBNativeItem nativeEntry, Association association) { - return new DynamoDBAssociationIndexer(nativeEntry, association, (DynamoDBSession) session); - } - - @Override - protected DynamoDBNativeItem createNewEntry(String family) { - return new DynamoDBNativeItem(); - } - - @Override - protected Object getEntryValue(DynamoDBNativeItem nativeEntry, String property) { - return nativeEntry.get(property); - } - - @Override - protected void setEntryValue(DynamoDBNativeItem nativeEntry, String key, Object value) { - if (value != null && !getMappingContext().isPersistentEntity(value)) { - String stringValue = DynamoDBConverterUtil.convertToString(value, getMappingContext()); - boolean isNumber = DynamoDBConverterUtil.isNumber(value); - - nativeEntry.put(key, stringValue, isNumber); - } - } - -// @Override -// protected EntityAccess createEntityAccess(PersistentEntity persistentEntity, Object obj, DynamoDBNativeItem nativeEntry) { -// final NativeEntryModifyingEntityAccess ea = new DynamoDBNativeEntryModifyingEntityAccess(persistentEntity, obj); -// ea.setNativeEntry(nativeEntry); -// return ea; -// } - - @Override - protected DynamoDBNativeItem retrieveEntry(final PersistentEntity persistentEntity, - String family, final Serializable key) { - String table = tableResolver.resolveTable((String) key); - Map item = dynamoDBTemplate.get(table, DynamoDBUtil.createIdKey((String) key)); - return item == null ? null : new DynamoDBNativeItem(item); - } - - @Override - protected Object storeEntry(final PersistentEntity persistentEntity, final EntityAccess entityAccess, - final Object storeId, final DynamoDBNativeItem entry) { - String id = storeId.toString(); - String table = tableResolver.resolveTable(id); - - Map allAttributes = entry.createItem(); - entry.put("id", id, false); - - dynamoDBTemplate.putItem(table, allAttributes); - return storeId; //todo should we return string id here? - } - - @Override - public void updateEntry(final PersistentEntity persistentEntity, final EntityAccess ea, - final Object key, final DynamoDBNativeItem entry) { - - String id = key.toString(); - String table = tableResolver.resolveTable(id); - - Map allAttributes = entry.createItem(); - - Map updates = new HashMap(); - - //we have to put *new* (incremented) version as part of the 'version' value and use the old version value in the conditional update. - //if the update fails we have to restore the version to the old value - Object currentVersion = null; - String stringCurrentVersion = null; - if (isVersioned(ea)) { - currentVersion = ea.getProperty("version"); - stringCurrentVersion = convertVersionToString(currentVersion); - incrementVersion(ea); //increment version now before we save it - } - - for (Map.Entry e : allAttributes.entrySet()) { - if ("version".equals(e.getKey())) { - //ignore it, it will be explicitly added later right before the insert by taking incrementing and taking new one - } else if ("id".equals(e.getKey())) { - //ignore it, we do not want to mark it as PUT - dynamo will freak out because it is primary key (can't be updated) - } else { - AttributeValue av = e.getValue(); - if (av.getS() != null || av.getN() != null) { - updates.put(e.getKey(), new AttributeValueUpdate(av, AttributeAction.PUT)); - } else { - updates.put(e.getKey(), new AttributeValueUpdate(null, AttributeAction.DELETE)); //http://stackoverflow.com/questions/9142074/deleting-attribute-in-dynamodb - } - } - } - - if (isVersioned(ea)) { - putAttributeForVersion(updates, ea); //update the version - try { - dynamoDBTemplate.updateItemVersioned(table, DynamoDBUtil.createIdKey(id), updates, stringCurrentVersion, persistentEntity); - } catch (DataAccessException e) { - //we need to restore version to what it was before the attempt to update - ea.setProperty("version", currentVersion); - throw e; - } - } else { - dynamoDBTemplate.updateItem(table, DynamoDBUtil.createIdKey(id), updates); - } - } - - protected void putAttributeForVersion(Map updates, EntityAccess ea) { - AttributeValueUpdate attrToPut; - Object updatedVersion = ea.getProperty("version"); - String stringUpdatedVersion = convertVersionToString(updatedVersion); - attrToPut = new AttributeValueUpdate(new AttributeValue().withN(stringUpdatedVersion), - AttributeAction.PUT); - updates.put("version", attrToPut); - } - - protected String convertVersionToString(Object currentVersion) { - if (currentVersion == null) { - return null; - } - - return currentVersion.toString(); - } - - @Override - protected void deleteEntries(String family, final List keys) { - for (Object key : keys) { - deleteEntry(family, key, null); //todo - optimize for bulk removal - } - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBHiLoIdGenerator.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBHiLoIdGenerator.java deleted file mode 100644 index 0fbd93acd..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBHiLoIdGenerator.java +++ /dev/null @@ -1,148 +0,0 @@ -package org.grails.datastore.mapping.dynamodb.engine; - -import java.util.HashMap; -import java.util.Map; - -import org.grails.datastore.mapping.core.OptimisticLockingException; -import org.grails.datastore.mapping.dynamodb.DynamoDBDatastore; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBConst; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.springframework.dao.DataAccessException; - -import com.amazonaws.AmazonServiceException; -import com.amazonaws.services.dynamodb.model.AttributeValue; - -/** - * Implementation of HiLo generator for DynamoDB. - * All HiLows are stored in a single dedicated AWS table. Id of each record is the corresponding table name of the - * {@link org.grails.datastore.mapping.model.PersistentEntity}. The only attributes are the nextHi long attribute and the version. - * - * @author Roman Stepanenko - */ -public class DynamoDBHiLoIdGenerator implements DynamoDBIdGenerator { - /** - * @param table table where the all the counters are stored - * @param id name of the domain for some {@link org.grails.datastore.mapping.model.PersistentEntity} for which this instance will be keeping the counter - * @param datastore - */ - public DynamoDBHiLoIdGenerator(String table, String id, int lowSize, DynamoDBDatastore datastore) { - this.table = table; - this.id = id; - this.lowSize = lowSize; - this.datastore = datastore; - } - - public synchronized Object generateIdentifier(PersistentEntity persistentEntity, DynamoDBNativeItem nativeEntry) { - if (!initialized) { - initialize(persistentEntity); - } - if (current == max) { - incrementDBAndRefresh(persistentEntity); - reset(); - } - - long result = current; - current = current + 1; - return result; - } - - private void reset() { - current = currentHi * lowSize; - max = current + lowSize; - } - - private void incrementDBAndRefresh(PersistentEntity persistentEntity) { - boolean done = false; - int attempt = 0; - while (!done) { - attempt++; - if (attempt > 10000) {//todo - make configurable at some point - throw new IllegalArgumentException("exceeded number of attempts to load new Hi value value from db"); - } - try { - Map item = datastore.getDynamoDBTemplate().getConsistent(table, DynamoDBUtil.createIdKey(id)); - - if (item == null) {//no record exist yet - currentHi = 1; - currentVersion = null; - } else { - currentHi = Long.parseLong(DynamoDBUtil.getAttributeValueNumeric(item, DynamoDBConst.ID_GENERATOR_HI_LO_ATTRIBUTE_NAME)); - currentVersion = Long.parseLong(DynamoDBUtil.getAttributeValueNumeric(item, "version")); - } - - long nextHi = currentHi + 1; - long nextVersion = currentVersion == null ? (long)1: currentVersion+1; - - createOrUpdate(nextHi, nextVersion, currentVersion, persistentEntity); - currentVersion = nextVersion; - - done = true; - } catch (OptimisticLockingException e) { - //collition, it is expected to happen, we will try again - } - } - } - - /** - * Create table if needed. - */ - private void initialize(PersistentEntity persistentEntity) { - try { - /*Map item =*/ datastore.getDynamoDBTemplate().getConsistent(table, DynamoDBUtil.createIdKey(id)); - } catch (DataAccessException e) { - throw new RuntimeException(e); - } catch (Exception e) { - //check if domain does not exist at all - AmazonServiceException awsE = null; - if (e instanceof AmazonServiceException) { - awsE = (AmazonServiceException) e; - } else if (e.getCause() instanceof AmazonServiceException) { - awsE = (AmazonServiceException) e.getCause(); - } - if (awsE != null && DynamoDBUtil.AWS_ERR_CODE_RESOURCE_NOT_FOUND.equals(awsE.getErrorCode())) { - //table does not exist, must create it - createHiLoTable(datastore, table); - } else { - throw new RuntimeException(e); - } - } - - current = 0; - max = 0; - - initialized = true; - } - - public static void createHiLoTable(DynamoDBDatastore datastore, String tableName) { - datastore.getDynamoDBTemplate().createTable( - tableName, - DynamoDBUtil.createIdKeySchema(), - DynamoDBUtil.createDefaultProvisionedThroughput(datastore)); - } - - private void createOrUpdate(long nextHi, long newVersion, Long expectedVersion, PersistentEntity persistentEntity) { - Map item = new HashMap(); - item.put(DynamoDBConst.ID_GENERATOR_HI_LO_ATTRIBUTE_NAME, new AttributeValue().withN(String.valueOf(nextHi))); - item.put("version", new AttributeValue().withN(String.valueOf(newVersion))); - DynamoDBUtil.addId(item, id); - if (expectedVersion == null) { - //since there is no record yet we can't assert on version - datastore.getDynamoDBTemplate().putItem(table, item); - } else { - datastore.getDynamoDBTemplate().putItemVersioned(table, DynamoDBUtil.createIdKey(id), item, String.valueOf(expectedVersion), persistentEntity); - } - } - - private String id; - private long current; - private int lowSize; - private long max; - - private boolean initialized; - private long currentHi; - private Long currentVersion; - - private DynamoDBDatastore datastore; - private String table; -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBIdGenerator.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBIdGenerator.java deleted file mode 100644 index 269e79720..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBIdGenerator.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.grails.datastore.mapping.dynamodb.engine; - -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Encapsulates logic for generating id for a DynamoDB object. - * - * @author Roman Stepanenko - */ -public interface DynamoDBIdGenerator { - Object generateIdentifier(final PersistentEntity persistentEntity, final DynamoDBNativeItem nativeEntry); -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBIdGeneratorFactory.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBIdGeneratorFactory.java deleted file mode 100644 index d9174210a..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBIdGeneratorFactory.java +++ /dev/null @@ -1,63 +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.mapping.dynamodb.engine; - -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.dynamodb.DynamoDBDatastore; -import org.grails.datastore.mapping.dynamodb.config.DynamoDBDomainClassMappedForm; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBConst; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil; - -import java.util.Map; - -/** - * Encapsulates logic of building appropriately configured DynamoDBIdGenerator instance. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class DynamoDBIdGeneratorFactory { - - public DynamoDBIdGenerator buildIdGenerator(PersistentEntity entity, DynamoDBDatastore dynamoDBDatastore) { - String entityFamily = DynamoDBUtil.getMappedTableName(entity); - - @SuppressWarnings("unchecked") - ClassMapping classMapping = entity.getMapping(); - DynamoDBDomainClassMappedForm mappedForm = classMapping.getMappedForm(); - - Map generatorInfo = mappedForm.getId_generator(); - - //by default use uuid generator - if (generatorInfo == null || generatorInfo.isEmpty()) { - return new DynamoDBUUIDIdGenerator(); - } - - String generatorType = (String) generatorInfo.get(DynamoDBConst.PROP_ID_GENERATOR_TYPE); - if (DynamoDBConst.PROP_ID_GENERATOR_TYPE_UUID.equals(generatorType)) { - return new DynamoDBUUIDIdGenerator(); - } else if ((DynamoDBConst.PROP_ID_GENERATOR_TYPE_HILO.equals(generatorType))) { - Integer lowSize = (Integer) generatorInfo.get(DynamoDBConst.PROP_ID_GENERATOR_MAX_LO); - if (lowSize == null) { - lowSize = DynamoDBConst.PROP_ID_GENERATOR_MAX_LO_DEFAULT_VALUE; // default value - } - String hiloDomainName = DynamoDBUtil.getPrefixedTableName(dynamoDBDatastore.getTableNamePrefix(), DynamoDBConst.ID_GENERATOR_HI_LO_TABLE_NAME); - return new DynamoDBHiLoIdGenerator(hiloDomainName, entityFamily, lowSize, dynamoDBDatastore); - } else { - throw new IllegalArgumentException("unknown id generator type for dynamodb: " + generatorType + ". Current implementation supports only " + - DynamoDBConst.PROP_ID_GENERATOR_TYPE_UUID + " and " + DynamoDBConst.PROP_ID_GENERATOR_TYPE_HILO); - } - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBNativeItem.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBNativeItem.java deleted file mode 100644 index d44d33895..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBNativeItem.java +++ /dev/null @@ -1,74 +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.mapping.dynamodb.engine; - -import com.amazonaws.services.dynamodb.model.AttributeValue; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil; - -import java.util.HashMap; -import java.util.Map; - -/** - * Logical representation of how information is loaded from and sent to AWS. - *

    - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class DynamoDBNativeItem { - - private Map data = new HashMap(); //todo - not sure about concurrency requirements? - - public DynamoDBNativeItem() { - } - - public DynamoDBNativeItem(Map item) { - //populate map with the item attributes. //todo - handle multi-value attributes/long string etc - for (Map.Entry entry : item.entrySet()) { - data.put(entry.getKey(), entry.getValue()); - } - } - - public void put(String key, String stringValue, boolean isNumber) { - data.put(key, DynamoDBUtil.createAttributeValue(stringValue, isNumber)); - } - - public String get(String key) { - AttributeValue attributeValue = data.get(key); - if (attributeValue == null) { - return null; - } - - //it can be either numeric or string format, try first string and then numeric - unfortunately we do not have access to real type - String result = attributeValue.getS(); - if (result == null) { - result = attributeValue.getN(); - } - - return result; - } - - public Map createItem() { -// Map result = new HashMap(); -// result.putAll(data); -// return result; - return data; //this method is used only in read-only fashion, so it is safe to return the inner map - } - - @Override - public String toString() { - return "DynamoDBNativeItem{data=" + data + '}'; - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBTableResolver.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBTableResolver.java deleted file mode 100644 index 170614d36..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBTableResolver.java +++ /dev/null @@ -1,48 +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.mapping.dynamodb.engine; - -import java.util.List; - -/** - * Encapsulates logic of determining DynamoDB domain name based specific a - * primary key, assuming that this instance of the resolver is used only for one - * {@link org.grails.datastore.mapping.model.PersistentEntity}, which - * was provided during construction time of this instance. - * - * Strictly speaking sharding is not really needed for DynamoDB because it is supposed - * to provide infinite scalability of a single table, but is left just in case. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public interface DynamoDBTableResolver { - - /** - * Returns domain name for the specified primary key value. - * - * @param id the id - * @return the domain name - */ - String resolveTable(String id); - - /** - * Returns all domain names for this type of entity. Without sharding this - * list contains always one element. - * - * @return the names - */ - List getAllTablesForEntity(); -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBTableResolverFactory.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBTableResolverFactory.java deleted file mode 100644 index 5df7314ae..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBTableResolverFactory.java +++ /dev/null @@ -1,33 +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.mapping.dynamodb.engine; - -import org.grails.datastore.mapping.dynamodb.DynamoDBDatastore; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Encapsulates logic of building appropriately configured DynamoDBTableResolver instance. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class DynamoDBTableResolverFactory { - - public DynamoDBTableResolver buildResolver(PersistentEntity entity, DynamoDBDatastore dynamoDBDatastore) { - String entityFamily = DynamoDBUtil.getMappedTableName(entity); - return new ConstDynamoDBTableResolver(entityFamily, dynamoDBDatastore.getTableNamePrefix()); - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBUUIDIdGenerator.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBUUIDIdGenerator.java deleted file mode 100644 index 053458b23..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/engine/DynamoDBUUIDIdGenerator.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.grails.datastore.mapping.dynamodb.engine; - -import org.grails.datastore.mapping.model.PersistentEntity; - -import java.util.UUID; - -/** - * Uses java UUID to generate a unique id. - * @author Roman Stepanenko - */ -public class DynamoDBUUIDIdGenerator implements DynamoDBIdGenerator { - public Object generateIdentifier(PersistentEntity persistentEntity, DynamoDBNativeItem nativeEntry) { - return UUID.randomUUID().toString(); - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/model/types/DynamoDBTypeConverterRegistrar.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/model/types/DynamoDBTypeConverterRegistrar.java deleted file mode 100644 index 0003ad147..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/model/types/DynamoDBTypeConverterRegistrar.java +++ /dev/null @@ -1,62 +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.mapping.dynamodb.model.types; - -import org.grails.datastore.mapping.model.types.BasicTypeConverterRegistrar; -import org.springframework.core.convert.converter.Converter; -import org.springframework.core.convert.converter.ConverterRegistry; - -/** - * A registrar that registers type converters used for DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class DynamoDBTypeConverterRegistrar extends BasicTypeConverterRegistrar { - - public void register(ConverterRegistry registry) { - //use most of the standard converters - super.register(registry); - - registry.addConverter(new Converter() { - public String convert(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i< bytes.length;i++){ - sb.append(bytes[i]); - if (i < bytes.length-1) { - sb.append(","); - } - - } - return sb.toString(); - } - }); - registry.addConverter(new Converter() { - public byte[] convert(String s) { - if (s == null || s.isEmpty()) { - return EMPTY_BYTES; - } - String[] tokens = s.split(","); - byte[] bytes = new byte[tokens.length]; - for (int i = 0; i< tokens.length; i++){ - bytes[i] = Byte.parseByte(tokens[i]); - } - return bytes; - } - }); - - } - private static final byte[] EMPTY_BYTES = new byte[0]; -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/query/DynamoDBQuery.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/query/DynamoDBQuery.java deleted file mode 100644 index 985055476..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/query/DynamoDBQuery.java +++ /dev/null @@ -1,555 +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.mapping.dynamodb.query; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBEntityPersister; -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBNativeItem; -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBTableResolver; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBConverterUtil; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBTemplate; -import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil; -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValue; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.order.ManualEntityOrdering; - -import com.amazonaws.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodb.model.ComparisonOperator; -import com.amazonaws.services.dynamodb.model.Condition; - -/** - * A {@link org.grails.datastore.mapping.query.Query} implementation for the DynamoDB store - * - * @author Roman Stepanenko - * @since 0.1 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class DynamoDBQuery extends Query { - - protected DynamoDBTableResolver tableResolver; - protected DynamoDBTemplate dynamoDBTemplate; - protected DynamoDBEntityPersister dynamoDBEntityPersister; - - protected static Map queryHandlers = new HashMap(); - - static { - //see http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/API_Scan.html - //for a list of all dynamodb operators and their arguments - - queryHandlers.put(Equals.class, new QueryHandler() { - public void handle(PersistentEntity entity, Equals criterion, Map filter) { - String propertyName = criterion.getProperty(); - String key = getKey(entity, propertyName); - if (criterion.getValue() == null) { - //for null we have to use special operator - DynamoDBUtil.checkFilterForExistingKey(filter, key); - filter.put(key, new Condition().withComparisonOperator(ComparisonOperator.NULL.toString())); - } else { - String stringValue = DynamoDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - boolean isNumber = DynamoDBConverterUtil.isNumber(criterion.getValue()); - - DynamoDBUtil.addSimpleComparison(filter, key, ComparisonOperator.EQ.toString(), stringValue, isNumber); - } - } - }); - queryHandlers.put(NotEquals.class, new QueryHandler() { - public void handle(PersistentEntity entity, NotEquals criterion, Map filter) { - String propertyName = criterion.getProperty(); - String key = getKey(entity, propertyName); - if (criterion.getValue() == null) { - //for null we have to use special operator - DynamoDBUtil.checkFilterForExistingKey(filter, key); - filter.put(key, new Condition().withComparisonOperator(ComparisonOperator.NOT_NULL.toString())); - } else { - String stringValue = DynamoDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - boolean isNumber = DynamoDBConverterUtil.isNumber(criterion.getValue()); - - DynamoDBUtil.addSimpleComparison(filter, key, ComparisonOperator.NE.toString(), stringValue, isNumber); - } - } - }); - queryHandlers.put(IdEquals.class, new QueryHandler() { - public void handle(PersistentEntity entity, IdEquals criterion, Map filter) { - String stringValue = DynamoDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - - DynamoDBUtil.addSimpleComparison(filter, "id", ComparisonOperator.EQ.toString(), stringValue, false); - } - }); - queryHandlers.put(Like.class, new QueryHandler() { - public void handle(PersistentEntity entity, Like criterion, Map filter) { - String propertyName = criterion.getProperty(); - String key = getKey(entity, propertyName); - String stringValue = DynamoDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - boolean isNumber = DynamoDBConverterUtil.isNumber(criterion.getValue()); - - //dynamo db has only 'contains' and 'begins_with' operators, so we have to take out '%' and figure out which one to use - - String searchToken = stringValue; - - //begins_with is without % at all or (xxx% and not %xxx%) - if (!searchToken.contains("%") || (searchToken.endsWith("%") && !searchToken.startsWith("%"))) { - if (searchToken.endsWith("%")) { - //kill % at the end - searchToken = searchToken.substring(0, searchToken.length() - 1); - } - - //make sure % is not in the middle - we can't handle it with dynamo - if (searchToken.contains("%")) { - throw new IllegalArgumentException("DynamoDB can not handle % in the middle of search string. You specified: " + stringValue); - } - - DynamoDBUtil.addSimpleComparison(filter, key, ComparisonOperator.BEGINS_WITH.toString(), searchToken, isNumber); - } else { - //if we got here it has to start with % - //the only supported cases are %xxx and %xxx% - - if (searchToken.endsWith("%")) { - //kill % at the end - searchToken = searchToken.substring(0, searchToken.length() - 1); - } - - if (searchToken.startsWith("%")) { - //kill % at the beginning - searchToken = searchToken.substring(1, searchToken.length()); - } - - //make sure % is not in the middle - we can't handle it with dynamo - if (searchToken.contains("%")) { - throw new IllegalArgumentException("DynamoDB can not handle % in the middle of search string. You specified: " + stringValue); - } - - DynamoDBUtil.addSimpleComparison(filter, key, ComparisonOperator.CONTAINS.toString(), searchToken, isNumber); - } - } - }); - queryHandlers.put(In.class, new QueryHandler() { - public void handle(PersistentEntity entity, In criterion, Map filter) { - String propertyName = criterion.getProperty(); - String key = getKey(entity, propertyName); - - DynamoDBUtil.checkFilterForExistingKey(filter, key); - - Collection stringValues = DynamoDBConverterUtil.convertToStrings(criterion.getValues(), entity.getMappingContext()); - boolean isNumber = false; - if (!criterion.getValues().isEmpty()) { - //all values should be of the same type, so take a look at the first - isNumber = DynamoDBConverterUtil.isNumber(criterion.getValues().iterator().next()); - } - - Collection attributeValues = new ArrayList(); - for (String stringValue : stringValues) { - DynamoDBUtil.addAttributeValue(attributeValues, stringValue, isNumber); - } - - filter.put(key, new Condition().withComparisonOperator(ComparisonOperator.IN.toString()). - withAttributeValueList(attributeValues)); - } - }); - queryHandlers.put(Between.class, new QueryHandler() { - public void handle(PersistentEntity entity, Between criterion, Map filter) { - String propertyName = criterion.getProperty(); - String key = getKey(entity, propertyName); - String fromStringValue = DynamoDBConverterUtil.convertToString(criterion.getFrom(), entity.getMappingContext()); - String toStringValue = DynamoDBConverterUtil.convertToString(criterion.getTo(), entity.getMappingContext()); - - DynamoDBUtil.checkFilterForExistingKey(filter, key); - - boolean isNumber = DynamoDBConverterUtil.isNumber(criterion.getFrom()); - Collection attributeValues = new ArrayList(); - DynamoDBUtil.addAttributeValue(attributeValues, fromStringValue, isNumber); - DynamoDBUtil.addAttributeValue(attributeValues, toStringValue, isNumber); - - filter.put(key, new Condition().withComparisonOperator(ComparisonOperator.BETWEEN.toString()). - withAttributeValueList(attributeValues)); - } - }); - queryHandlers.put(GreaterThan.class, new QueryHandler() { - public void handle(PersistentEntity entity, GreaterThan criterion, Map filter) { - String propertyName = criterion.getProperty(); - String key = getKey(entity, propertyName); - String stringValue = DynamoDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - boolean isNumber = DynamoDBConverterUtil.isNumber(criterion.getValue()); - - DynamoDBUtil.addSimpleComparison(filter, key, ComparisonOperator.GT.toString(), stringValue, isNumber); - } - }); - queryHandlers.put(GreaterThanEquals.class, new QueryHandler() { - public void handle(PersistentEntity entity, GreaterThanEquals criterion, Map filter) { - String propertyName = criterion.getProperty(); - String key = getKey(entity, propertyName); - String stringValue = DynamoDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - boolean isNumber = DynamoDBConverterUtil.isNumber(criterion.getValue()); - - DynamoDBUtil.addSimpleComparison(filter, key, ComparisonOperator.GE.toString(), stringValue, isNumber); - } - }); - queryHandlers.put(LessThan.class, new QueryHandler() { - public void handle(PersistentEntity entity, LessThan criterion, Map filter) { - String propertyName = criterion.getProperty(); - String key = getKey(entity, propertyName); - String stringValue = DynamoDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - boolean isNumber = DynamoDBConverterUtil.isNumber(criterion.getValue()); - - DynamoDBUtil.addSimpleComparison(filter, key, ComparisonOperator.LT.toString(), stringValue, isNumber); - } - }); - queryHandlers.put(LessThanEquals.class, new QueryHandler() { - public void handle(PersistentEntity entity, LessThanEquals criterion, Map filter) { - String propertyName = criterion.getProperty(); - String key = getKey(entity, propertyName); - String stringValue = DynamoDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - boolean isNumber = DynamoDBConverterUtil.isNumber(criterion.getValue()); - - DynamoDBUtil.addSimpleComparison(filter, key, ComparisonOperator.LE.toString(), stringValue, isNumber); - } - }); - } - - public DynamoDBQuery(Session session, PersistentEntity entity, DynamoDBTableResolver tableResolver, - DynamoDBEntityPersister dynamoDBEntityPersister, DynamoDBTemplate dynamoDBTemplate) { - super(session, entity); - this.tableResolver = tableResolver; - this.dynamoDBEntityPersister = dynamoDBEntityPersister; - this.dynamoDBTemplate = dynamoDBTemplate; - } - - @Override - protected List executeQuery(PersistentEntity entity, Junction criteria) { - String table = tableResolver.getAllTablesForEntity().get(0); - - final List projectionList = projections().getProjectionList(); - boolean hasCountProjection = false; - - if (!projectionList.isEmpty()) { - hasCountProjection = validateProjectionsAndCheckIfCountIsPresent(projectionList); - } - - List> independentConditions = flattenAndReplaceDisjunction(criteria); - List> filters = buildFilters(independentConditions); - - int maxToGet = max < 0 ? Integer.MAX_VALUE : max; - boolean hasOrdering = !getOrderBy().isEmpty(); - - List results; - if (projectionList.isEmpty()) { - if (!hasOrdering) { - results = doGetItems(table, filters, maxToGet).objects; - } else { - //since we sort in memory, if we have ordering we should get all matches, then sort, then cut to the maximum size - results = doGetItems(table, filters, Integer.MAX_VALUE).objects; - results = handleOrdering(entity, results); - results = resizeUpTo(results, maxToGet); - } - } else { - if (hasCountProjection) { //count is returned by AWS in a special way... - results = new ArrayList(); - if (independentConditions.size() == 1) { - //optimization - if we only have one query to run we can use scan with the count request - int count = dynamoDBTemplate.scanCount(table, filters.get(0)); - results.add(count); - } else { - //we have to actually get the items and return size of the collection because for queries '(a or b) and (a or c)' we can't return sum of counts - List loaded = doGetItems(table, filters, maxToGet).objects; - results.add(loaded.size()); - } - } else { - List orderBys = getOrderBy(); - - if (!orderBys.isEmpty()) { - //too messy to implement for initial cut - throw new UnsupportedOperationException("'order by' can't be used with projections (not implemented yet). You have: " + orderBys.size()); - } - - List> items = doGetItems(table, filters, maxToGet).items; - results = new ArrayList(); - for (Projection projection : projectionList) { - if (IdProjection.class.equals(projection.getClass())) { - for (Map item : items) { - results.add(DynamoDBUtil.getAttributeValue(item, "id")); - } - } else if (PropertyProjection.class.equals(projection.getClass())) { - for (Map item : items) { - String key = extractPropertyKey(((PropertyProjection) projection).getPropertyName(), entity); - results.add(DynamoDBUtil.getAttributeValue(item, key)); - } - } - } - } - } - - return results; - } - - private List resizeUpTo(List results, int max) { - if (results.size() > max) { - return results.subList(0, max); - } else { - return results; - } - } - - private List handleOrdering(PersistentEntity entity, List results) { - ManualEntityOrdering ordering = new ManualEntityOrdering(entity); - List orderBys = getOrderBy(); - results = ordering.applyOrder(results, orderBys); - return results; - } - - private Results doGetItems(String table, List> filters, int maxToGet) { - List objects = new ArrayList(); - List> resultItems = new ArrayList>(); - Set alreadyLoadedIds = new HashSet(); - for (Map filter : filters) { - List> items = dynamoDBTemplate.scan(table, filter, maxToGet); - for (Map item : items) { - Object id = DynamoDBUtil.getIdKey(item); - if (!alreadyLoadedIds.contains(id)) { - if (objects.size() < maxToGet) { - objects.add(createObjectFromItem(item)); - resultItems.add(item); - alreadyLoadedIds.add(id); - } - } - } - } - return new Results(objects, resultItems); - } - - private List> buildFilters(List> independentConditions) { - List> result = new ArrayList>(); - if (independentConditions.isEmpty()) { - //if there are no criteria queries, create single dummy empty filter, otherwise we will not call dynamo at all - if (independentConditions.isEmpty()) { - result.add((Map) Collections.EMPTY_MAP); - } - } else { - for (List query : independentConditions) { - Map filter = new HashMap(); - for (PropertyCriterion propertyCriterion : query) { - QueryHandler queryHandler = queryHandlers.get(propertyCriterion.getClass()); - if (queryHandler != null) { - queryHandler.handle(entity, propertyCriterion, filter); - } else { - throw new UnsupportedOperationException("Queries of type " + - propertyCriterion.getClass().getSimpleName() + " are not supported by this implementation"); - } - } - result.add(filter); - } - } - - return result; - } - - /** - * make sure that only property, id, or count projections are provided, and that the combination of them is meaningful. - * Throws exception if something is invalid. - * - * @param projections - * @returns true if count projection is present, false otherwise. - */ - private boolean validateProjectionsAndCheckIfCountIsPresent(List projections) { - //of the grouping projects AWS DynamoDB only supports count(*) projection, nothing else. Other kinds will have - //to be explicitly coded later... - boolean hasCountProjection = false; - for (Projection projection : projections) { - if (!(PropertyProjection.class.equals(projection.getClass()) || - IdProjection.class.equals(projection.getClass()) || - CountProjection.class.equals(projection.getClass()) - )) { - throw new UnsupportedOperationException("Currently projections of type " + - projection.getClass().getSimpleName() + " are not supported by this implementation"); - } - - if (CountProjection.class.equals(projection.getClass())) { - hasCountProjection = true; - } - } - if (projections.size() > 1 && hasCountProjection) { - throw new IllegalArgumentException("Can not mix count projection and other types of projections. You requested: " + projections); - } - return hasCountProjection; - } - - /** - * Recurses into the specified junction and flattens it into a list. Each top-level element in this list - * represents queries on properties (meant as conjunction queries) which must be fired independently of each other, and then later - * combined to get unique set of matching elements. This is needed because dynamodb does not support OR queries in any shape of form. - * For example, to illustrate behavior of this method: - * just property a ==> [ [a] ] //1 query - * a and b = con(a,b) ==> [ [a,b] ] //1 query - * a or b = dis(a,b) ==> [ [a], [b] ] //2 queries: 1 for a, 1 for b - * (a or b) and c = Con( Dis(a,b) , c ) = [Con(a,c), con(b,c)] ==> [ [a,c], [b,c] ] // 2 queries - 1 for a&c, 1 for b&c - * (a or b) and c,d = Con( Dis(a,b) , c , d) = [Con(a,c,d), con(b,c,d)] ==> [ [a,c,d], [b,c,d] ] //2 queries - * (a and b) and c = con(con(a,b), c) ==> [ [a,b,c] ] //1 query - * (a and b) or c = dis(con(a,b), c) ==> [ [a,b], [c] ] //2 queries - * - * @param criteria - * @return the results - */ - private List> flattenAndReplaceDisjunction(Junction criteria) { - List> result = new ArrayList>(); - - if (criteria instanceof Conjunction) { - List> temp = handleConjunction((Conjunction) criteria); - result.addAll(temp); - } else if (criteria instanceof Disjunction) { - handleDisjunction(criteria, result); - } else if (criteria instanceof Negation) { - throw new RuntimeException("negation clause is not supported, please change your query"); - } else { - throw new UnsupportedOperationException("Queries of type " + - criteria.getClass().getSimpleName() + " are not supported by this implementation"); - } - - return result; - } - - private void handleDisjunction(Junction criteria, List> result) { - //we flatten each criterion and add output to result - for (Criterion c : criteria.getCriteria()) { - if (c instanceof PropertyCriterion) { - List temp = new ArrayList(); - temp.add((PropertyCriterion) c); - - result.add(temp); - } else { - List> flattened = flattenAndReplaceDisjunction((Junction) c); - result.addAll(flattened); - } - } - } - - private List> handleConjunction(Conjunction criterion) { - List> result = new ArrayList>(); - //first collect the non-disjunctions and disjunctions - List properties = new ArrayList(); - List>> toCombinate = new ArrayList>>(); - for (Criterion c : ((Conjunction) criterion).getCriteria()) { - if (c instanceof PropertyCriterion) { - properties.add((PropertyCriterion) c); - } - if (c instanceof Conjunction) { - //lets process it and see if there were any disjunctions internally - List> inner = flattenAndReplaceDisjunction((Junction) c); - if (inner.size() == 1) { - properties.addAll(inner.get(0)); - } else { - toCombinate.add(inner); - } - } - if (c instanceof Disjunction) { - List> inner = flattenAndReplaceDisjunction((Junction) c); - //a or b = [ [a],[b] ] - toCombinate.add(inner); - } - if (c instanceof Negation) { - throw new RuntimeException("negation clause is not supported, please change your query"); - } - } - - if (toCombinate.isEmpty()) { - result.add(properties); - } else { - /* - con((a or b),(c or d),e) = con(a,c,e),con(b,c,e),con(a,d,e),con(b,d,e) - con((a or b),(c or d),e) => - toCombinate is [ - [ [a],[b] ], - [ [c],[d] ] - ] - properties = [ e ] - */ - //add properties to the combination list as a single element, so it becomes - /* - toCombinate is [ - [ [a],[b] ], - [ [c],[d] ], - [ [e] ] - ] - */ - List> temp = new ArrayList>(); - temp.add(properties); - toCombinate.add(temp); - - List> combinations = DynamoDBUtil.combinate(toCombinate); - result = combinations; - } - return result; - } - - protected Object createObjectFromItem(Map item) { - final String id = DynamoDBUtil.getAttributeValue(item, "id"); - return dynamoDBEntityPersister.createObjectFromNativeEntry(getEntity(), id, - new DynamoDBNativeItem(item)); - } - - protected static interface QueryHandler { - public void handle(PersistentEntity entity, T criterion, Map filter); - } - - protected static String extractPropertyKey(String propertyName, PersistentEntity entity) { - PersistentProperty prop = null; - if (entity.isIdentityName(propertyName)) { - prop = entity.getIdentity(); - } else { - prop = entity.getPropertyByName(propertyName); - } - - if (prop == null) { - throw new IllegalArgumentException( - "Could not find property '" + propertyName + "' in entity '" + entity.getName() + "' : " + entity); - } - - KeyValue kv = (KeyValue) prop.getMapping().getMappedForm(); - String key = kv.getKey(); - return key; - } - - /** - * Returns mapped key - * - * @param entity - * @param propertyName - * @return the key - */ - protected static String getKey(PersistentEntity entity, String propertyName) { - return extractPropertyKey(propertyName, entity); - } - - /** - * simple temp container - */ - protected static class Results { - public Results(List objects, List> items) { - this.objects = objects; - this.items = items; - } - - public List objects; - public List> items; - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DataStoreOperationException.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DataStoreOperationException.java deleted file mode 100644 index 058d7b63c..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DataStoreOperationException.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.grails.datastore.mapping.dynamodb.util; - -import org.springframework.dao.DataAccessException; - -public class DataStoreOperationException extends DataAccessException { - private static final long serialVersionUID = 1; - - public DataStoreOperationException(String msg) { - super(msg); - } - - public DataStoreOperationException(String msg, Throwable cause) { - super(msg, cause); - } -} \ No newline at end of file diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DelayAfterWriteDynamoDBTemplateDecorator.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DelayAfterWriteDynamoDBTemplateDecorator.java deleted file mode 100644 index 8e9eef2f1..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DelayAfterWriteDynamoDBTemplateDecorator.java +++ /dev/null @@ -1,114 +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.mapping.dynamodb.util; - -import java.util.List; -import java.util.Map; - -import org.grails.datastore.mapping.model.PersistentEntity; -import org.springframework.dao.DataAccessException; - -import com.amazonaws.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodb.model.AttributeValueUpdate; -import com.amazonaws.services.dynamodb.model.Condition; -import com.amazonaws.services.dynamodb.model.Key; -import com.amazonaws.services.dynamodb.model.KeySchema; -import com.amazonaws.services.dynamodb.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodb.model.TableDescription; - -/** - * Simple decorator used in testing to fight eventual consistency of DynamoDB. - */ -public class DelayAfterWriteDynamoDBTemplateDecorator implements DynamoDBTemplate { - - private DynamoDBTemplate template; - private long delayMillis; - - public DelayAfterWriteDynamoDBTemplateDecorator(DynamoDBTemplate template, long delayMillis) { - this.template = template; - this.delayMillis = delayMillis; - } - - public boolean deleteAllItems(String domainName) throws DataAccessException { - boolean result = template.deleteAllItems(domainName); - if (result) { - pause(); //pause only if there were items to delete - } - return result; - } - - public List> scan(String tableName, Map filter, int max) throws DataAccessException { - return template.scan(tableName, filter, max); - } - - public int scanCount(String tableName, Map filter) { - return template.scanCount(tableName, filter); - } - - public void deleteTable(String domainName) throws DataAccessException { - template.deleteTable(domainName); - pause(); - } - - public Map get(String tableName, Key id) throws DataAccessException { - return template.get(tableName, id); - } - - public Map getConsistent(String domainName, Key id) throws DataAccessException { - return template.getConsistent(domainName, id); - } - - public void putItem(String tableName, Map attributes) throws DataAccessException { - template.putItem(tableName, attributes); -// pause(); //for tests we use DelayAfterWriteDynamoDBSession which pauses after flush - } - - public void putItemVersioned(String tableName, Key key, Map attributes, String expectedVersion, PersistentEntity persistentEntity) throws DataAccessException { - template.putItemVersioned(tableName, key, attributes, expectedVersion, persistentEntity); -// pause(); //for tests we use DelayAfterWriteDynamoDBSession which pauses after flush - } - - public void updateItem(String tableName, Key key, Map attributes) throws DataAccessException { - template.updateItem(tableName, key, attributes); -// pause(); //for tests we use DelayAfterWriteDynamoDBSession which pauses after flush - } - - public void updateItemVersioned(String tableName, Key key, Map attributes, String expectedVersion, PersistentEntity persistentEntity) throws DataAccessException { - template.updateItemVersioned(tableName, key, attributes, expectedVersion, persistentEntity); -// pause(); //for tests we use DelayAfterWriteDynamoDBSession which pauses after flush - } - - public void deleteItem(String tableName, Key key) throws DataAccessException { - template.deleteItem(tableName, key); -// pause(); //for tests we use DelayAfterWriteDynamoDBSession which pauses after flush - } - - public List listTables() throws DataAccessException { - return template.listTables(); - } - - public void createTable(String tableName, KeySchema ks, ProvisionedThroughput provisionedThroughput) throws DataAccessException { - template.createTable(tableName, ks, provisionedThroughput); - pause(); - } - - public TableDescription describeTable(String tableName) throws DataAccessException { - return template.describeTable(tableName); - } - - private void pause() { - try { Thread.sleep(delayMillis); } catch (InterruptedException e) { /* ignored */ } - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBConst.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBConst.java deleted file mode 100644 index 26f7f52ef..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBConst.java +++ /dev/null @@ -1,55 +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.mapping.dynamodb.util; - -/** - * Various constants for DynamoDB support. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class DynamoDBConst { - - private DynamoDBConst() { - // don't instantiate - } - - public static final String PROP_ID_GENERATOR_TYPE = "type"; - public static final String PROP_ID_GENERATOR_TYPE_HILO = "hilo"; - public static final String PROP_ID_GENERATOR_TYPE_UUID = "uuid"; //used by default - public static final String PROP_ID_GENERATOR_MAX_LO = "maxLo"; - public static final int PROP_ID_GENERATOR_MAX_LO_DEFAULT_VALUE = 1000; - public static final String ID_GENERATOR_HI_LO_TABLE_NAME = "HiLo"; //in which domain will HiLo store the counters, this domain name might be prefixed, as for all other domains - public static final String ID_GENERATOR_HI_LO_ATTRIBUTE_NAME = "nextHi"; - - public static final String THROUGHPUT_READ_ATTRIBUTE_NAME = "read"; - public static final String THROUGHPUT_WRITE_ATTRIBUTE_NAME = "write"; - - public static final String PROP_SHARDING_ENABLED = "enabled"; - - /** - * What must be specified in mapping as a value of 'mapWith' to map the - * domain class with DynamoDB gorm plugin: - *
    -     * class DomPerson {
    -     *      String id
    -     *      String firstName
    -     *      static mapWith = "dynamodb"
    -     * }
    -     * 
    - */ - public static final String DYNAMO_DB_MAP_WITH_VALUE = "dynamodb"; - -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBConverterUtil.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBConverterUtil.java deleted file mode 100644 index 165fddc14..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBConverterUtil.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.grails.datastore.mapping.dynamodb.util; - -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.proxy.EntityProxy; -import org.springframework.core.convert.ConversionService; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; - -/** - * Simple conversion utility for DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class DynamoDBConverterUtil { - public static String convertToString(Object value, MappingContext mappingContext) { - String stringValue = null; - if (value instanceof String) { - stringValue = (String)value; - } else if (shouldConvert(value, mappingContext)) { - final ConversionService conversionService = mappingContext.getConversionService(); - stringValue = conversionService.convert(value, String.class); - } - return stringValue; - } - - public static boolean isNumber(Object value) { - return value instanceof Number; - } - - public static Collection convertToStrings(Collection values, MappingContext mappingContext) { - List stringValues = new LinkedList(); - for (Object value : values) { - stringValues.add(convertToString(value, mappingContext)); - } - - return stringValues; - } - - private static boolean shouldConvert(Object value, MappingContext mappingContext) { - return !mappingContext.isPersistentEntity(value) && !(value instanceof EntityProxy); - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBTemplate.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBTemplate.java deleted file mode 100644 index 0e0716be6..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBTemplate.java +++ /dev/null @@ -1,165 +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.mapping.dynamodb.util; - -import java.util.List; -import java.util.Map; - -import org.grails.datastore.mapping.model.PersistentEntity; -import org.springframework.dao.DataAccessException; - -import com.amazonaws.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodb.model.AttributeValueUpdate; -import com.amazonaws.services.dynamodb.model.Condition; -import com.amazonaws.services.dynamodb.model.Key; -import com.amazonaws.services.dynamodb.model.KeySchema; -import com.amazonaws.services.dynamodb.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodb.model.TableDescription; - -/** - * AWS DynamoDB template. This is a low-level way of accessing DynamoDB, - * currently is uses AWS SDK API as the return and parameter types. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public interface DynamoDBTemplate { - /** - * Returns null if not found - * @param tableName complete name of the table in DynamoDB, will be used as-is - * @param key the key for which to retrieve the data - * @return null if the item is not found - * @throws DataAccessException - */ - Map get(String tableName, Key key) throws DataAccessException; - - /** - * Same as get but with consistent read flag. - * @param tableName complete name of the table in DynamoDB, will be used as-is - * @param key the key for which to retrieve the data - * @return null if the item is not found - * @throws org.springframework.dao.DataAccessException - */ - Map getConsistent(String tableName, Key key) throws DataAccessException; - - /** - * Executes 'put' Dynamo DB command, replacing all existing attributes if they exist. - * - * http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/LowLevelJavaItemCRUD.html#PutLowLevelAPIJava - * - * @param tableName complete name of the table in DynamoDB, will be used as-is - * @param attributes - * @throws org.springframework.dao.DataAccessException - */ - void putItem(String tableName, Map attributes) throws DataAccessException; - - /** - * Executes 'put' Dynamo DB command, replacing all existing attributes if they exist. - * Put is conditioned on the specified version - used for optimistic - * locking. If the specified expectedVersion does not match what is in - * dynamoDB, exception is thrown and no changes are made to the dynamoDB - * - * http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/LowLevelJavaItemCRUD.html#PutLowLevelAPIJava - * @param tableName complete name of the table in DynamoDB, will be used as-is - * @param key - * @param attributes - * @param expectedVersion - * @throws org.springframework.dao.DataAccessException - */ - void putItemVersioned(String tableName, Key key, Map attributes, String expectedVersion, PersistentEntity persistentEntity) throws DataAccessException; - - /** - * Executes 'update' Dynamo DB command, which can be used to add/replace/delete specified attributes. - * - * http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/LowLevelJavaItemCRUD.html#LowLevelJavaItemUpdate - * @param tableName complete name of the table in DynamoDB, will be used as-is - * @param key - * @param attributes - * @throws org.springframework.dao.DataAccessException - */ - void updateItem(String tableName, Key key, Map attributes) throws DataAccessException; - - /** - * Executes 'update' Dynamo DB command, which can be used to add/replace/delete specified attributes. - * Update is conditioned on the specified version - used for optimistic - * locking. If the specified expectedVersion does not match what is in - * dynamoDB, exception is thrown and no changes are made to the dynamoDB - * - * http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/LowLevelJavaItemCRUD.html#LowLevelJavaItemUpdate - * @param tableName complete name of the table in DynamoDB, will be used as-is - * @param key - * @param attributes - * @throws org.springframework.dao.DataAccessException - */ - void updateItemVersioned(String tableName, Key key, Map attributes, String expectedVersion, PersistentEntity persistentEntity) throws DataAccessException; - - /** - * Deletes the specified item with all of its attributes. - * - * @param tableName complete name of the table in DynamoDB, will be used as-is - * @param key the key for which to retrieve the data - */ - void deleteItem(String tableName, Key key) throws DataAccessException; - - /** - * Returns true if any item was deleted, in other words if domain was empty it returns false. - * @param tableName complete name of the table in DynamoDB, will be used as-is - * @return true if any item was deleted - * @throws org.springframework.dao.DataAccessException - */ - boolean deleteAllItems(String tableName) throws DataAccessException; - - /** - * Executes scan Dynamo DB operation (note this operation does not scale well with the growth of the table). - * @param max maximum amount of items to return (inclusive) - * @return the scan results - * @throws org.springframework.dao.DataAccessException - */ - List> scan(String tableName, Map filter, int max) throws DataAccessException; - - /** - * Executes scan Dynamo DB operation and returns the count of matched items - * (note this operation does not scale well with the growth of the table) - * @param tableName the table name - * @param filter filters - * @return the count of matched items - */ - int scanCount(String tableName, Map filter); - - /** - * Blocking call - internally will wait until the table is successfully deleted. - * @throws DataAccessException - */ - void deleteTable(String domainName) throws DataAccessException; - - List listTables() throws DataAccessException; - - /** - * Blocking call - internally will wait until the table is successfully created and is in ACTIVE state. - * @param tableName the table name - * @param ks the schema - * @param provisionedThroughput the throughput - * @throws DataAccessException - */ - void createTable(String tableName, KeySchema ks, ProvisionedThroughput provisionedThroughput) throws DataAccessException; - - /** - * Returns table description object containing throughput and key scheme information - * @param tableName the table name - * @return the description - * @throws org.springframework.dao.DataAccessException - */ - TableDescription describeTable(String tableName) throws DataAccessException; -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBTemplateImpl.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBTemplateImpl.java deleted file mode 100644 index a9daae74b..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBTemplateImpl.java +++ /dev/null @@ -1,430 +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.mapping.dynamodb.util; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.grails.datastore.mapping.core.OptimisticLockingException; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.springframework.dao.DataAccessException; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -import com.amazonaws.AmazonClientException; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.services.dynamodb.AmazonDynamoDB; -import com.amazonaws.services.dynamodb.AmazonDynamoDBClient; -import com.amazonaws.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodb.model.AttributeValueUpdate; -import com.amazonaws.services.dynamodb.model.Condition; -import com.amazonaws.services.dynamodb.model.CreateTableRequest; -import com.amazonaws.services.dynamodb.model.DeleteItemRequest; -import com.amazonaws.services.dynamodb.model.DeleteTableRequest; -import com.amazonaws.services.dynamodb.model.DescribeTableRequest; -import com.amazonaws.services.dynamodb.model.ExpectedAttributeValue; -import com.amazonaws.services.dynamodb.model.GetItemRequest; -import com.amazonaws.services.dynamodb.model.GetItemResult; -import com.amazonaws.services.dynamodb.model.Key; -import com.amazonaws.services.dynamodb.model.KeySchema; -import com.amazonaws.services.dynamodb.model.ListTablesRequest; -import com.amazonaws.services.dynamodb.model.ListTablesResult; -import com.amazonaws.services.dynamodb.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodb.model.PutItemRequest; -import com.amazonaws.services.dynamodb.model.ResourceNotFoundException; -import com.amazonaws.services.dynamodb.model.ScanRequest; -import com.amazonaws.services.dynamodb.model.ScanResult; -import com.amazonaws.services.dynamodb.model.TableDescription; -import com.amazonaws.services.dynamodb.model.UpdateItemRequest; - -/** - * Implementation of DynamoDBTemplate using AWS Java SDK. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class DynamoDBTemplateImpl implements DynamoDBTemplate { - - private AmazonDynamoDB ddb; - - public DynamoDBTemplateImpl(AmazonDynamoDB ddb) { - this.ddb = ddb; - } - - public DynamoDBTemplateImpl(String accessKey, String secretKey) { - Assert.isTrue(StringUtils.hasLength(accessKey) && StringUtils.hasLength(secretKey), - "Please provide accessKey and secretKey"); - - ddb = new AmazonDynamoDBClient(new BasicAWSCredentials(accessKey, secretKey)); - } - - public Map get(String tableName, Key id) { - return getInternal(tableName, id, 1); - } - - private Map getInternal(String tableName, Key key, int attempt) { - GetItemRequest request = new GetItemRequest(tableName, key); - try { - GetItemResult result = ddb.getItem(request); - Map attributes = result.getItem(); - if (attributes == null || attributes.isEmpty()) { - return null; - } - return attributes; - } catch (AmazonServiceException e) { - if (DynamoDBUtil.AWS_ERR_CODE_RESOURCE_NOT_FOUND.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such table: " + tableName, e); - } else if (DynamoDBUtil.AWS_STATUS_CODE_SERVICE_UNAVAILABLE == e.getStatusCode()) { - //retry after a small pause - DynamoDBUtil.sleepBeforeRetry(attempt); - attempt++; - return getInternal(tableName, key, attempt); - } else { - throw new DataStoreOperationException("problem with table: " + tableName + ", key: " + key, e); - } - } - } - - public Map getConsistent(String domainName, Key key) { - return getConsistentInternal(domainName, key, 1); - } - - private Map getConsistentInternal(String tableName, Key key, int attempt) { - GetItemRequest request = new GetItemRequest(tableName, key); - request.setConsistentRead(true); - try { - GetItemResult result = ddb.getItem(request); - Map attributes = result.getItem(); - if (attributes == null || attributes.isEmpty()) { - return null; - } - return attributes; - } catch (AmazonServiceException e) { - if (DynamoDBUtil.AWS_ERR_CODE_RESOURCE_NOT_FOUND.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such table: " + tableName, e); - } else if (DynamoDBUtil.AWS_STATUS_CODE_SERVICE_UNAVAILABLE == e.getStatusCode()) { - //retry after a small pause - DynamoDBUtil.sleepBeforeRetry(attempt); - attempt++; - return getConsistentInternal(tableName, key, attempt); - } else { - throw new DataStoreOperationException("problem with table: " + tableName + ", key: " + key, e); - } - } - } - - public void putItem(String tableName, Map attributes) throws DataAccessException { - putItemInternal(tableName, attributes, 1); - } - - private void putItemInternal(String tableName, Map attributes, int attempt) throws DataAccessException { - try { - PutItemRequest request = new PutItemRequest(tableName, attributes); - ddb.putItem(request); - } catch (AmazonServiceException e) { - if (DynamoDBUtil.AWS_ERR_CODE_RESOURCE_NOT_FOUND.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such table: " + tableName, e); - } else if (DynamoDBUtil.AWS_STATUS_CODE_SERVICE_UNAVAILABLE == e.getStatusCode()) { - //retry after a small pause - DynamoDBUtil.sleepBeforeRetry(attempt); - attempt++; - putItemInternal(tableName, attributes, attempt); - } else { - throw new DataStoreOperationException("problem with table: " + tableName + ", attributes: " + attributes, e); - } - } - } - - public void putItemVersioned(String tableName, Key key, Map attributes, String expectedVersion, PersistentEntity persistentEntity) throws DataAccessException { - putItemVersionedInternal(tableName, key, attributes, expectedVersion, persistentEntity, 1); - } - - private void putItemVersionedInternal(String tableName, Key key, Map attributes, String expectedVersion, PersistentEntity persistentEntity, int attempt) throws DataAccessException { - PutItemRequest request = new PutItemRequest(tableName, attributes).withExpected(getOptimisticVersionCondition(expectedVersion)); - try { - ddb.putItem(request); - } catch (AmazonServiceException e) { - if (DynamoDBUtil.AWS_ERR_CODE_CONDITIONAL_CHECK_FAILED.equals(e.getErrorCode())) { - throw new OptimisticLockingException(persistentEntity, key); - } else if (DynamoDBUtil.AWS_ERR_CODE_RESOURCE_NOT_FOUND.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such table: " + tableName, e); - } else if (DynamoDBUtil.AWS_STATUS_CODE_SERVICE_UNAVAILABLE == e.getStatusCode()) { - //retry after a small pause - DynamoDBUtil.sleepBeforeRetry(attempt); - attempt++; - putItemVersionedInternal(tableName, key, attributes, expectedVersion, persistentEntity, attempt); - } else { - throw new DataStoreOperationException("problem with table: " + tableName + ", key: " + key + ", attributes: " + attributes, e); - } - } - } - - public void updateItem(String tableName, Key key, Map attributes) throws DataAccessException { - updateItemInternal(tableName, key, attributes, 1); - } - - private void updateItemInternal(String tableName, Key key, Map attributes, int attempt) throws DataAccessException { - try { - UpdateItemRequest request = new UpdateItemRequest(tableName, key, attributes); - ddb.updateItem(request); - } catch (AmazonServiceException e) { - if (DynamoDBUtil.AWS_ERR_CODE_RESOURCE_NOT_FOUND.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such table: " + tableName, e); - } else if (DynamoDBUtil.AWS_STATUS_CODE_SERVICE_UNAVAILABLE == e.getStatusCode()) { - //retry after a small pause - DynamoDBUtil.sleepBeforeRetry(attempt); - attempt++; - updateItemInternal(tableName, key, attributes, attempt); - } else { - throw new DataStoreOperationException("problem with table: " + tableName + ", key: " + key + ", attributes: " + attributes, e); - } - } - } - - public void updateItemVersioned(String tableName, Key key, Map attributes, String expectedVersion, PersistentEntity persistentEntity) throws DataAccessException { - updateItemVersionedInternal(tableName, key, attributes, expectedVersion, persistentEntity, 1); - } - - private void updateItemVersionedInternal(String tableName, Key key, Map attributes, String expectedVersion, PersistentEntity persistentEntity, int attempt) throws DataAccessException { - UpdateItemRequest request = new UpdateItemRequest(tableName, key, attributes).withExpected(getOptimisticVersionCondition(expectedVersion)); - try { - ddb.updateItem(request); - } catch (AmazonServiceException e) { - if (DynamoDBUtil.AWS_ERR_CODE_CONDITIONAL_CHECK_FAILED.equals(e.getErrorCode())) { - throw new OptimisticLockingException(persistentEntity, key); - } else if (DynamoDBUtil.AWS_ERR_CODE_RESOURCE_NOT_FOUND.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such table: " + tableName, e); - } else if (DynamoDBUtil.AWS_STATUS_CODE_SERVICE_UNAVAILABLE == e.getStatusCode()) { - //retry after a small pause - DynamoDBUtil.sleepBeforeRetry(attempt); - attempt++; - updateItemVersionedInternal(tableName, key, attributes, expectedVersion, persistentEntity, attempt); - } else { - throw new DataStoreOperationException("problem with table: " + tableName + ", key: " + key + ", attributes: " + attributes, e); - } - } - } - - public void deleteItem(String tableName, Key key) { - deleteItemInternal(tableName, key, 1); - } - - private void deleteItemInternal(String tableName, Key key, int attempt) { - DeleteItemRequest request = new DeleteItemRequest(tableName, key); - try { - ddb.deleteItem(request); - } catch (AmazonServiceException e) { - if (DynamoDBUtil.AWS_ERR_CODE_RESOURCE_NOT_FOUND.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such table: " + tableName, e); - } else if (DynamoDBUtil.AWS_STATUS_CODE_SERVICE_UNAVAILABLE == e.getStatusCode()) { - //retry after a small pause - DynamoDBUtil.sleepBeforeRetry(attempt); - attempt++; - deleteItemInternal(tableName, key, attempt); - } else { - throw new DataStoreOperationException("problem with table: " + tableName + ", key: " + key, e); - } - } - } - - public boolean deleteAllItems(String tableName) throws DataAccessException { - ScanRequest request = new ScanRequest().withTableName(tableName); - boolean deleted = false; - ScanResult result = ddb.scan(request); - for (Map item : result.getItems()) { - Key key = DynamoDBUtil.getIdKey(item); - deleteItem(tableName, key); - deleted = true; - } - - //keep repeating until we get through all matched items - Key lastKeyEvaluated = null; - do { - lastKeyEvaluated = result.getLastEvaluatedKey(); - if (lastKeyEvaluated != null) { - request = new ScanRequest(tableName).withExclusiveStartKey(lastKeyEvaluated); - result = ddb.scan(request); - for (Map item : result.getItems()) { - Key key = DynamoDBUtil.getIdKey(item); - deleteItem(tableName, key); - deleted = true; - } - } - } while (lastKeyEvaluated != null); - - return deleted; - } - - public List> scan(String tableName, Map filter, int max) { - return scanInternal(tableName, filter, max, 1); - } - - private List> scanInternal(String tableName, Map filter, int max, int attempt) { - LinkedList> items = new LinkedList>(); - try { - ScanRequest request = new ScanRequest(tableName).withScanFilter(filter); - ScanResult result = ddb.scan(request); - items.addAll(result.getItems()); - - //keep repeating until we get through all matched items - Key lastKeyEvaluated = null; - do { - lastKeyEvaluated = result.getLastEvaluatedKey(); - if (lastKeyEvaluated != null) { - request = new ScanRequest(tableName).withScanFilter(filter).withExclusiveStartKey(lastKeyEvaluated); - result = ddb.scan(request); - items.addAll(result.getItems()); - } - } while (lastKeyEvaluated != null && items.size() < max); - - //truncate if needed - while (items.size() > max) { - items.removeLast(); - } - - return items; - } catch (AmazonServiceException e) { - if (DynamoDBUtil.AWS_ERR_CODE_RESOURCE_NOT_FOUND.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such table: " + tableName, e); - } else if (DynamoDBUtil.AWS_STATUS_CODE_SERVICE_UNAVAILABLE == e.getStatusCode()) { - //retry after a small pause - DynamoDBUtil.sleepBeforeRetry(attempt); - attempt++; - return scanInternal(tableName, filter, max, attempt); - } else { - throw new DataStoreOperationException("problem with table: " + tableName + ", filter: " + filter, e); - } - } - } - - public int scanCount(String tableName, Map filter) { - return scanCountInternal(tableName, filter, 1); - } - - private int scanCountInternal(String tableName, Map filter, int attempt) { - try { - ScanRequest request = new ScanRequest(tableName).withScanFilter(filter).withCount(true); - ScanResult result = ddb.scan(request); - int count = 0; - count = count + result.getCount(); - - //keep repeating until we get through all matched items - Key lastKeyEvaluated = null; - do { - lastKeyEvaluated = result.getLastEvaluatedKey(); - if (lastKeyEvaluated != null) { - request = new ScanRequest(tableName).withScanFilter(filter).withExclusiveStartKey(lastKeyEvaluated).withCount(true); - result = ddb.scan(request); - count = count + result.getCount(); - } - } while (lastKeyEvaluated != null); - - return count; - } catch (AmazonServiceException e) { - if (DynamoDBUtil.AWS_ERR_CODE_RESOURCE_NOT_FOUND.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such table: " + tableName, e); - } else if (DynamoDBUtil.AWS_STATUS_CODE_SERVICE_UNAVAILABLE == e.getStatusCode()) { - //retry after a small pause - DynamoDBUtil.sleepBeforeRetry(attempt); - attempt++; - return scanCountInternal(tableName, filter, attempt); - } else { - throw new DataStoreOperationException("problem with table: " + tableName + ", filter: " + filter, e); - } - } - } - - public void createTable(String tableName, KeySchema ks, ProvisionedThroughput provisionedThroughput) throws DataAccessException { - CreateTableRequest request = new CreateTableRequest() - .withTableName(tableName) - .withKeySchema(ks) - .withProvisionedThroughput(provisionedThroughput); - - try { - /*CreateTableResult result =*/ ddb.createTable(request); - //now we must wait until table is ACTIVE - TableDescription tableDescription = waitTillTableState(tableName, "ACTIVE"); - if (!"ACTIVE".equals(tableDescription.getTableStatus())) { - throw new DataStoreOperationException("could not create table " + tableName + ", current table description: " + tableDescription); - } - } catch (AmazonClientException e) { - throw new DataStoreOperationException("problem with table: " + tableName + ", key schema: " + ks + ", provisioned throughput: " + provisionedThroughput, e); - } - } - - public List listTables() throws DataAccessException { - ListTablesRequest request = new ListTablesRequest(); - try { - ListTablesResult result = ddb.listTables(request); - return result.getTableNames(); - } catch (AmazonClientException e) { - throw new DataStoreOperationException("", e); - } - } - - public TableDescription describeTable(String tableName) throws DataAccessException{ - TableDescription tableDescription = ddb.describeTable(new DescribeTableRequest().withTableName(tableName)).getTable(); - return tableDescription; - } - - public void deleteTable(String tableName) throws DataAccessException { - DeleteTableRequest request = new DeleteTableRequest(tableName); - try { - ddb.deleteTable(request); - try { - int attempt = 0; - TableDescription tableDescription = null; - do { - tableDescription = ddb.describeTable(new DescribeTableRequest().withTableName(tableName)).getTable(); - attempt++; - try { - Thread.sleep(200); - } catch (InterruptedException e) { - } - } while (attempt < 1000); - //if we got here it means there was no ResourceNotFoundException, so it was not deleted - throw new DataStoreOperationException("could not delete table " + tableName + ", current table description: " + tableDescription); - } catch (ResourceNotFoundException e) { - //this is good, it means table is actually deleted - return; - } - } catch (AmazonClientException e) { - throw new DataStoreOperationException("problem with table: " + tableName, e); - } - } - - protected Map getOptimisticVersionCondition(String expectedVersion) { - Map expectedMap = new HashMap(); - expectedMap.put("version", new ExpectedAttributeValue(new AttributeValue().withN(expectedVersion))); - return expectedMap; - } - - private TableDescription waitTillTableState(String tableName, String desiredState) { - int attempt = 0; - TableDescription tableDescription = null; - do { - tableDescription = ddb.describeTable(new DescribeTableRequest().withTableName(tableName)).getTable(); - attempt++; - try { - Thread.sleep(200); - } catch (InterruptedException e) { - } - } while (attempt < 1000 && !desiredState.equals(tableDescription.getTableStatus())); - return tableDescription; - } -} diff --git a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBUtil.java b/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBUtil.java deleted file mode 100644 index bf0efc84e..000000000 --- a/grails-datastore-dynamodb/src/main/groovy/org/grails/datastore/mapping/dynamodb/util/DynamoDBUtil.java +++ /dev/null @@ -1,287 +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.mapping.dynamodb.util; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.grails.datastore.mapping.dynamodb.DynamoDBDatastore; -import org.grails.datastore.mapping.dynamodb.config.DynamoDBDomainClassMappedForm; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.PersistentEntity; - -import com.amazonaws.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodb.model.Condition; -import com.amazonaws.services.dynamodb.model.Key; -import com.amazonaws.services.dynamodb.model.KeySchema; -import com.amazonaws.services.dynamodb.model.KeySchemaElement; -import com.amazonaws.services.dynamodb.model.ProvisionedThroughput; - -/** - * Simple util class for DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class DynamoDBUtil { - public static final String AWS_ERR_CODE_CONDITIONAL_CHECK_FAILED = "ConditionalCheckFailedException"; - public static final String AWS_ERR_CODE_RESOURCE_NOT_FOUND = "ResourceNotFoundException"; - public static final int AWS_STATUS_CODE_SERVICE_UNAVAILABLE = 503; - - /** - * If tableNamePrefix is not null returns prefixed table name. - * - * @param tableName - * @param tableNamePrefix - * @return prefixed table name - */ - public static String getPrefixedTableName(String tableNamePrefix, String tableName) { - if (tableNamePrefix != null) { - return tableNamePrefix + tableName; - } - return tableName; - } - - /** - * Returns mapped table name (*unprefixed*) for the specified @{link PersistentEntity}. - * - * @param entity - * @return mapped table name - */ - public static String getMappedTableName(PersistentEntity entity) { - @SuppressWarnings("unchecked") - ClassMapping classMapping = entity.getMapping(); - DynamoDBDomainClassMappedForm mappedForm = classMapping.getMappedForm(); - String entityFamily = getFamily(entity, mappedForm); - return entityFamily; - } - - private static String getFamily(PersistentEntity persistentEntity, DynamoDBDomainClassMappedForm mappedForm) { - String table = null; - if (mappedForm != null) { - table = mappedForm.getFamily(); - } - if (table == null) { - table = persistentEntity.getJavaClass().getSimpleName(); - } - return table; - } - - /** - * Returns ProvisionedThroughput for the specific entity, or uses default one if the entity does not define it - * - * @param entity - * @param datastore - * @return ProvisionedThroughput - */ - public static ProvisionedThroughput getProvisionedThroughput(PersistentEntity entity, DynamoDBDatastore datastore) { - @SuppressWarnings("unchecked") - ClassMapping classMapping = entity.getMapping(); - DynamoDBDomainClassMappedForm mappedForm = classMapping.getMappedForm(); - - Map throughput = mappedForm.getThroughput(); - - if (throughput == null || throughput.isEmpty()) { - return DynamoDBUtil.createDefaultProvisionedThroughput(datastore); - } - - Number read = (Number) throughput.get(DynamoDBConst.THROUGHPUT_READ_ATTRIBUTE_NAME); - if (read == null) { - read = datastore.getDefaultReadCapacityUnits(); // default value - } - - Number write = (Number) throughput.get(DynamoDBConst.THROUGHPUT_WRITE_ATTRIBUTE_NAME); - if (write == null) { - write = datastore.getDefaultWriteCapacityUnits(); // default value - } - - ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput(). - withReadCapacityUnits(read.longValue()). - withWriteCapacityUnits(write.longValue()); - return provisionedThroughput; - } - - /** - * Returns KeySchema for the specific entity. - * - * @param entity - * @param datastore - * @return KeySchema - */ - public static KeySchema getKeySchema(PersistentEntity entity, DynamoDBDatastore datastore) { - return DynamoDBUtil.createIdKeySchema(); //current implementation does not handle composite keys //TODO - } - - public static String getAttributeValue(Map item, String attributeName) { - AttributeValue av = item.get(attributeName); - if (av != null) { - return av.getS(); - } - return null; - } - - public static String getAttributeValueNumeric(Map item, String attributeName) { - AttributeValue av = item.get(attributeName); - if (av != null) { - return av.getN(); - } - return null; - } - - public static List getAttributeValues(Map item, String attributeName) { - AttributeValue av = item.get(attributeName); - if (av != null) { - return av.getSS(); - } - return null; - } - - public static List collectIds(List> items) { - if (items.isEmpty()) { - return Collections.emptyList(); - } - - List ids = new LinkedList(); - for (Map item : items) { - ids.add(getAttributeValue(item, "id")); - } - return ids; - } - - /** - * Used in case we need to re-submit request to AWS when it throws 'AWS Error Code: ServiceUnavailable, AWS Error Message: Service AmazonDynamoDB is currently unavailable. Please try again ' - * - * @param attemptNumber - */ - public static void sleepBeforeRetry(int attemptNumber) { - long sleepMS; - if (attemptNumber < 5) { - sleepMS = 100; - } else if (attemptNumber < 10) { - sleepMS = 1000; - } else if (attemptNumber < 15) { - sleepMS = 5000; - } else if (attemptNumber < 20) { - sleepMS = 30000; - } else { - sleepMS = 60000; - } - try { - Thread.sleep(sleepMS); - } catch (InterruptedException e) { - } - } - - public static Key getIdKey(Map item) { - //todo - this currently works with non-ranged keys only - return new Key(item.get("id")); - } - - public static Key createIdKey(String id) { - return new Key(new AttributeValue("id").withS(id)); - } - - public static KeySchema createIdKeySchema() { - KeySchemaElement hashKey = new KeySchemaElement().withAttributeName("id").withAttributeType("S"); - KeySchema ks = new KeySchema().withHashKeyElement(hashKey); - return ks; - } - - public static ProvisionedThroughput createDefaultProvisionedThroughput(DynamoDBDatastore datastore) { - ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput(). - withReadCapacityUnits(datastore.getDefaultReadCapacityUnits()). - withWriteCapacityUnits(datastore.getDefaultWriteCapacityUnits()); - return provisionedThroughput; - } - - public static void addId(Map item, String id) { - item.put("id", new AttributeValue().withS(id)); - } - - public static void addAttributeValue(Collection attributeValues, String stringValue, boolean isNumber) { - attributeValues.add(createAttributeValue(stringValue, isNumber)); - } - - public static AttributeValue createAttributeValue(String stringValue, boolean isNumber) { - if (isNumber) { - return new AttributeValue().withN(stringValue); - } else { - return new AttributeValue().withS(stringValue); - } - } - - /* - when toCombinate is [ - [ [a],[b] ], - [ [c],[d] ] - ] - returns [ [a,c], [a,d], [b,c], [b,d] ] - */ - public static List> combinate(List>> toCombinate) { - if (toCombinate.isEmpty()) { - return Collections.emptyList(); - } else if (toCombinate.size() == 1) { - return toCombinate.get(0); - } else { - return recursiveCombine(toCombinate, 0); - } - } - - private static List> recursiveCombine(List>> toCombinate, int index) { - if (index == toCombinate.size() - 1) { - //this is leaf, just return what we got at this position - return new ArrayList>(toCombinate.get(index)); - } else { - List> next = recursiveCombine(toCombinate, index + 1); - //now combinate with each element in my list - List> result = new ArrayList>(); - List> currentContainer = toCombinate.get(index); //[ [a],[b] ] - for (List current : currentContainer) { - for (List n : next) { - List temp = new ArrayList(n); - temp.addAll(current); - result.add(temp); - } - } - return result; - } - } - - /** - * @param filter - * @param key - * @param operator - * @param stringValue - * @param isNumber - */ - public static void addSimpleComparison(Map filter, String key, String operator, String stringValue, boolean isNumber) { - checkFilterForExistingKey(filter, key); - if (isNumber) { - filter.put(key, new Condition().withComparisonOperator(operator).withAttributeValueList(new AttributeValue().withN(stringValue))); - } else { - filter.put(key, new Condition().withComparisonOperator(operator).withAttributeValueList(new AttributeValue().withS(stringValue))); - } - } - - public static void checkFilterForExistingKey(Map filter, String key) { - if (filter.containsKey(key)) { - throw new IllegalArgumentException("DynamoDB allows only a single filter condition per attribute. You are trying to use more than one condition for attribute: " + key); - } - } -} diff --git a/grails-datastore-gemfire/build.gradle b/grails-datastore-gemfire/build.gradle deleted file mode 100644 index 7549d8efd..000000000 --- a/grails-datastore-gemfire/build.gradle +++ /dev/null @@ -1,16 +0,0 @@ -version = "1.0.0.BUILD-SNAPSHOT" - -repositories { - maven { url "http://dist.gemstone.com/maven/release" } -} - -dependencies { - compile project(":grails-datastore-core") - compile('org.springframework.data.gemfire:spring-gemfire:1.0.1.RELEASE') { - exclude module:'spring-context' - exclude module:'spring-tx' - } - compile('com.gemstone.gemfire:gemfire:6.5.1.4') { - exclude module:'antlr' - } -} diff --git a/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/GemfireDatastore.java b/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/GemfireDatastore.java deleted file mode 100644 index 0622e5266..000000000 --- a/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/GemfireDatastore.java +++ /dev/null @@ -1,335 +0,0 @@ -/* Copyright (C) 2010 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.mapping.gemfire; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.model.DatastoreConfigurationException; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.data.gemfire.CacheFactoryBean; -import org.springframework.data.gemfire.GemfireTemplate; -import org.springframework.data.gemfire.RegionFactoryBean; - -import com.gemstone.gemfire.cache.AttributesFactory; -import com.gemstone.gemfire.cache.Cache; -import com.gemstone.gemfire.cache.DataPolicy; -import com.gemstone.gemfire.cache.Region; -import com.gemstone.gemfire.cache.Scope; -import com.gemstone.gemfire.cache.client.Pool; -import com.gemstone.gemfire.cache.query.CqQuery; -import com.gemstone.gemfire.cache.query.Index; -import com.gemstone.gemfire.cache.query.IndexExistsException; -import com.gemstone.gemfire.cache.query.IndexNameConflictException; -import com.gemstone.gemfire.cache.query.IndexType; -import com.gemstone.gemfire.cache.query.QueryService; - -/** - * Implementation of the {@link org.grails.datastore.mapping.core.Datastore} interface - * that maps entities into Gemfire regions. - * - * @since 1.0 - * @author Graeme Rocher - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class GemfireDatastore extends AbstractDatastore implements InitializingBean, DisposableBean, MappingContext.Listener { - - protected Cache gemfireCache; - protected Pool gemfirePool; - protected Map gemfireTemplates = new ConcurrentHashMap(); - protected Collection continuousQueries = new ConcurrentLinkedQueue(); - - public static final String SETTING_CACHE_XML = "cacheXml"; - public static final String SETTING_PROPERTIES = "properties"; - - public GemfireDatastore(MappingContext mappingContext, Map connectionDetails, - ConfigurableApplicationContext ctx) { - super(mappingContext, connectionDetails != null ? connectionDetails : Collections.emptyMap(), ctx); - - mappingContext.addMappingContextListener(this); - } - - public GemfireDatastore(MappingContext mappingContext, ConfigurableApplicationContext ctx) { - this(mappingContext, Collections.emptyMap(), ctx); - } - - public GemfireDatastore(MappingContext mappingContext, Cache gemfireCache, ConfigurableApplicationContext ctx) { - this(mappingContext, Collections.emptyMap(), ctx); - this.gemfireCache = gemfireCache; - } - - public void setGemfirePool(Pool gemfirePool) { - this.gemfirePool = gemfirePool; - } - - public Pool getGemfirePool() { - return gemfirePool; - } - - protected void initializeRegions(Cache cache, MappingContext context) throws Exception { - for (PersistentEntity entity : context.getPersistentEntities()) { - Region region = initializeRegion(cache, entity); - initializeIndices(cache, entity, region); - } - } - - protected void initializeIndices(Cache cache, PersistentEntity entity, Region region) throws Exception { - final List properties = entity.getPersistentProperties(); - - final QueryService queryService = cache.getQueryService(); - String entityName = entity.getDecapitalizedName(); - final String idName = entity.getIdentity().getName(); - - org.grails.datastore.mapping.gemfire.config.Region mappedRegion = getMappedRegionInfo(entity); - - final Collection indices = queryService.getIndexes(region); - final String indexName = entityName + "PrimaryKeyIndex"; - - if (!checkIndexExists(indices, indexName)) { - try { - queryService.createIndex(indexName, IndexType.PRIMARY_KEY, idName, mappedRegion != null && mappedRegion.getRegion() != null ? - "/" + mappedRegion.getRegion() : "/"+entityName); - } - catch (IndexExistsException e) { - // ignore - } - catch(IndexNameConflictException e) { - // ignore - } - } - - for (PersistentProperty property : properties) { - final boolean indexed = isIndexed(property) && Comparable.class.isAssignableFrom(property.getType()); - - if (indexed) { - final String propertyIndexName = entityName + property.getCapitilizedName() + "Index"; - if (!checkIndexExists(indices, propertyIndexName)) { - try { - queryService.createIndex(propertyIndexName, IndexType.FUNCTIONAL,property.getName(), "/"+entityName); - } - catch (IndexExistsException e) { - // ignore - } - catch(IndexNameConflictException e) { - // ignore - } - } - } - } - } - - private boolean checkIndexExists(Collection indices, String indexName) { - if (indices == null) { - return false; - } - - for (Index index : indices) { - if (index.getName().equals(indexName)) { - return true; - } - } - - return false; - } - - protected Region initializeRegion(Cache cache, PersistentEntity entity) throws Exception { - - org.grails.datastore.mapping.gemfire.config.Region mappedRegion = getMappedRegionInfo(entity); - - final boolean hasMappedRegion = mappedRegion != null; - String regionName; - if (hasMappedRegion && mappedRegion.getRegion() != null) { - regionName = mappedRegion.getRegion(); - } - else { - regionName = entity.getDecapitalizedName(); - } - - Region region = cache.getRegion(regionName); - - if (region == null) { - RegionFactoryBean regionFactory = new RegionFactoryBean(); - regionFactory.setCache(cache); - - regionFactory.setName(regionName); - if (gemfirePool != null) { - AttributesFactory factory = new AttributesFactory(); - factory.setScope(Scope.LOCAL); - factory.setPoolName(gemfirePool.getName()); - regionFactory.setAttributes(factory.create()); - } - else { - if (hasMappedRegion && mappedRegion.getDataPolicy() != null) { - regionFactory.setDataPolicy(mappedRegion.getDataPolicy()); - } - else { - regionFactory.setDataPolicy(DataPolicy.PARTITION); - } - if (hasMappedRegion && mappedRegion.getRegionAttributes() != null) { - regionFactory.setAttributes(mappedRegion.getRegionAttributes()); - } - if (hasMappedRegion && mappedRegion.getCacheListeners() != null) { - regionFactory.setCacheListeners(mappedRegion.getCacheListeners()); - } - if (hasMappedRegion && mappedRegion.getCacheLoader() != null) { - regionFactory.setCacheLoader(mappedRegion.getCacheLoader()); - } - if (hasMappedRegion && mappedRegion.getCacheWriter() != null) { - regionFactory.setCacheWriter(mappedRegion.getCacheWriter()); - } - } - - regionFactory.afterPropertiesSet(); - region = regionFactory.getObject(); - if (gemfirePool != null) { - region.registerInterest("ALL_KEYS"); - } - } - - gemfireTemplates.put(entity, new GemfireTemplate(region) /*{ - @Override - public T execute(GemfireCallback action) throws DataAccessException { - long now = System.currentTimeMillis(); - try { - return super.execute(action); - } finally { - System.out.println("Gemfire query took " + (System.currentTimeMillis() - now) + "ms"); - } - } - }*/); - return region; - } - - private org.grails.datastore.mapping.gemfire.config.Region getMappedRegionInfo(PersistentEntity entity) { - final Object mappedForm = entity.getMapping().getMappedForm(); - - org.grails.datastore.mapping.gemfire.config.Region mappedRegion = null; - if (mappedForm instanceof org.grails.datastore.mapping.gemfire.config.Region) { - mappedRegion = (org.grails.datastore.mapping.gemfire.config.Region) mappedForm; - } - return mappedRegion; - } - - public Cache getGemfireCache() { - return gemfireCache; - } - - public void addContinuousQuery(CqQuery query) { - continuousQueries.add(query); - } - - /** - * Obtains the template used to query data for a particular entity - * - * @param entity The entity to use - * @return The template - */ - public GemfireTemplate getTemplate(PersistentEntity entity) { - return gemfireTemplates.get(entity); - } - - /** - * Obtains the template used to query data for a particular entity - * - * @param entity The entity to use - * @return The template - */ - public GemfireTemplate getTemplate(Class entity) { - final PersistentEntity e = getMappingContext().getPersistentEntity(entity.getName()); - return e == null ? null : gemfireTemplates.get(e); - } - - @Override - protected Session createSession(Map connDetails) { - return new GemfireSession(this, mappingContext, getApplicationEventPublisher()); - } - - public void destroy() throws Exception { - super.destroy(); - if (gemfireCache == null) { - return; - } - - gemfireCache.close(); - for (CqQuery continuousQuery : continuousQueries) { - continuousQuery.close(); - } - continuousQueries.clear(); - } - - public void afterPropertiesSet() throws Exception { - CacheFactoryBean cacheFactory = new CacheFactoryBean(); - if (connectionDetails != null) { - if (connectionDetails.containsKey(SETTING_CACHE_XML)) { - Object entry = connectionDetails.remove(SETTING_CACHE_XML); - if (entry instanceof Resource) { - cacheFactory.setCacheXml((Resource) entry); - } - else { - cacheFactory.setCacheXml(new ClassPathResource(entry.toString())); - } - } - - if (connectionDetails.containsKey(SETTING_PROPERTIES)) { - Object entry = connectionDetails.get(SETTING_PROPERTIES); - if (entry instanceof Properties) { - cacheFactory.setProperties((Properties) entry); - } - else if (entry instanceof Map) { - final Properties props = new Properties(); - props.putAll((Map)entry); - cacheFactory.setProperties(props); - } - } - } - - try { - if (gemfireCache == null) { - cacheFactory.afterPropertiesSet(); - gemfireCache = cacheFactory.getObject(); - } - initializeRegions(gemfireCache, mappingContext); - initializeConverters(mappingContext); - } catch (Exception e) { - throw new DatastoreConfigurationException("Failed to configure Gemfire cache and regions: " + - e.getMessage(), e); - } - } - - public void persistentEntityAdded(PersistentEntity entity) { - try { - Region region = initializeRegion(gemfireCache, entity); - initializeIndices(gemfireCache, entity, region); - } catch (Exception e) { - throw new DatastoreConfigurationException( - "Failed to configure Gemfire cache and regions for entity [" + entity + - "]: " + e.getMessage(), e); - } - } -} diff --git a/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/GemfireSession.java b/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/GemfireSession.java deleted file mode 100644 index cbe217c4b..000000000 --- a/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/GemfireSession.java +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2010 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.mapping.gemfire; - -import org.springframework.context.ApplicationEventPublisher; -import org.grails.datastore.mapping.core.AbstractSession; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.gemfire.engine.GemfireEntityPersister; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.transactions.Transaction; - -import com.gemstone.gemfire.cache.Cache; -import com.gemstone.gemfire.cache.CacheTransactionManager; - -/** - * Implementation of the {@link org.grails.datastore.mapping.core.Session} interface - * that interacts with a Gemfire cache implementation - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class GemfireSession extends AbstractSession { - public GemfireSession(GemfireDatastore datastore, MappingContext mappingContext, - ApplicationEventPublisher publisher) { - super(datastore, mappingContext, publisher); - } - - @Override - protected Persister createPersister(Class cls, MappingContext mappingContext) { - final PersistentEntity entity = mappingContext.getPersistentEntity(cls.getName()); - return entity == null ? null : new GemfireEntityPersister(mappingContext, entity, this, publisher); - } - - @Override - protected Transaction beginTransactionInternal() { - GemfireDatastore datastore = (GemfireDatastore) getDatastore(); - final CacheTransactionManager tm = datastore.getGemfireCache().getCacheTransactionManager(); - tm.begin(); - return new GemfireTransaction(tm); - } - - // TODO: Support Client Caches, here we assume a peer cache -// public boolean isConnected() {} - - public Object getNativeInterface() { - return ((GemfireDatastore)getDatastore()).getGemfireCache(); - } - - private class GemfireTransaction implements Transaction { - - private CacheTransactionManager transactionManager; - - public GemfireTransaction(CacheTransactionManager transactionManager) { - this.transactionManager = transactionManager; - } - - public void commit() { - transactionManager.commit(); - } - - public void rollback() { - transactionManager.rollback(); - } - - public CacheTransactionManager getNativeTransaction() { - return transactionManager; - } - - public boolean isActive() { - return transactionManager.exists(); - } - - public void setTimeout(int timeout) { - // noop - } - } -} diff --git a/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/config/GormGemfireMappingFactory.java b/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/config/GormGemfireMappingFactory.java deleted file mode 100644 index a9fbbf921..000000000 --- a/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/config/GormGemfireMappingFactory.java +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright (C) 2010 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.mapping.gemfire.config; - -import groovy.lang.Closure; - -import org.grails.datastore.mapping.config.groovy.MappingConfigurationBuilder; -import org.grails.datastore.mapping.keyvalue.mapping.config.Family; -import org.grails.datastore.mapping.keyvalue.mapping.config.GormKeyValueMappingFactory; -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValue; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; - -import com.gemstone.gemfire.cache.AttributesFactory; -import com.gemstone.gemfire.cache.DataPolicy; -import com.gemstone.gemfire.cache.RegionAttributes; - -/** - * Allows GORM-style configuration of how an entity maps to a - * Gemfire region. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class GormGemfireMappingFactory extends GormKeyValueMappingFactory { - - private DataPolicy defaultDataPolicy = DataPolicy.PARTITION; - - public GormGemfireMappingFactory() { - super("Gemfire"); - } - - public void setDefaultDataPolicy(DataPolicy defaultDataPolicy) { - this.defaultDataPolicy = defaultDataPolicy; - } - - @Override - @SuppressWarnings({"rawtypes", "unchecked"}) - public Family createMappedForm(PersistentEntity entity) { - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass()); - final Closure value = cpf.getStaticPropertyValue(GormProperties.MAPPING, Closure.class); - if (value == null) { - return new Region(); - } - - final Region family = new Region(); - AttributesFactory factory = new AttributesFactory() { - @SuppressWarnings("unused") - public void setRegion(String name) { - family.setRegion(name); - } - }; - factory.setDataPolicy(defaultDataPolicy); - - MappingConfigurationBuilder builder = new MappingConfigurationBuilder(factory, KeyValue.class); - builder.evaluate(value); - entityToPropertyMap.put(entity, builder.getProperties()); - final RegionAttributes regionAttributes = factory.create(); - family.setRegionAttributes(regionAttributes); - family.setCacheListeners(regionAttributes.getCacheListeners()); - family.setDataPolicy(regionAttributes.getDataPolicy()); - family.setCacheLoader(regionAttributes.getCacheLoader()); - family.setCacheWriter(regionAttributes.getCacheWriter()); - - builder = new MappingConfigurationBuilder(family, KeyValue.class); - builder.evaluate(value); - return family; - } -} diff --git a/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/config/Region.java b/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/config/Region.java deleted file mode 100644 index 12708301c..000000000 --- a/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/config/Region.java +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright (C) 2010 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.mapping.gemfire.config; - -import org.grails.datastore.mapping.keyvalue.mapping.config.Family; - -import com.gemstone.gemfire.cache.CacheListener; -import com.gemstone.gemfire.cache.CacheLoader; -import com.gemstone.gemfire.cache.CacheWriter; -import com.gemstone.gemfire.cache.DataPolicy; -import com.gemstone.gemfire.cache.RegionAttributes; - -/** - * Configures a Gemfire region - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class Region extends Family { - - private RegionAttributes regionAttributes; - private CacheListener[] cacheListeners; - private CacheLoader cacheLoader; - private CacheWriter cacheWriter; - private DataPolicy dataPolicy; - private String regionShortcut; - - public RegionAttributes getRegionAttributes() { - return regionAttributes; - } - - public String getRegionShortcut() { - return regionShortcut; - } - - public void setRegionShortcut(String regionShortcut) { - this.regionShortcut = regionShortcut; - } - - public void setRegion(String name) { - setFamily(name); - } - - public String getRegion() { return getFamily(); } - - public void setRegionAttributes(RegionAttributes regionAttributes) { - this.regionAttributes = regionAttributes; - } - - public CacheListener[] getCacheListeners() { - return cacheListeners; - } - - public void setCacheListeners(CacheListener[] cacheListeners) { - this.cacheListeners = cacheListeners; - } - - public CacheLoader getCacheLoader() { - return cacheLoader; - } - - public void setCacheLoader(CacheLoader cacheLoader) { - this.cacheLoader = cacheLoader; - } - - public CacheWriter getCacheWriter() { - return cacheWriter; - } - - public void setCacheWriter(CacheWriter cacheWriter) { - this.cacheWriter = cacheWriter; - } - - public DataPolicy getDataPolicy() { - return dataPolicy; - } - - public void setDataPolicy(DataPolicy dataPolicy) { - this.dataPolicy = dataPolicy; - } -} diff --git a/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/engine/GemfireEntityPersister.java b/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/engine/GemfireEntityPersister.java deleted file mode 100644 index a8f4a6d26..000000000 --- a/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/engine/GemfireEntityPersister.java +++ /dev/null @@ -1,543 +0,0 @@ -/* Copyright (C) 2010 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.mapping.gemfire.engine; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Lock; - -import javax.persistence.CascadeType; - -import org.grails.datastore.mapping.core.OptimisticLockingException; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.LockableEntityPersister; -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; -import org.grails.datastore.mapping.engine.event.PreDeleteEvent; -import org.grails.datastore.mapping.engine.event.PreInsertEvent; -import org.grails.datastore.mapping.engine.event.PreUpdateEvent; -import org.grails.datastore.mapping.gemfire.GemfireDatastore; -import org.grails.datastore.mapping.gemfire.GemfireSession; -import org.grails.datastore.mapping.gemfire.query.GemfireQuery; -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValue; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.model.types.OneToMany; -import org.grails.datastore.mapping.model.types.ToOne; -import org.grails.datastore.mapping.query.Query; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.dao.CannotAcquireLockException; -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.data.gemfire.GemfireCallback; -import org.springframework.data.gemfire.GemfireTemplate; - -import com.gemstone.gemfire.GemFireCheckedException; -import com.gemstone.gemfire.GemFireException; -import com.gemstone.gemfire.cache.Cache; -import com.gemstone.gemfire.cache.CacheFactory; -import com.gemstone.gemfire.cache.Region; -import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem; -import com.gemstone.gemfire.internal.cache.PartitionedRegion; - -/** - * A persister capable of storing objects in a Gemfire region. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class GemfireEntityPersister extends LockableEntityPersister { - - private GemfireDatastore gemfireDatastore; - private Map distributedLocksHeld = new ConcurrentHashMap(); - private static AtomicInteger identifierGenerator = new AtomicInteger(0); - - public GemfireEntityPersister(MappingContext mappingContext, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher) { - super(mappingContext, entity, session, publisher); - this.gemfireDatastore = (GemfireDatastore) session.getDatastore(); - } - - @Override - public Object lock(final Serializable id) throws CannotAcquireLockException { - final GemfireTemplate template = gemfireDatastore.getTemplate(getPersistentEntity()); - - return template.execute(new GemfireCallback() { - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - final Lock lock = region.getDistributedLock(id); - lock.lock(); - final Object o = region.get(id); - distributedLocksHeld.put(o, lock); - return o; - } - }); - } - - @Override - public Object lock(final Serializable id, final int timeout) throws CannotAcquireLockException { - final GemfireTemplate template = gemfireDatastore.getTemplate(getPersistentEntity()); - - return template.execute(new GemfireCallback() { - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - final Lock lock = region.getDistributedLock(id); - try { - if (lock.tryLock(timeout, TimeUnit.SECONDS)) { - final Object o = region.get(id); - distributedLocksHeld.put(o, lock); - return o; - } - throw new CannotAcquireLockException("Timeout acquiring Gemfire lock on object type ["+getPersistentEntity()+"] with identifier ["+id+"]"); - } catch (InterruptedException e) { - throw new CannotAcquireLockException("Cannot acquire Gemfire lock on object type ["+getPersistentEntity()+"] with identifier ["+id+"]: " + e.getMessage(), e); - } - } - }); - } - - @Override - public boolean isLocked(Object o) { - return distributedLocksHeld.containsKey(o); - } - - @Override - public void unlock(Object o) { - final Lock lock = distributedLocksHeld.get(o); - if (lock != null) { - lock.unlock(); - } - } - - @Override - protected List retrieveAllEntities(PersistentEntity persistentEntity, final Serializable[] keys) { - return retrieveAllEntities(persistentEntity, Arrays.asList(keys)); - } - - @Override - protected List retrieveAllEntities(final PersistentEntity persistentEntity, final Iterable keys) { - final GemfireTemplate template = gemfireDatastore.getTemplate(persistentEntity); - return (List) template.execute(new GemfireCallback() { - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - if (keys instanceof Collection) { - return getListOfValues(region.getAll((Collection) keys)); - } - Collection keyList = new ArrayList(); - for (Serializable key : keys) { - keyList.add(key); - } - return getListOfValues(region.getAll(keyList)); - } - - List getListOfValues(final Map all) { - if (all != null) { - Collection nativeEntries = all.values(); - List values = new ArrayList(nativeEntries.size()); - for (Object entry : nativeEntries) { - values.add(handleDatastoreLoad(persistentEntity, entry)); - } - return values; - } - return Collections.emptyList(); - } - }); - } - - @Override - protected List persistEntities(final PersistentEntity persistentEntity, Iterable objs) { - final GemfireTemplate template = gemfireDatastore.getTemplate(persistentEntity); - final Map putMap = new HashMap(); - List identifiers = new ArrayList(); - final Map entityAccessObjects = new HashMap(); - - final Map updates = new HashMap(); - for (Object obj : objs) { - final EntityAccess access = createEntityAccess(persistentEntity,obj); - entityAccessObjects.put(obj, access); - Object identifier = access.getIdentifier(); - boolean isUpdate = true; - if (identifier == null) { - identifier = generateIdentifier(persistentEntity, access); - isUpdate = false; - } - - AbstractPersistenceEvent event = isUpdate ? - new PreUpdateEvent(session.getDatastore(), persistentEntity, access) : - new PreInsertEvent(session.getDatastore(), persistentEntity, access); - updates.put(obj, isUpdate); - publisher.publishEvent(event); - if (event.isCancelled()) { - break; - } - - putMap.put(identifier, obj); - identifiers.add((Serializable) identifier); - } - - template.execute(new GemfireCallback() { - - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - region.putAll(putMap); - - if (!persistentEntity.isRoot()) { - doWithParents(persistentEntity, new GemfireCallback() { - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - region.putAll(putMap); - return null; - } - }); - } - - for (Object id : putMap.keySet()) { - Object obj = putMap.get(id); - final EntityAccess access = entityAccessObjects.get(obj); - if (access != null) { - cascadeSaveOrUpdate(persistentEntity, obj, access); - if (updates.get(obj)) { - firePostUpdateEvent(persistentEntity, access); - } - else { - firePostInsertEvent(persistentEntity, access); - } - } - } - - return null; - } - }); - - return identifiers; - } - - @Override - protected Object retrieveEntity(final PersistentEntity persistentEntity, final Serializable key) { - - final GemfireTemplate template = gemfireDatastore.getTemplate(persistentEntity); - return template.execute(new GemfireCallback() { - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - final Class idType = persistentEntity.getIdentity().getType(); - Object lookupKey = getMappingContext().getConversionService().convert(key, idType); - final Object entry = region.get(lookupKey); - - if (entry != null) { - return handleDatastoreLoad(persistentEntity, entry); - } - - return null; - } - }); - } - - /** - * Handle loading an event from store, including firing necessary events. - * @param persistentEntity The entity type - * @param entry The native entry taken from the store. - * @return The domain entity - */ - public Object handleDatastoreLoad(PersistentEntity persistentEntity, Object entry) { - final EntityAccess ea = createEntityAccess(persistentEntity, entry); - firePreLoadEvent(persistentEntity, ea); - for (Association association : persistentEntity.getAssociations()) { - if (association instanceof OneToMany) { - final String propertyName = association.getName(); - final Object currentState = ea.getProperty(propertyName); - if (currentState == null) { - initializeCollectionState(association, ea, propertyName); - } - } - } - firePostLoadEvent(persistentEntity, ea); - return entry; - } - - private Object initializeCollectionState(Association association, EntityAccess ea, String propertyName) { - if (Set.class.isAssignableFrom(association.getType())) { - final HashSet set = new HashSet(); - ea.setProperty(propertyName, set); - return set; - } - - if (List.class.isAssignableFrom(association.getType())) { - final ArrayList list = new ArrayList(); - ea.setProperty(propertyName, list); - return list; - } - - if (Map.class.isAssignableFrom(association.getType())) { - final HashMap map = new HashMap(); - ea.setProperty(propertyName, map); - return map; - } - - return null; - } - - @Override - protected Serializable persistEntity(final PersistentEntity persistentEntity, final Object obj) { - final EntityAccess access = createEntityAccess(persistentEntity,obj); - Object identifier = access.getIdentifier(); - boolean isUpdate = true; - if (identifier == null) { - identifier = generateIdentifier(persistentEntity, access); - isUpdate = false; - } - final Object finalId = identifier; - final GemfireTemplate template = gemfireDatastore.getTemplate(persistentEntity); - - final boolean finalIsUpdate = isUpdate; - template.execute(new GemfireCallback() { - - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - - AbstractPersistenceEvent event = finalIsUpdate ? - new PreUpdateEvent(session.getDatastore(), persistentEntity, access) : - new PreInsertEvent(session.getDatastore(), persistentEntity, access); - publisher.publishEvent(event); - if (event.isCancelled()) { - return finalId; - } - - if (finalIsUpdate && isVersioned(access)) { - // TODO this should be done with a CAS approach if possible - checkVersion(region, access, persistentEntity, finalId); - } - - region.put(finalId, obj); - if (!persistentEntity.isRoot()) { - doWithParents(persistentEntity, new GemfireCallback() { - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - region.put(finalId, obj); - return null; - } - }); - } - - cascadeSaveOrUpdate(persistentEntity, obj, access); - - if (finalIsUpdate) { - firePostUpdateEvent(persistentEntity, access); - } - else { - firePostInsertEvent(persistentEntity, access); - } - - return null; - } - }); - return (Serializable) identifier; - } - - protected void checkVersion(Region region, EntityAccess access, - PersistentEntity persistentEntity, Object id) { - - final Class idType = persistentEntity.getIdentity().getType(); - Object lookupKey = getMappingContext().getConversionService().convert(id, idType); - Object previous = region.get(lookupKey); - - Object oldVersion = new EntityAccess(persistentEntity, previous).getProperty("version"); - Object currentVersion = access.getProperty("version"); - if (Number.class.isAssignableFrom(access.getPropertyType("version"))) { - oldVersion = ((Number)oldVersion).longValue(); - currentVersion = ((Number)currentVersion).longValue(); - } - - if (oldVersion != null && currentVersion != null && !oldVersion.equals(currentVersion)) { - throw new OptimisticLockingException(persistentEntity, id); - } - - incrementVersion(access); - } - - private void cascadeSaveOrUpdate(PersistentEntity persistentEntity, Object obj, EntityAccess access) { - final List associations = persistentEntity.getAssociations(); - for (Association association : associations) { - if (association.doesCascade(CascadeType.PERSIST)) { - final Session session = getSession(); - String processKey = association + ">" + obj; - if (association instanceof ToOne) { - final Object associatedObject = access.getProperty(association.getName()); - - if (associatedObject != null && !associatedObject.equals(obj)) { - if (session.getAttribute(obj, processKey) == null) { - session.setAttribute(obj, processKey, true); - this.session.persist(associatedObject); - autoAssociateInverseSide(obj, association, associatedObject); - } - } - else { - session.setAttribute(obj, processKey, false); - } - } - else if (association instanceof OneToMany) { - if (session.getAttribute(obj, processKey) == Boolean.TRUE) { - session.setAttribute(obj, processKey, Boolean.TRUE); - Object associatedObjects = access.getProperty(association.getName()); - if (associatedObjects instanceof Iterable) { - final Iterable iterable = (Iterable) associatedObjects; - for (Object associatedObject : iterable) { - autoAssociateInverseSide(obj, association, associatedObject); - } - session.persist(iterable); - } - } - else { - session.setAttribute(obj, processKey, false); - } - } - } - } - } - - private void autoAssociateInverseSide(Object obj, Association association, Object associatedObject) { - if (association.isBidirectional()) { - final Association inverseSide = association.getInverseSide(); - if (inverseSide instanceof ToOne) { - final EntityAccess associationAccess = createEntityAccess(association.getAssociatedEntity(), associatedObject); - associationAccess.setProperty(inverseSide.getName(), obj); - } - else if (inverseSide instanceof OneToMany) { - final EntityAccess associationAccess = createEntityAccess(association.getAssociatedEntity(), associatedObject); - Object collectionObject = associationAccess.getProperty(inverseSide.getName()); - if (collectionObject == null) { - collectionObject = initializeCollectionState(inverseSide, associationAccess, inverseSide.getName()); - } - - if (collectionObject instanceof Collection) { - final Collection collection = (Collection) collectionObject; - if (!collection.contains(obj)) - collection.add(obj); - } - } - } - } - - private void cascadeDelete(PersistentEntity persistentEntity, Object obj, EntityAccess access) { - final List associations = persistentEntity.getAssociations(); - for (Association association : associations) { - if (association.doesCascade(CascadeType.REMOVE)) { - if (association instanceof ToOne) { - ToOne toOne = (ToOne) association; - - final Object associatedObject = access.getProperty(toOne.getName()); - if (associatedObject != null && !associatedObject.equals(obj)) { - session.delete(associatedObject); - } - } - else if (association instanceof OneToMany) { - Object associatedObjects = access.getProperty(association.getName()); - if (associatedObjects instanceof Iterable) { - session.delete((Iterable)associatedObjects); - } - } - } - } - } - - private void doWithParents(PersistentEntity persistentEntity, GemfireCallback gemfireCallback) { - if (!persistentEntity.isRoot()) { - PersistentEntity parentEntity = persistentEntity.getParentEntity(); - do { - GemfireTemplate parentTemplate = gemfireDatastore.getTemplate(parentEntity); - parentTemplate.execute(gemfireCallback); - parentEntity = parentEntity.getParentEntity(); - } - while(parentEntity != null && !(parentEntity.isRoot())); - } - } - - private Object generateIdentifier(final PersistentEntity persistentEntity, final EntityAccess access) { - final GemfireTemplate template = gemfireDatastore.getTemplate(persistentEntity); - return template.execute(new GemfireCallback() { - - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - - KeyValue mf = (KeyValue)gemfireDatastore.getMappingContext().getMappingFactory().createMappedForm(persistentEntity.getIdentity()); - if ("uuid".equals(mf.getGenerator())) { - String uuid = UUID.randomUUID().toString(); - access.setIdentifier(uuid); - return uuid; - } - - Cache cache = CacheFactory.getAnyInstance(); - final int uuid = PartitionedRegion.generatePRId( - (InternalDistributedSystem)cache.getDistributedSystem(),cache); - if (uuid == 0) { - throw new DataAccessResourceFailureException("Unable to generate Gemfire UUID"); - } - long finalId = identifierGenerator.getAndIncrement() + uuid; - access.setIdentifier(finalId); - return finalId; - } - }); - } - - @Override - protected void deleteEntity(final PersistentEntity persistentEntity, final Object obj) { - final EntityAccess access = createEntityAccess(persistentEntity, obj); - - final Object identifier = access.getIdentifier(); - final GemfireTemplate template = gemfireDatastore.getTemplate(persistentEntity); - - template.execute(new GemfireCallback() { - - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - PreDeleteEvent event = new PreDeleteEvent(session.getDatastore(), persistentEntity, access); - publisher.publishEvent(event); - if (event.isCancelled()) { - return null; - } - - region.remove(identifier); - if (!persistentEntity.isRoot()) { - doWithParents(persistentEntity, new GemfireCallback() { - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - region.remove(identifier); - return null; - } - }); - } - cascadeDelete(persistentEntity, obj, access); - firePostDeleteEvent(persistentEntity, access); - return null; - } - }); - } - - @Override - protected void deleteEntities(PersistentEntity persistentEntity, Iterable objects) { - for (Object object : objects) { - deleteEntity(persistentEntity, object); - } - } - - public Query createQuery() { - return new GemfireQuery((GemfireSession) getSession(), getPersistentEntity()); - } - - public Serializable refresh(Object o) { - return (Serializable)createEntityAccess(getPersistentEntity(), o).getIdentifier(); - } -} diff --git a/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/query/GemfireQuery.java b/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/query/GemfireQuery.java deleted file mode 100644 index a5edd2304..000000000 --- a/grails-datastore-gemfire/src/main/groovy/org/grails/datastore/mapping/gemfire/query/GemfireQuery.java +++ /dev/null @@ -1,561 +0,0 @@ -/* Copyright (C) 2010 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.mapping.gemfire.query; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.grails.datastore.mapping.gemfire.GemfireDatastore; -import org.grails.datastore.mapping.gemfire.GemfireSession; -import org.grails.datastore.mapping.gemfire.engine.GemfireEntityPersister; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.types.ToOne; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.order.ManualEntityOrdering; -import org.grails.datastore.mapping.query.projections.ManualProjections; -import org.springframework.dao.InvalidDataAccessResourceUsageException; -import org.springframework.data.gemfire.GemfireCallback; -import org.springframework.data.gemfire.GemfireTemplate; - -import com.gemstone.gemfire.GemFireCheckedException; -import com.gemstone.gemfire.GemFireException; -import com.gemstone.gemfire.cache.Region; -import com.gemstone.gemfire.cache.query.QueryService; -import com.gemstone.gemfire.cache.query.SelectResults; - -/** - *

    Adds query support for Gemfire. Note that due to limitations in the Gemfire API some operations - * are more expensive than in other stores.

    - * - *

    In particular Gemfire doesn't support native ORDER BY or OFFSET clauses hence these are handled manually by this - * implementation which results in some performance implications when ordering or offsets are used in queries.

    - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class GemfireQuery extends Query { - public static final String SELECT_CLAUSE = "SELECT "; - public static final String SELECT_DISTINCT = " DISTINCT "; - public static final String WHERE_CLAUSE = " WHERE "; - public static final String FROM_CLAUSE = " FROM /"; - public static final String LIMIT_CLAUSE = " LIMIT "; - public static final String NOT_CLAUSE = " NOT "; - public static final String LOGICAL_OR = " OR "; - private ManualEntityOrdering ordering; - private ManualProjections manualProjections; - private String regionName; - - private static interface QueryHandler { - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder query, List params, int index); - } - - private static Map queryHandlers = new HashMap(); - - public static final String GREATER_THAN_EQUALS = " >= "; - public static final String LESS_THAN_EQUALS = " <= "; - public static final String LOGICAL_AND = " AND "; - public static final String GREATER_THAN = " > "; - public static final String WILDCARD = " * "; - public static final char SPACE = ' '; - public static final char DOLLAR_SIGN = '$'; - public static final String LESS_THAN = " < "; - public static final String EQUALS = " = "; - public static final String NOT_EQUALS = " != "; - public static final String LIKE = " like "; - - static { - queryHandlers.put(Equals.class, new QueryHandler() { - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder q, List params, int index) { - Equals eq = (Equals) criterion; - final String name = eq.getProperty(); - validateProperty(entity, name, Equals.class); - - q.append(calculateName(entity, name)); - return appendOrEmbedValue(q, params, index, eq.getValue(), EQUALS); - } - }); - queryHandlers.put(IdEquals.class, new QueryHandler() { - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder q, List params, int index) { - IdEquals eq = (IdEquals) criterion; - String name = entity.getIdentity().getName(); - validateProperty(entity, name, Equals.class); - - q.append(calculateName(entity, name)); - return appendOrEmbedValue(q, params, index, eq.getValue(), EQUALS); - } - }); - queryHandlers.put(NotEquals.class, new QueryHandler() { - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder q, List params, int index) { - NotEquals eq = (NotEquals) criterion; - final String name = eq.getProperty(); - validateProperty(entity, name, NotEquals.class); - - q.append(calculateName(entity, name)); - return appendOrEmbedValue(q, params, index, eq.getValue(), NOT_EQUALS); - } - }); - queryHandlers.put(Like.class, new QueryHandler() { - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder q, List params, int index) { - Like eq = (Like) criterion; - final String name = eq.getProperty(); - validateProperty(entity, name, Like.class); - q.append(calculateName(entity, name)) - .append(" like '") - .append(eq.getValue()) - .append("' "); - -// params.add(eq.getValue()); - return index; - } - }); - - queryHandlers.put(In.class, new QueryHandler() { - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder q, List params, int index) { - In eq = (In) criterion; - final String name = eq.getProperty(); - validateProperty(entity, name, In.class); - q.append(calculateName(entity, name)) - .append(" IN SET ("); - - final Collection values = eq.getValues(); - for (Iterator iterator = values.iterator(); iterator.hasNext();) { - Object value = iterator.next(); - index = appendOrEmbedValue(q, params, index, value, ""); - if (iterator.hasNext()) q.append(","); - } - - q.append(") "); - - return index; - } - }); - queryHandlers.put(IsNull.class, new QueryHandler() { - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder q, List params, int index) { - IsNull eq = (IsNull) criterion; - final String name = eq.getProperty(); - validateProperty(entity, name, IsNull.class); - q.append(calculateName(entity, name)).append(" = NULL "); - - return index; - } - }); - queryHandlers.put(Disjunction.class, new QueryHandler() { - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder query, List params, int index) { - return buildWhereClause(entity, (Junction) criterion,query, index, params); - } - }); - queryHandlers.put(Conjunction.class, new QueryHandler() { - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder query, List params, int index) { - return buildWhereClause(entity, (Junction) criterion,query, index, params); - } - }); - queryHandlers.put(Negation.class, new QueryHandler() { - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder query, List params, int index) { - return buildWhereClause(entity, (Junction) criterion,query, index, params); - } - }); - - queryHandlers.put(Between.class, new QueryHandler() { - - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder q, List params, int index) { - Between eq = (Between) criterion; - final String name = eq.getProperty(); - validateProperty(entity, name, Between.class); - q.append("("); - final String calculatedName = calculateName(entity, name); - q.append(calculatedName); - - index = appendOrEmbedValue(q, params, index, eq.getFrom(), GREATER_THAN_EQUALS); - q.append(LOGICAL_AND) - .append(calculatedName); - - index = appendOrEmbedValue(q, params, index, eq.getTo(), LESS_THAN_EQUALS); - q.append(") "); - - return index; - } - }); - - queryHandlers.put(GreaterThan.class, new QueryHandler() { - - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder q, List params, int index) { - PropertyCriterion eq = (PropertyCriterion) criterion; - final String name = eq.getProperty(); - validateProperty(entity, name, GreaterThan.class); - q.append(calculateName(entity, name)); - return appendOrEmbedValue(q, params, index, eq.getValue(), GREATER_THAN); - } - }); - - queryHandlers.put(GreaterThanEquals.class, new QueryHandler() { - - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder q, List params, int index) { - PropertyCriterion eq = (PropertyCriterion) criterion; - final String name = eq.getProperty(); - validateProperty(entity, name, GreaterThanEquals.class); - q.append(calculateName(entity, name)); - return appendOrEmbedValue(q, params, index, eq.getValue(), GREATER_THAN_EQUALS); - } - }); - - queryHandlers.put(LessThanEquals.class, new QueryHandler() { - - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder q, List params, int index) { - PropertyCriterion eq = (PropertyCriterion) criterion; - final String name = eq.getProperty(); - validateProperty(entity, name, LessThanEquals.class); - q.append(calculateName(entity, name)); - return appendOrEmbedValue(q, params, index, eq.getValue(), LESS_THAN_EQUALS); - } - }); - - queryHandlers.put(LessThan.class, new QueryHandler() { - - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder q, List params, int index) { - PropertyCriterion eq = (PropertyCriterion) criterion; - final String name = eq.getProperty(); - validateProperty(entity, name, LessThan.class); - q.append(calculateName(entity, name)); - return appendOrEmbedValue(q, params, index, eq.getValue(), LESS_THAN); - } - }); - } - - private static int appendOrEmbedValue(StringBuilder q, List params, int index, Object value, String operator) { - if (params == null) { - q.append(operator); - appendValue(q, value); - q.append(SPACE); - } - else { - q.append(operator) - .append(DOLLAR_SIGN) - .append(++index) - .append(SPACE); - params.add(value); - } - return index; - } - - private static void appendValue(StringBuilder q, Object value) { - if (value instanceof Number || value instanceof Boolean) { - q.append(value); - } - else { - q.append(quote(value)); - } - } - - private static Object quote(Object value) { - return "'" + value + "'"; - } - - private static String calculateName(PersistentEntity entity, String name) { - final PersistentProperty prop = entity.getPropertyByName(name); - if (prop instanceof ToOne) { - ToOne association = (ToOne) prop; - final PersistentEntity associated = association.getAssociatedEntity(); - return name + "." + associated.getIdentity().getName(); - } - return name; - } - - private static void validateProperty(PersistentEntity entity, String name, Class criterionType) { - if (entity.getIdentity().getName().equals(name)) return; - PersistentProperty prop = entity.getPropertyByName(name); - if (prop == null) { - throw new InvalidDataAccessResourceUsageException("Cannot use ["+ criterionType.getSimpleName()+"] criterion on non-existent property: " + name); - } - } - - GemfireDatastore gemfireDatastore; - - public GemfireQuery(GemfireSession session, PersistentEntity entity) { - super(session, entity); - gemfireDatastore = (GemfireDatastore) session.getDatastore(); - this.ordering = new ManualEntityOrdering(entity); - this.manualProjections = new ManualProjections(entity); - final org.grails.datastore.mapping.gemfire.config.Region region = getMappedRegionInfo(entity); - - if (region != null && region.getRegion() != null) { - this.regionName = region.getRegion(); - } - else { - this.regionName = entity.getDecapitalizedName(); - } - } - - private org.grails.datastore.mapping.gemfire.config.Region getMappedRegionInfo(PersistentEntity entity) { - final Object mappedForm = entity.getMapping().getMappedForm(); - - org.grails.datastore.mapping.gemfire.config.Region mappedRegion = null; - if (mappedForm instanceof org.grails.datastore.mapping.gemfire.config.Region) { - mappedRegion = (org.grails.datastore.mapping.gemfire.config.Region) mappedForm; - } - return mappedRegion; - } - - @Override - protected List executeQuery(final PersistentEntity entity, Junction criteria) { - final ProjectionList projectionList = projections(); - if (criteria.isEmpty() && !(max > -1)) { - return (List) gemfireDatastore.getTemplate(entity).execute(new GemfireCallback() { - - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - - List finalResults; - if (projectionList.isEmpty()) { - finalResults = new ArrayList(region.values()); - } - else { - List results = new ArrayList(); - for (Projection projection : projectionList.getProjectionList()) { - Collection values = null; - if (projection instanceof CountProjection) { - results.add(region.size()); - } - else if (projection instanceof MinProjection) { - MinProjection min = (MinProjection) projection; - if (values == null) { - values = region.values(); - } - results.add(manualProjections.min(values, min.getPropertyName())); - } - else if (projection instanceof MaxProjection) { - if (values == null) { - values = region.values(); - } - MaxProjection maxProjection = (MaxProjection) projection; - results.add(manualProjections.max(values,maxProjection.getPropertyName())); - } - else if (projection instanceof IdProjection) { - results.add(region.keySet()); - } - else if (projection instanceof CountDistinctProjection) { - if (values == null) { - values = region.values(); - } - results.add(manualProjections.countDistinct(values, ((PropertyProjection) projection).getPropertyName())); - } - else if (projection.getClass() == PropertyProjection.class) { - if (values == null) { - values = region.values(); - } - final List propertyProjectionResults = manualProjections.property(values, ((PropertyProjection) projection).getPropertyName()); - if (projectionList.getProjectionList().size() == 1) { - results = propertyProjectionResults; - } - else { - results.add(propertyProjectionResults); - } - } - } - finalResults = results; - } - finalResults = ordering.applyOrder(finalResults, getOrderBy()); - return finalResults; - } - }); - } - - GemfireTemplate template = gemfireDatastore.getTemplate(entity); - final List params = new ArrayList(); - final String queryString = getQueryString(params, true); - - return (List) template.execute(new GemfireCallback() { - - public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { - - final QueryService queryService = gemfireDatastore.getGemfireCache().getQueryService(); - - final com.gemstone.gemfire.cache.query.Query gemfireQuery = queryService.newQuery(queryString); - - final Object result = gemfireQuery.execute(params.toArray()); - List finalResults = Collections.emptyList(); - if (projectionList.isEmpty()) { - if (result instanceof SelectResults) { - finalResults = ((SelectResults)result).asList(); - } - else { - finalResults = wrapResultInList(result); - } - handleAfterLoad(finalResults); - } - else { - if (result instanceof SelectResults) { - SelectResults selectResults = (SelectResults) result; - List resultList = selectResults.asList(); - finalResults = applyProjections(resultList, projectionList); - } - else { - finalResults = wrapResultInList(result); - } - } - - finalResults = ordering.applyOrder(finalResults, getOrderBy()); - - if (offset > 0 ) { - - final int resultSize = finalResults.size(); - if (offset > resultSize) { - finalResults = Collections.emptyList(); - } - else { - int end = resultSize; - if (max > -1) { - end = offset + max; - if (end > resultSize) { - end = resultSize; - } - } - finalResults = finalResults.subList(offset, end); - } - } - - return finalResults; - } - }); - } - - private void handleAfterLoad(List finalResults) { - for (Object o : finalResults) { - GemfireEntityPersister persister = (GemfireEntityPersister) getSession().getPersister(o); - if (persister != null) { - persister.handleDatastoreLoad(getEntity(), o); - } - } - } - - /** - * Obtains the query string with variables embedded within the Query - * @return The query string - */ - public String getQueryString() { - return getQueryString(null, false); - } - - protected String getQueryString(List params, boolean distinct) { - ProjectionList projectionList = projections(); - String select = SELECT_CLAUSE; - String from = FROM_CLAUSE + regionName; - String where = WHERE_CLAUSE; - - final StringBuilder q = new StringBuilder(); - q.append(select); - if (distinct) { - q.append(SELECT_DISTINCT); - } - if (projectionList.isEmpty()) { - q.append(WILDCARD); - } - else { - boolean modifiedQuery = false; - for (Projection projection : projectionList.getProjectionList()) { - if (projection instanceof IdProjection) { - if (modifiedQuery) { - q.append(','); - } - q.append(SPACE).append(entity.getIdentity().getName()); - modifiedQuery = true; - - } - else if (projection.getClass() == PropertyProjection.class) { - if (modifiedQuery) { - q.append(','); - } - - q.append(SPACE).append(((PropertyProjection)projection).getPropertyName()); - modifiedQuery = true; - } - } - - if (!modifiedQuery) { - q.append(WILDCARD); - } - else { - q.append(SPACE); - } - } - q.append(from); - - if (!criteria.isEmpty()) { - q.append(where); - buildWhereClause(entity, criteria, q, 0, params); - } - - if (max > 0 && offset == 0) { - q.append(LIMIT_CLAUSE).append(max); - } - - return q.toString(); - } - - private List applyProjections(List results, ProjectionList projections) { - List projectedResults = new ArrayList(); - for (Projection projection : projections.getProjectionList()) { - if (projection instanceof CountProjection) { - projectedResults.add(results.size()); - } - else if (projection instanceof MinProjection) { - MinProjection min = (MinProjection) projection; - projectedResults.add(manualProjections.min(results,min.getPropertyName())); - } - else if (projection instanceof MaxProjection) { - MaxProjection min = (MaxProjection) projection; - projectedResults.add(manualProjections.max(results,min.getPropertyName())); - } - } - if (projectedResults.isEmpty()) { - return results; - } - return projectedResults; - } - - private List wrapResultInList(Object result) { - List listResult = new ArrayList(); - listResult.add(result); - return listResult; - } - - private static int buildWhereClause(PersistentEntity entity, Junction criteria, StringBuilder q, int index, List params) { - final List criterionList = criteria.getCriteria(); - if (criteria instanceof Negation) { - q.append(NOT_CLAUSE); - } - q.append('('); - for (Iterator iterator = criterionList.iterator(); iterator.hasNext();) { - Criterion criterion = iterator.next(); - - final String operator = criteria instanceof Conjunction ? LOGICAL_AND : LOGICAL_OR; - QueryHandler qh = queryHandlers.get(criterion.getClass()); - if (qh != null) { - index = qh.handle(entity, criterion, q, params, index); - } - - if (iterator.hasNext()) { - q.append(operator); - } - } - q.append(')'); - return index; - } -} diff --git a/grails-datastore-gorm-dynamodb/build.gradle b/grails-datastore-gorm-dynamodb/build.gradle deleted file mode 100644 index c9b5d8b4c..000000000 --- a/grails-datastore-gorm-dynamodb/build.gradle +++ /dev/null @@ -1,37 +0,0 @@ -version = "0.1.2.BUILD-SNAPSHOT" - -configurations { - grails -} - -dependencies { - - grails("org.grails:grails-core:$grailsVersion") - grails("org.grails:grails-bootstrap:$grailsVersion") { - transitive = false - } - - compile project(":grails-datastore-gorm"), - project(":grails-datastore-gorm-plugin-support"), - project(":grails-datastore-dynamodb"), - project(":grails-datastore-core") - - testCompile project(":grails-datastore-gorm-test"), - project(":grails-datastore-gorm-tck") -} - -configurations { - compile.exclude module: "org.slf4j" - testCompile.exclude module: "org.slf4j" -} - -sourceSets { - main { - compileClasspath += configurations.grails - } -} - -//test { -// maxParallelForks = 4 -// forkEvery = 25 -//} diff --git a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/DynamoDBCriteriaBuilder.java b/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/DynamoDBCriteriaBuilder.java deleted file mode 100644 index 460904137..000000000 --- a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/DynamoDBCriteriaBuilder.java +++ /dev/null @@ -1,36 +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.dynamodb; - -import grails.gorm.CriteriaBuilder; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.query.Query; - -/** - * Extends the default CriteriaBuilder implementation. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -public class DynamoDBCriteriaBuilder extends CriteriaBuilder { - - public DynamoDBCriteriaBuilder(final Class targetClass, final Session session, final Query query) { - super(targetClass, session, query); - } - - public DynamoDBCriteriaBuilder(final Class targetClass, final Session session) { - super(targetClass, session); - } -} diff --git a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/DynamoDBGormEnhancer.groovy b/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/DynamoDBGormEnhancer.groovy deleted file mode 100644 index 006fe67c1..000000000 --- a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/DynamoDBGormEnhancer.groovy +++ /dev/null @@ -1,128 +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.dynamodb - -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBNativeItem -import org.grails.datastore.mapping.dynamodb.util.DynamoDBTemplate -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.core.SessionCallback -import org.grails.datastore.mapping.engine.EntityPersister -import org.springframework.transaction.PlatformTransactionManager - -/** - * GORM enhancer for DynamoDB. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -class DynamoDBGormEnhancer extends GormEnhancer { - - DynamoDBGormEnhancer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - DynamoDBGormEnhancer(Datastore datastore) { - this(datastore, null) - } - - protected GormStaticApi getStaticApi(Class cls) { - return new DynamoDBGormStaticApi(cls, datastore, getFinders()) - } - - protected GormInstanceApi getInstanceApi(Class cls) { - final api = new DynamoDBGormInstanceApi(cls, datastore) - api.failOnError = failOnError - return api - } -} - -class DynamoDBGormInstanceApi extends GormInstanceApi { - - DynamoDBGormInstanceApi(Class persistentClass, Datastore datastore) { - super(persistentClass, datastore) - } - - /** - * Allows subscript access to schemaless attributes. - * - * @param instance The instance - * @param name The name of the field - */ - void putAt(D instance, String name, value) { - if (instance.hasProperty(name)) { - instance.setProperty(name, value) - } - else { - getDbo(instance)?.put name, value, xx - } - } - - /** - * Allows subscript access to schemaless attributes. - * - * @param instance The instance - * @param name The name of the field - * @return the value - */ - def getAt(D instance, String name) { - if (instance.hasProperty(name)) { - return instance.getProperty(name) - } - - def dbo = getDbo(instance) - if (dbo != null && dbo.containsField(name)) { - return DynamoDBTemplate.get(name) - } - return null - } - - /** - * Return the DBObject instance for the entity - * - * @param instance The instance - * @return The NativeDynamoDBItem instance - */ - DynamoDBNativeItem getDbo(D instance) { - execute (new SessionCallback() { - DynamoDBNativeItem doInSession(Session session) { - - if (!session.contains(instance) && !instance.save()) { - throw new IllegalStateException( - "Cannot obtain DBObject for transient instance, save a valid instance first") - } - - EntityPersister persister = session.getPersister(instance) - def id = persister.getObjectIdentifier(instance) - return session.getCachedEntry(persister.getPersistentEntity(), id) - } - }) - } -} - -class DynamoDBGormStaticApi extends GormStaticApi { - DynamoDBGormStaticApi(Class persistentClass, Datastore datastore, List finders) { - super(persistentClass, datastore, finders) - } - - @Override - DynamoDBCriteriaBuilder createCriteria() { - return new DynamoDBCriteriaBuilder(persistentClass, datastore.currentSession) - } -} diff --git a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/bean/factory/DynamoDBDatastoreFactoryBean.groovy b/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/bean/factory/DynamoDBDatastoreFactoryBean.groovy deleted file mode 100644 index 8e51ed29d..000000000 --- a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/bean/factory/DynamoDBDatastoreFactoryBean.groovy +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (C) 2010 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.dynamodb.bean.factory - -import org.grails.datastore.mapping.dynamodb.DynamoDBDatastore - -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBNativeItem -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository -import org.grails.datastore.mapping.model.MappingContext -import org.springframework.beans.factory.FactoryBean -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware - -/** - * Factory bean for constructing a {@link org.grails.datastore.mapping.dynamodb.DynamoDBDatastore} instance. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ - -class DynamoDBDatastoreFactoryBean implements FactoryBean, ApplicationContextAware { - - MappingContext mappingContext - Map config = [:] - ApplicationContext applicationContext - TPCacheAdapterRepository cacheAdapterRepository - - DynamoDBDatastore getObject() { - - DynamoDBDatastore datastore = new DynamoDBDatastore(mappingContext, config, applicationContext, cacheAdapterRepository) - - applicationContext.addApplicationListener new DomainEventListener(datastore) - applicationContext.addApplicationListener new AutoTimestampEventListener(datastore) - - datastore.afterPropertiesSet() - datastore - } - - Class getObjectType() { DynamoDBDatastore } - - boolean isSingleton() { true } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/bean/factory/DynamoDBMappingContextFactoryBean.groovy b/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/bean/factory/DynamoDBMappingContextFactoryBean.groovy deleted file mode 100644 index 1ae9f528a..000000000 --- a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/bean/factory/DynamoDBMappingContextFactoryBean.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package org.grails.datastore.gorm.dynamodb.bean.factory - -import org.grails.datastore.gorm.bean.factory.AbstractMappingContextFactoryBean -import org.grails.datastore.mapping.dynamodb.config.DynamoDBMappingContext -import org.grails.datastore.mapping.model.MappingContext - -/** - * Factory bean for construction the DynamoDB MappingContext. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -class DynamoDBMappingContextFactoryBean extends AbstractMappingContextFactoryBean { - @Override - protected MappingContext createMappingContext() { - return new DynamoDBMappingContext() - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBApplicationContextConfigurer.groovy b/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBApplicationContextConfigurer.groovy deleted file mode 100644 index 2376fcdb8..000000000 --- a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBApplicationContextConfigurer.groovy +++ /dev/null @@ -1,185 +0,0 @@ -package org.grails.datastore.gorm.dynamodb.plugin.support - -import java.util.concurrent.CountDownLatch -import java.util.concurrent.Executor -import java.util.concurrent.Executors - -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty -import org.codehaus.groovy.grails.plugins.GrailsPluginManager -import org.grails.datastore.gorm.plugin.support.ApplicationContextConfigurer -import org.grails.datastore.mapping.dynamodb.DynamoDBDatastore -import org.grails.datastore.mapping.dynamodb.config.DynamoDBMappingContext -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBAssociationInfo -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBTableResolver -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBTableResolverFactory -import org.grails.datastore.mapping.dynamodb.util.DynamoDBConst -import org.grails.datastore.mapping.dynamodb.util.DynamoDBTemplate -import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher -import org.springframework.context.ConfigurableApplicationContext - -import com.amazonaws.services.dynamodb.model.KeySchema -import com.amazonaws.services.dynamodb.model.ProvisionedThroughput -import com.amazonaws.services.dynamodb.model.TableDescription - -class DynamoDBApplicationContextConfigurer extends ApplicationContextConfigurer { - - DynamoDBApplicationContextConfigurer() { - super("DynamoDB") - } - - @Override - void configure(ConfigurableApplicationContext ctx) { - super.configure(ctx) - - GrailsPluginManager pluginManager = ctx.pluginManager - GrailsApplication application = ctx.grailsApplication - - def dynamoDBDomainClasses = [] - dynamoDBDomainClassProcessor(application, pluginManager, { dc -> - dynamoDBDomainClasses.add(dc) //collect domain classes which are stored via DynamoDB - }) - - //explicitly register dynamodb domain classes with datastore - DynamoDBDatastore dynamoDBDatastore = ctx.dynamodbDatastore - DynamoDBMappingContext mappingContext = ctx.dynamodbMappingContext - - dynamoDBDomainClasses.each { domainClass -> - PersistentEntity entity = mappingContext.getPersistentEntity(domainClass.clazz.getName()) - dynamoDBDatastore.persistentEntityAdded(entity) - } - - def dynamoDBConfig = application.config?.grails?.dynamodb - //determine dbCreate flag and create/delete AWS tables if needed - handleDBCreate(dynamoDBConfig, - application, - dynamoDBDomainClasses, - mappingContext, - dynamoDBDatastore - ) //similar to JDBC datastore, do 'create' or 'drop-create' - } - - /** - * Iterates over all domain classes which are mapped with DynamoDB and passes them to the specified closure - */ - def dynamoDBDomainClassProcessor = { application, pluginManager, closure -> - def isHibernateInstalled = pluginManager.hasGrailsPlugin("hibernate") - for (dc in application.domainClasses) { - def cls = dc.clazz - def cpf = ClassPropertyFetcher.forClass(cls) - def mappedWith = cpf.getStaticPropertyValue(GrailsDomainClassProperty.MAPPING_STRATEGY, String) - if (mappedWith == DynamoDBConst.DYNAMO_DB_MAP_WITH_VALUE || (!isHibernateInstalled && mappedWith == null)) { - closure.call(dc) - } - } - } - - def handleDBCreate = { dynamoDBConfig, application, dynamoDBDomainClasses, mappingContext, dynamoDBDatastore -> - String dbCreate = dynamoDBConfig.dbCreate - boolean drop = false - boolean create = false - if ("drop-create" == dbCreate) { - drop = true - create = true - } else if ("create" == dbCreate) { - create = true - } else if ("drop" == dbCreate) { - drop = true - } - - //protection against accidental drop - boolean disableDrop = dynamoDBConfig.disableDrop - if (disableDrop && drop) { - throw new IllegalArgumentException("Value of disableDrop is " + disableDrop + " while dbCreate is " + - dbCreate + ". Throwing an exception to prevent accidental drop of the data") - } - - def numOfThreads = 10 //how many parallel threads are used to create dbCreate functionality in parallel, dynamo DB has a max of 10 concurrent threads - - Executor executor = Executors.newFixedThreadPool(numOfThreads) - - DynamoDBTemplate template = dynamoDBDatastore.getDynamoDBTemplate() - List existingTables = template.listTables() - DynamoDBTableResolverFactory resolverFactory = new DynamoDBTableResolverFactory() - CountDownLatch latch = new CountDownLatch(dynamoDBDomainClasses.size()) - - for (dc in dynamoDBDomainClasses) { - def domainClass = dc.clazz //explicitly declare local variable which we will be using from the thread - //do dynamoDB work in parallel threads for each domain class to speed things up - executor.execute({ - try { - PersistentEntity entity = mappingContext.getPersistentEntity(domainClass.getName()) - KeySchema keySchema = DynamoDBUtil.getKeySchema(entity, dynamoDBDatastore) - ProvisionedThroughput provisionedThroughput = DynamoDBUtil.getProvisionedThroughput(entity, dynamoDBDatastore) - - DynamoDBTableResolver tableResolver = resolverFactory.buildResolver(entity, dynamoDBDatastore) - def tables = tableResolver.getAllTablesForEntity() - tables.each { table -> - handleTable(dynamoDBDatastore, existingTables, table, drop, create, keySchema, provisionedThroughput) - //handle tables for associations - entity.getAssociations().each { association -> - DynamoDBAssociationInfo associationInfo = dynamoDBDatastore.getAssociationInfo(association) - if (associationInfo) { - handleTable(dynamoDBDatastore, existingTables, associationInfo.getTableName(), drop, create, keySchema, provisionedThroughput) - } - } - } - } finally { - latch.countDown() - } - }) - } - - //if needed, drop/create hilo id generator table - String hiloTableName = DynamoDBUtil.getPrefixedTableName(dynamoDBDatastore.getTableNamePrefix(), DynamoDBConst.ID_GENERATOR_HI_LO_TABLE_NAME) - handleTable(dynamoDBDatastore, existingTables, hiloTableName, drop, create, DynamoDBUtil.createIdKeySchema(), DynamoDBUtil.createDefaultProvisionedThroughput(dynamoDBDatastore)) - - latch.await() - executor.shutdown() - } - - def dropAndCreateTable(DynamoDBDatastore datastore, existingTables, tableName, KeySchema keySchema, ProvisionedThroughput throughput) { - if (existingTables.contains(tableName)) { - //in theory if the table already exists we just have to clear it - it is faster than dropping and re-creating it - //however, before we decide it is okay to clear we have to compare the throughput - if it has changed we actually have to - //re-create the table... - TableDescription tableDescription = datastore.getDynamoDBTemplate().describeTable(tableName) - if (tableDescription.getProvisionedThroughput().getReadCapacityUnits().equals(throughput.getReadCapacityUnits()) && - tableDescription.getProvisionedThroughput().getWriteCapacityUnits().equals(throughput.getWriteCapacityUnits())) { - //ok, just clear the data - datastore.getDynamoDBTemplate().deleteAllItems(tableName) //delete all items there - } else { - //have to drop and create it - datastore.getDynamoDBTemplate().deleteTable(tableName) - datastore.getDynamoDBTemplate().createTable(tableName, keySchema, throughput) - } - } else { - //create it - datastore.getDynamoDBTemplate().createTable(tableName, keySchema, throughput) - } - } - - def createTableIfDoesNotExist(DynamoDBDatastore datastore, existingTables, tableName, KeySchema keySchema, ProvisionedThroughput throughput) { - if (!existingTables.contains(tableName)) { - datastore.getDynamoDBTemplate().createTable(tableName, keySchema, throughput) - } - } - - def deleteTableIfExists(DynamoDBDatastore datastore, existingTables, tableName) { - if (existingTables.contains(tableName)) { - datastore.getDynamoDBTemplate().deleteTable(tableName) - } - } - - def handleTable(DynamoDBDatastore datastore, existingTables, tableName, boolean drop, boolean create, KeySchema keySchema, ProvisionedThroughput throughput) { - if (drop && create) { - dropAndCreateTable(datastore, existingTables, tableName, keySchema, throughput) - } else if (create) { - createTableIfDoesNotExist(datastore, existingTables, tableName, keySchema, throughput) - } else if (drop) { - deleteTableIfExists(datastore, existingTables, tableName) - } - } -} diff --git a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBMethodsConfigurer.groovy b/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBMethodsConfigurer.groovy deleted file mode 100644 index 747063d09..000000000 --- a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBMethodsConfigurer.groovy +++ /dev/null @@ -1,69 +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.dynamodb.plugin.support - -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.dynamodb.DynamoDBGormEnhancer -import org.grails.datastore.gorm.dynamodb.DynamoDBGormInstanceApi -import org.grails.datastore.gorm.dynamodb.DynamoDBGormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.plugin.support.DynamicMethodsConfigurer -import org.grails.datastore.mapping.core.Datastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * DynamoDB specific dynamic methods configurer. - * - * @author Roman Stepanenko based on Graeme Rocher - * @since 0.1 - */ -class DynamoDBMethodsConfigurer extends DynamicMethodsConfigurer{ - - DynamoDBMethodsConfigurer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { - return "DynamoDB" - } - - @Override - protected GormStaticApi createGormStaticApi(Class cls, List finders) { - return new DynamoDBGormStaticApi(cls, datastore, finders) - } - - @Override - protected GormInstanceApi createGormInstanceApi(Class cls) { - def api = new DynamoDBGormInstanceApi(cls, datastore) - api.failOnError = failOnError - api - } - - @Override - protected GormEnhancer createEnhancer() { - def ge - if (transactionManager == null) { - ge = new DynamoDBGormEnhancer(datastore) - } - else { - ge = new DynamoDBGormEnhancer(datastore, transactionManager) - } - ge.failOnError = failOnError - ge - } -} diff --git a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBOnChangeHandler.groovy b/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBOnChangeHandler.groovy deleted file mode 100644 index 632295e06..000000000 --- a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBOnChangeHandler.groovy +++ /dev/null @@ -1,34 +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.dynamodb.plugin.support - -import org.grails.datastore.gorm.plugin.support.OnChangeHandler -import org.grails.datastore.mapping.core.Datastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * On change handler for DynamoDB - */ -class DynamoDBOnChangeHandler extends OnChangeHandler{ - - DynamoDBOnChangeHandler(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { - return "DynamoDB" - } -} diff --git a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBSpringConfigurer.groovy b/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBSpringConfigurer.groovy deleted file mode 100644 index bd231ab6f..000000000 --- a/grails-datastore-gorm-dynamodb/src/main/groovy/org/grails/datastore/gorm/dynamodb/plugin/support/DynamoDBSpringConfigurer.groovy +++ /dev/null @@ -1,63 +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.dynamodb.plugin.support - -import org.grails.datastore.gorm.dynamodb.bean.factory.DynamoDBDatastoreFactoryBean -import org.grails.datastore.gorm.dynamodb.bean.factory.DynamoDBMappingContextFactoryBean -import org.grails.datastore.gorm.plugin.support.SpringConfigurer -import org.grails.datastore.mapping.cache.impl.TPCacheAdapterRepositoryImpl -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager - -/** - * DynamoDB specific configuration logic for Spring - * - * @author Roman Stepanenko after Graeme Rocher - * @since 1.0 - */ -class DynamoDBSpringConfigurer extends SpringConfigurer { - - @Override - String getDatastoreType() { - return "DynamoDB" - } - - @Override - Closure getSpringCustomizer() { - return { - def dynamoDBConfig = application.config?.grails?.dynamodb - def cacheAdapters = application.config?.grails?.cacheAdapters - - def theCacheAdapterRepository = new TPCacheAdapterRepositoryImpl() - cacheAdapters?.each { clazz, adapter -> - theCacheAdapterRepository.setTPCacheAdapter(clazz, adapter) - } - - dynamodbTransactionManager(DatastoreTransactionManager) { - datastore = ref("dynamodbDatastore") - } - - dynamodbMappingContext(DynamoDBMappingContextFactoryBean) { - grailsApplication = ref('grailsApplication') - pluginManager = ref('pluginManager') - } - - dynamodbDatastore(DynamoDBDatastoreFactoryBean) { - mappingContext = ref("dynamodbMappingContext") - config = dynamoDBConfig.toProperties() - cacheAdapterRepository = theCacheAdapterRepository - } - } - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Book.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Book.groovy deleted file mode 100644 index 5b5571845..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Book.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Book implements Serializable { - String id - Long version - String author - String title - Boolean published = false -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Child.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Child.groovy deleted file mode 100644 index 439cb5cf8..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Child.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class Child implements Serializable { - String id - String name -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ChildEntity.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ChildEntity.groovy deleted file mode 100644 index 25d19e408..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ChildEntity.groovy +++ /dev/null @@ -1,22 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class ChildEntity implements Serializable { - String id - Long version - String name - - String toString() { - "ChildEntity{id='$id', name='$name'}" - } - - static belongsTo = [TestEntity] -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/City.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/City.groovy deleted file mode 100644 index 54b9d0125..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/City.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class City extends Location{ - String id - Long version - BigDecimal latitude - BigDecimal longitude -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy deleted file mode 100644 index c43eaef0b..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy +++ /dev/null @@ -1,29 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class ClassWithListArgBeforeValidate implements Serializable { - String id - Long version - - def listArgCounter = 0 - def propertiesPassedToBeforeValidate - String name - - def beforeValidate(List properties) { - ++listArgCounter - propertiesPassedToBeforeValidate = properties - } - - static constraints = { - name blank: false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy deleted file mode 100644 index 585869595..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class ClassWithNoArgBeforeValidate implements Serializable { - String id - Long version - - def noArgCounter = 0 - String name - - def beforeValidate() { - ++noArgCounter - } - - static constraints = { - name blank: false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy deleted file mode 100644 index cab931956..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy +++ /dev/null @@ -1,32 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class ClassWithOverloadedBeforeValidate implements Serializable { - String id - Long version - - def noArgCounter = 0 - def listArgCounter = 0 - def propertiesPassedToBeforeValidate - String name - def beforeValidate() { - ++noArgCounter - } - def beforeValidate(List properties) { - ++listArgCounter - propertiesPassedToBeforeValidate = properties - } - - static constraints = { - name blank: false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/CommonTypes.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/CommonTypes.groovy deleted file mode 100644 index 66847fc26..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/CommonTypes.groovy +++ /dev/null @@ -1,38 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class CommonTypes implements Serializable { - String id - Long version - - String name - - Long l - Byte b - Short s - Boolean bool - Integer i - URL url - Date date - Calendar c - BigDecimal bd - BigInteger bi - Double d - Float f - TimeZone tz - Locale loc - Currency cur - byte[] ba - - String toString() { - "CommonTypes{$id='$id', version=$version, name='$name', l=$l, b=$b, s=$s, bool=$bool, i=$i, url=$url, date=$date, c=$c, bd=$bd, bi=$bi, d=$d, f=$f, tz=$tz, loc=$loc, cur=$cur}" - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ConstrainedEntity.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ConstrainedEntity.groovy deleted file mode 100644 index 3d10e03a8..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ConstrainedEntity.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package grails.gorm.tests - -class ConstrainedEntity implements Serializable { - - static final MAX_VALUE = 1000 - static final List ALLOWABLE_VALUES=['ABC','DEF','GHI'] - - String id - Integer num - String str - - static constraints = { - num maxSize: MAX_VALUE /*Must be MyDomainClass.MAX_VALUE in order work with redis*/ - str validator: { val, obj -> - if (val != null && !ALLOWABLE_VALUES.contains(val)) {/*Must be MyDomainClass.ALLOWABLE_VALUES in order work with redis */ - return ['not.valid'] - } - } - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Country.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Country.groovy deleted file mode 100644 index 30c150a11..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Country.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Country extends Location { - String id - Long version - - Integer population - - static hasMany = [residents: Person] - Set residents - - String toString() { - "Country{id='$id', population=$population, residents=$residents}" - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy deleted file mode 100644 index 79e7807d4..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy +++ /dev/null @@ -1,158 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.tests.ChildEntity -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.TestEntity -import spock.lang.Ignore - -/** - * Removed some projection tests from standard CriteriaBuilderSpec because DynamoDB allows only count(*) in the select. - * The rest is identical to the main CriteriaBuilderSpec. - */ - -class CriteriaBuilderSpec extends GormDatastoreSpec { - void "Test idEq method"() { - given: - def entity = new TestEntity(name:"Bob", age: 44, child:new ChildEntity(name:"Child")).save(flush:true) - - when: - def result = TestEntity.createCriteria().get { idEq entity.id } - - then: - result != null - result.name == 'Bob' - } - - void "Test disjunction query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - or { - like('name', 'B%') - eq('age', 41) - } - } - - then: - 3 == results.size() - } - - void "Test conjunction query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - and { - like('name', 'B%') - eq('age', 40) - } - } - - then: - 1 == results.size() - } - - void "Test list() query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child: new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - like('name', 'B%') - } - - then: - 2 == results.size() - - when: - criteria = TestEntity.createCriteria() - results = criteria.list { - like('name', 'B%') - maxResults 1 - } - - then: - 1 == results.size() - } - - void "Test count()"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def result = criteria.count { - like('name', 'B%') - } - - then: - 2 == result - } - - void "Test obtain a single result"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def result = criteria.get { - eq('name', 'Bob') - } - - then: - result != null - "Bob" == result.name - } - - void "Test order by a property name"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - like('name', 'B%') - order "age" - } - - then: - "Bob" == results[0].name - "Barney" == results[1].name - - when: - criteria = TestEntity.createCriteria() - results = criteria.list { - like('name', 'B%') - order "age", "desc" - } - - then: - "Barney" == results[0].name - "Bob" == results[1].name - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy deleted file mode 100644 index 3530d112b..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy +++ /dev/null @@ -1,242 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.DetachedCriteria - -/** - * Overwrite standard DetachedCriteriaSpec because "Test list method with property projection" test is not correct - - * currently it assumes that records are returned in creation order ( ["Homer", "Marge"] ) - which is not always correct. - */ -class DetachedCriteriaSpec extends GormDatastoreSpec{ -// void "Test list method with property projection"() { -// given:"A bunch of people" -// createPeople() -// -// when:"A detached criteria instance is created that uses a property projection" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// criteria = criteria.property("firstName") -// -// def results = criteria.list(max: 2).sort() -// then:"The list method returns the right results" -// results.size() == 2 -// results == ["Homer", "Marge"] -// -// when:"A detached criteria instance is created that uses a property projection using property missing" -// criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// criteria = criteria.firstName -// -// results = criteria.list(max: 2).sort() -// then:"The list method returns the right results" -// results.size() == 2 -// results == ["Homer", "Marge"] -// -// } -// -// void "Test exists method"() { -// given:"A bunch of people" -// createPeople() -// -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// then:"The count method returns the right results" -// criteria.exists() == true -// } -// void "Test updateAll method"() { -// given:"A bunch of people" -// createPeople() -// -// when:"A detached criteria is created that deletes all matching records" -// def criteria = new DetachedCriteria(Person).build { -// eq 'lastName', 'Simpson' -// } -// int total = criteria.updateAll(lastName:"Bloggs") -// -// -// then:"The number of deletions is correct" -// total == 4 -// Person.count() == 6 -// criteria.count() == 0 -// Person.countByLastName("Bloggs") == 4 -// } -// -// void "Test deleteAll method"() { -// given:"A bunch of people" -// createPeople() -// -// when:"A detached criteria is created that deletes all matching records" -// def criteria = new DetachedCriteria(Person).build { -// eq 'lastName', 'Simpson' -// } -// int total = criteria.deleteAll() -// -// -// then:"The number of deletions is correct" -// total == 4 -// Person.count() == 2 -// } -// -// void "Test iterate of detached criteria"() { -// given:"A bunch of people" -// createPeople() -// -// when:"A detached criteria is created that matches the last name and then iterated over" -// def criteria = new DetachedCriteria(Person).build { -// eq 'lastName', 'Simpson' -// } -// int total = 0 -// criteria.each { -// total++ -// } -// -// then:"The number of iterations is correct" -// total == 4 -// } -// void "Test dynamic finder on detached criteria"() { -// given:"A bunch of people" -// createPeople() -// -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// def result = criteria.findByFirstNameLike("B%") -// -// then:"The list method returns the right results" -// result != null -// result.firstName == "Bart" -// } -// -// void "Test get method on detached criteria and additional criteria"() { -// given:"A bunch of people" -// createPeople() -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// def result = criteria.get { -// like 'firstName', 'B%' -// } -// then:"The list method returns the right results" -// result != null -// result.firstName == "Bart" -// } -// -// void "Test list method on detached criteria and additional criteria"() { -// given:"A bunch of people" -// createPeople() -// -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// def results = criteria.list { -// like 'firstName', 'B%' -// } -// then:"The list method returns the right results" -// results.size() == 1 -// results[0].firstName == "Bart" -// -// when:"The original detached criteria is queried" -// results = criteria.list() -// -// then:"The additional criteria didn't modify the original instance and the correct results are returned" -// results.size() == 4 -// results.every { it.lastName == 'Simpson'} -// } -// -// void "Test count method on detached criteria and additional criteria"() { -// given:"A bunch of people" -// createPeople() -// -// -// when:"A detached criteria instance is created matching the last name and count is called with additional criteria" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// def result = criteria.count { -// like 'firstName', 'B%' -// } -// then:"The count method returns the right results" -// result == 1 -// -// } -// -// void "Test count method on detached criteria"() { -// given:"A bunch of people" -// createPeople() -// -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// def result = criteria.count() -// then:"The count method returns the right results" -// result == 4 -// -// } -// void "Test list method on detached criteria"() { -// given:"A bunch of people" -// createPeople() -// -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// def results = criteria.list() -// then:"The list method returns the right results" -// results.size() == 4 -// results.every { it.lastName == 'Simpson'} -// } -// -// void "Test list method on detached criteria with pagination"() { -// given:"A bunch of people" -// createPeople() -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.build { -// eq 'lastName', 'Simpson' -// } -// -// def results = criteria.list(max: 2) -// then:"The list method returns the right results" -// results.size() == 2 -// results.every { it.lastName == 'Simpson'} -// } - - protected void createPeople() { - new Person(firstName: "Homer", lastName: "Simpson").save() - new Person(firstName: "Marge", lastName: "Simpson").save() - new Person(firstName: "Bart", lastName: "Simpson").save() - new Person(firstName: "Lisa", lastName: "Simpson").save() - new Person(firstName: "Barney", lastName: "Rubble").save() - new Person(firstName: "Fred", lastName: "Flinstone").save() - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/DynamoDBCombinationSpec.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/DynamoDBCombinationSpec.groovy deleted file mode 100644 index bf31c1daf..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/DynamoDBCombinationSpec.groovy +++ /dev/null @@ -1,62 +0,0 @@ -package grails.gorm.tests - -import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil - -import spock.lang.Specification - -/** - * Tests combination method in dymanodb util. - */ -class DynamoDBCombinationSpec extends Specification { - void "Test 1"() { - given: - def input = [ - [ ['a', 'b'] ] - ] - - when: - def result = DynamoDBUtil.combinate(input) - - then: - result == [ ['a', 'b'] ] - } - void "Test 2"() { - given: - def input = [ - [ ['a'], ['b'] ] - ] - - when: - def result = DynamoDBUtil.combinate(input) - - then: - result == [ ['a'], ['b'] ] - } - void "Test 3"() { - given: - def input = [ - [ ['a'], ['b'] ], - [ ['c'], ['d'] ], - ] - - when: - def result = DynamoDBUtil.combinate(input) - - then: - result == [ ['c', 'a'], ['d', 'a'], ['c', 'b'], ['d', 'b']] - } - void "Test 4"() { - given: - def input = [ - [ ['a'], ['b'] ], - [ ['c'], ['d'] ], - [ ['e'] ], - ] - - when: - def result = DynamoDBUtil.combinate(input) - - then: - result == [['e', 'c', 'a'], ['e', 'd', 'a'], ['e', 'c', 'b'], ['e', 'd', 'b']] - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/EnumThing.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/EnumThing.groovy deleted file mode 100644 index b8df89ed5..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/EnumThing.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class EnumThing implements Serializable { - String id - Long version - - String name - TestEnum en -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Face.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Face.groovy deleted file mode 100644 index f0ced9672..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Face.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -@Entity -class Face implements Serializable { - String id - String name - Nose nose - static hasOne = [nose: Nose] -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/GroupWithin.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/GroupWithin.groovy deleted file mode 100644 index 05d25ce4b..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/GroupWithin.groovy +++ /dev/null @@ -1,26 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class GroupWithin implements Serializable { - String id - Long version - - String name - String org - static constraints = { - name unique:"org" -// org index:true - } - - String toString() { - "GroupWithin{id='$id', version=$version, name='$name', org='$org'}" - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Highway.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Highway.groovy deleted file mode 100644 index cc0890259..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Highway.groovy +++ /dev/null @@ -1,19 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class Highway implements Serializable { - String id - Long version - - Boolean bypassed - String name -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/InheritanceSpec.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/InheritanceSpec.groovy deleted file mode 100644 index b437e0924..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/InheritanceSpec.groovy +++ /dev/null @@ -1,74 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity -import spock.lang.Ignore - -/** - * Removed "Test querying with inheritance" from InheritanceSpec because it is not supported currently. - * The rest is identical to the main CriteriaBuilderSpec. - */ -class InheritanceSpec extends GormDatastoreSpec { - - void "Test inheritance with dynamic finder"() { - - given: - def city = new City([code: "UK", name: "London", longitude: 49.1, latitude: 53.1]) - def country = new Country([code: "UK", name: "United Kingdom", population: 10000000]) - - city.save() - country.save(flush:true) - session.clear() - - when: - def cities = City.findAllByCode("UK") - def countries = Country.findAllByCode("UK") - - then: - 1 == cities.size() - 1 == countries.size() - "London" == cities[0].name - "United Kingdom" == countries[0].name - } - - @Ignore - void "Test querying with inheritance"() { - - given: - def city = new City([code: "LON", name: "London", longitude: 49.1, latitude: 53.1]) - def location = new Location([code: "XX", name: "The World"]) - def country = new Country([code: "UK", name: "United Kingdom", population: 10000000]) - - country.save() - city.save() - location.save() - - session.flush() - - when: - city = City.get(city.id) - def london = Location.get(city.id) - country = Location.findByName("United Kingdom") - def london2 = Location.findByName("London") - - then: - 1 == City.count() - 1 == Country.count() - 3 == Location.count() - - city != null - city instanceof City - london instanceof City - london2 instanceof City - "London" == london2.name - 49.1 == london2.longitude - "LON" == london2.code - - country instanceof Country - "UK" == country.code - 10000000 == country.population - } - - def clearSession() { - City.withSession { session -> session.flush() } - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/LexComparisonSpec.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/LexComparisonSpec.groovy deleted file mode 100644 index 5770f0086..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/LexComparisonSpec.groovy +++ /dev/null @@ -1,371 +0,0 @@ -package grails.gorm.tests - -/** - * Tests correctness of lexicographical comparisons and encoding. - * - * @author Roman Stepanenko - */ -class LexComparisonSpec extends GormDatastoreSpec { - - void "Test byte comparison"() { - given: - create("Alex") { it.setB(Byte.MAX_VALUE) }.save() - create("Bob") { it.setB(Byte.MIN_VALUE) }.save() - create("Sam") { it.setB(-102 as byte) }.save() - create("Carl") { it.setB(-15 as byte) }.save() - create("Don") { it.setB(-13 as byte) }.save() - create("Earl") { it.setB(0 as byte) }.save() - create("Roman") { it.setB(15 as byte) }.save() - create("Glen") { it.setB(125 as byte) }.save() - session.flush() - session.clear() - - def criteria = CommonTypes.createCriteria() - - when: - def results = CommonTypes.findAllByB(Byte.MAX_VALUE) - - then: - results.size() == 1 - results[0].name == 'Alex' - - when: - results = CommonTypes.findAllByB(Byte.MIN_VALUE) - - then: - results.size() == 1 - results[0].name == 'Bob' - - when: - results = CommonTypes.findAllByB(-13 as byte) - - then: - results.size() == 1 - results[0].name == 'Don' - - when: - results = CommonTypes.findAllByB(125 as byte) - - then: - results.size() == 1 - results[0].name == 'Glen' - - when: - results = criteria.list { - gt('b', 0 as byte) - order("b", "asc") - } - - then: - results.size() == 3 - results.collect {it.name} == ["Roman", "Glen", "Alex"] - - when: - results = criteria.list { - gt('b', -14 as byte) - order("b", "asc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Don", "Earl", "Roman", "Glen", "Alex"] - - when: - results = criteria.list { - lt('b', 0 as byte) - order("b", "asc") - } - - then: - results.size() == 4 - results.collect {it.name} == ["Bob", "Sam", "Carl", "Don"] - - when: - results = criteria.list { - lt('b', 2 as byte) - order("b", "desc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Earl", "Don", "Carl", "Sam", "Bob"] - } - - void "Test short comparison"() { - given: - create("Alex") { it.setS(Short.MAX_VALUE) }.save() - create("Bob") { it.setS(Short.MIN_VALUE) }.save() - create("Sam") { it.setS(-102 as short) }.save() - create("Carl") { it.setS(-15 as short) }.save() - create("Don") { it.setS(-13 as short) }.save() - create("Earl") { it.setS(0 as short) }.save() - create("Roman") { it.setS(15 as short) }.save() - create("Glen") { it.setS(125 as short) }.save() - session.flush() - session.clear() - - def criteria = CommonTypes.createCriteria() - - when: - def results = CommonTypes.findAllByS(Short.MAX_VALUE) - - then: - results.size() == 1 - results[0].name == 'Alex' - - when: - results = CommonTypes.findAllByS(Short.MIN_VALUE) - - then: - results.size() == 1 - results[0].name == 'Bob' - - when: - results = CommonTypes.findAllByS(-13 as short) - - then: - results.size() == 1 - results[0].name == 'Don' - - when: - results = CommonTypes.findAllByS(125 as short) - - then: - results.size() == 1 - results[0].name == 'Glen' - - when: - results = criteria.list { - gt('s', 0 as short) - order("s", "asc") - } - - then: - results.size() == 3 - results.collect {it.name} == ["Roman", "Glen", "Alex"] - - when: - results = criteria.list { - gt('s', -14 as short) - order("s", "asc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Don", "Earl", "Roman", "Glen", "Alex"] - - when: - results = criteria.list { - lt('s', 0 as short) - order("s", "asc") - } - - then: - results.size() == 4 - results.collect {it.name} == ["Bob", "Sam", "Carl", "Don"] - - when: - results = criteria.list { - lt('s', 2 as short) - order("s", "desc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Earl", "Don", "Carl", "Sam", "Bob"] - } - - void "Test integer comparison"() { - given: - create("Alex") { it.setI(Integer.MAX_VALUE) }.save() - create("Bob") { it.setI(Integer.MIN_VALUE) }.save() - create("Sam") { it.setI(-102 as int) }.save() - create("Carl") { it.setI(-15 as int) }.save() - create("Don") { it.setI(-13 as int) }.save() - create("Earl") { it.setI(0 as int) }.save() - create("Roman") { it.setI(15 as int) }.save() - create("Glen") { it.setI(125 as int) }.save() - session.flush() - session.clear() - - def criteria = CommonTypes.createCriteria() - - when: - def results = CommonTypes.findAllByI(Integer.MAX_VALUE) - - then: - results.size() == 1 - results[0].name == 'Alex' - - when: - results = CommonTypes.findAllByI(Integer.MIN_VALUE) - - then: - results.size() == 1 - results[0].name == 'Bob' - - when: - results = CommonTypes.findAllByI(-13 as int) - - then: - results.size() == 1 - results[0].name == 'Don' - - when: - results = CommonTypes.findAllByI(125 as int) - - then: - results.size() == 1 - results[0].name == 'Glen' - - when: - results = criteria.list { - gt('i', 0 as int) - order("i", "asc") - } - - then: - results.size() == 3 - results.collect {it.name} == ["Roman", "Glen", "Alex"] - - when: - results = criteria.list { - gt('i', -14 as int) - order("i", "asc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Don", "Earl", "Roman", "Glen", "Alex"] - - when: - results = criteria.list { - lt('i', 0 as int) - order("i", "asc") - } - - then: - results.size() == 4 - results.collect {it.name} == ["Bob", "Sam", "Carl", "Don"] - - when: - results = criteria.list { - lt('i', 2 as int) - order("i", "desc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Earl", "Don", "Carl", "Sam", "Bob"] - } - - void "Test long comparison"() { - given: - create("Alex") { it.setL(Long.MAX_VALUE) }.save() - create("Bob") { it.setL(Long.MIN_VALUE) }.save() - create("Sam") { it.setL(-102 as long) }.save() - create("Carl") { it.setL(-15 as long) }.save() - create("Don") { it.setL(-13 as long) }.save() - create("Earl") { it.setL(0 as long) }.save() - create("Roman") { it.setL(15 as long) }.save() - create("Glen") { it.setL(125 as long) }.save() - session.flush() - session.clear() - - def criteria = CommonTypes.createCriteria() - - when: - def results = CommonTypes.findAllByL(Long.MAX_VALUE) - - then: - results.size() == 1 - results[0].name == 'Alex' - - when: - results = CommonTypes.findAllByL(Long.MIN_VALUE) - - then: - results.size() == 1 - results[0].name == 'Bob' - - when: - results = CommonTypes.findAllByL(-13 as long) - - then: - results.size() == 1 - results[0].name == 'Don' - - when: - results = CommonTypes.findAllByL(125 as long) - - then: - results.size() == 1 - results[0].name == 'Glen' - - when: - results = criteria.list { - gt('l', 0 as long) - order("l", "asc") - } - - then: - results.size() == 3 - results.collect {it.name} == ["Roman", "Glen", "Alex"] - - when: - results = criteria.list { - gt('l', -14 as long) - order("l", "asc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Don", "Earl", "Roman", "Glen", "Alex"] - - when: - results = criteria.list { - lt('l', 0 as long) - order("l", "asc") - } - - then: - results.size() == 4 - results.collect {it.name} == ["Bob", "Sam", "Carl", "Don"] - - when: - results = criteria.list { - lt('l', 2 as long) - order("l", "desc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Earl", "Don", "Carl", "Sam", "Bob"] - } - - private CommonTypes create(name, modifier) { - def now = new Date() - def cal = new GregorianCalendar() - def ct = new CommonTypes( - name: name, - l: 10L, - b: 10 as byte, - s: 10 as short, - bool: true, - i: 10, - url: new URL("http://google.com"), - date: now, - c: cal, - bd: 1.0, - bi: 10 as BigInteger, - d: 1.0 as Double, - f: 1.0 as Float, - tz: TimeZone.getTimeZone("GMT"), - loc: Locale.UK, - cur: Currency.getInstance("USD") - ) - modifier(ct) - print "returning: "+ct - return ct - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Location.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Location.groovy deleted file mode 100644 index 77b9585a6..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Location.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class Location implements Serializable { - String id - Long version - - String name - String code = "DEFAULT" - - def namedAndCode() { - "$name - $code" - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy deleted file mode 100644 index 733b68616..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy +++ /dev/null @@ -1,22 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class ModifyPerson implements Serializable { - String id - Long version - - String name - - def beforeInsert() { - name = "Fred" - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/MultilineValueSpec.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/MultilineValueSpec.groovy deleted file mode 100644 index 55ef43131..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/MultilineValueSpec.groovy +++ /dev/null @@ -1,31 +0,0 @@ -package grails.gorm.tests - -/** - * Tests whether values with line breaks are stored and retrieved correctly. - */ -class MultilineValueSpec extends GormDatastoreSpec { - void "Test multivalue with slash n"() { - given: - def multiline = "Bob\nThe coder\nBuilt decoder" - def entity = new Book(title: multiline, author: "Mark", published: true).save(flush:true) - - when: - def result = Book.get(entity.id) - - then: - result != null - result.title == multiline - } - void "Test multivalue with slash r slash n"() { - given: - def multiline = "Bob\r\nThe coder\r\nBuilt decoder" - def entity = new Book(title: multiline, author: "Mark", published: true).save(flush:true) - - when: - def result = Book.get(entity.id) - - then: - result != null - result.title == multiline - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/NegationSpec.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/NegationSpec.groovy deleted file mode 100644 index 055893f5a..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/NegationSpec.groovy +++ /dev/null @@ -1,67 +0,0 @@ -package grails.gorm.tests - -/** - * Disabled complex negation - not supported [rstepanenko] - * @author graemerocher - */ -class NegationSpec extends GormDatastoreSpec { - - void "Test negation in dynamic finder"() { - given: - new Book(title:"The Stand", author:"Stephen King").save() - new Book(title:"The Shining", author:"Stephen King").save() - new Book(title:"Along Came a Spider", author:"James Patterson").save() - - when: - def results = Book.findAllByAuthorNotEqual("James Patterson") - def author = Book.findByAuthorNotEqual("Stephen King") - - then: - results.size() == 2 - results[0].author == "Stephen King" - results[1].author == "Stephen King" - - author != null - author.author == "James Patterson" - } - - void "Test simple negation in criteria"() { - given: - new Book(title:"The Stand", author:"Stephen King").save() - new Book(title:"The Shining", author:"Stephen King").save() - new Book(title:"Along Came a Spider", author:"James Patterson").save() - - when: - def results = Book.withCriteria { ne("author", "James Patterson" ) } - def author = Book.createCriteria().get { ne("author", "Stephen King" ) } - - then: - results.size() == 2 - results[0].author == "Stephen King" - results[1].author == "Stephen King" - - author != null - author.author == "James Patterson" - } - -// void "Test complex negation in criteria"() { -// given: -// new Book(title:"The Stand", author:"Stephen King").save() -// new Book(title:"The Shining", author:"Stephen King").save() -// new Book(title:"Along Came a Spider", author:"James Patterson").save() -// new Book(title:"The Girl with the Dragon Tattoo", author:"Stieg Larsson").save() -// -// when: -// def results = Book.withCriteria { -// not { -// eq 'title', 'The Stand' -// eq 'author', 'James Patterson' -// } -// } -// -// then: -// results.size() == 2 -// results.find { it.author == "Stieg Larsson" } != null -// results.find { it.author == "Stephen King" && it.title == "The Shining" } != null -// } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Nose.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Nose.groovy deleted file mode 100644 index e16c0791e..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Nose.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -@Entity -class Nose implements Serializable { - String id - boolean hasFreckles - Face face - static belongsTo = [face: Face] -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/OptLockNotVersioned.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/OptLockNotVersioned.groovy deleted file mode 100644 index a29881c69..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/OptLockNotVersioned.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class OptLockNotVersioned implements Serializable { - String id - - String name - - static mapping = { - version false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/OptLockVersioned.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/OptLockVersioned.groovy deleted file mode 100644 index 5c9063565..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/OptLockVersioned.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class OptLockVersioned implements Serializable { - String id - Long version - String name -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy deleted file mode 100644 index f91f3911d..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy +++ /dev/null @@ -1,53 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.PagedResultList - -import spock.lang.Ignore - -/** - * Ignored for DynamoDB because DynamoDB doesn't support pagination. - */ -@Ignore -class PagedResultSpec extends GormDatastoreSpec { - - void "Test that a paged result list is returned from the list() method with pagination params"() { - given:"Some people" - createPeople() - - when:"The list method is used with pagination params" - def results = Person.list(offset:2, max:2) - - then:"You get a paged result list back" - results instanceof PagedResultList - results.size() == 2 - results[0].firstName == "Bart" - results[1].firstName == "Lisa" - results.totalCount == 6 - } - - void "Test that a paged result list is returned from the critera with pagination params"() { - given:"Some people" - createPeople() - - when:"The list method is used with pagination params" - def results = Person.createCriteria().list(offset:1, max:2) { - eq 'lastName', 'Simpson' - } - - then:"You get a paged result list back" - results instanceof PagedResultList - results.size() == 2 - results[0].firstName == "Marge" - results[1].firstName == "Bart" - results.totalCount == 4 - } - - protected void createPeople() { - new Person(firstName: "Homer", lastName: "Simpson", age:45).save() - new Person(firstName: "Marge", lastName: "Simpson", age:40).save() - new Person(firstName: "Bart", lastName: "Simpson", age:9).save() - new Person(firstName: "Lisa", lastName: "Simpson", age:7).save() - new Person(firstName: "Barney", lastName: "Rubble", age:35).save() - new Person(firstName: "Fred", lastName: "Flinstone", age:41).save() - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Parent.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Parent.groovy deleted file mode 100644 index 55c50785f..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Parent.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class Parent implements Serializable { - String id - String name - Set children = [] - static hasMany = [children: Child] -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Person.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Person.groovy deleted file mode 100644 index de5d5dd02..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Person.groovy +++ /dev/null @@ -1,25 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Person implements Serializable { - String id - Long version - - String firstName - String lastName - Integer age = 0 - Set pets = [] as Set - static hasMany = [pets: Pet] - - String toString() { - "Person{firstName='$firstName', id='$id', lastName='$lastName', pets=$pets}" - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PersonEvent.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PersonEvent.groovy deleted file mode 100644 index 6d83b79fd..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PersonEvent.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class PersonEvent implements Serializable { - String id - Long version - - String name - Date dateCreated - Date lastUpdated - - def personService - - static STORE_INITIAL = [ - beforeDelete: 0, afterDelete: 0, - beforeUpdate: 0, afterUpdate: 0, - beforeInsert: 0, afterInsert: 0, - beforeLoad: 0, afterLoad: 0] - - static STORE = [:] + STORE_INITIAL - - static void resetStore() { - STORE = [:] + STORE_INITIAL - } - - def beforeDelete() { - STORE.beforeDelete++ - } - - void afterDelete() { - STORE.afterDelete++ - } - - def beforeUpdate() { - STORE.beforeUpdate++ - } - - void afterUpdate() { - STORE.afterUpdate++ - } - - def beforeInsert() { - STORE.beforeInsert++ - } - - void afterInsert() { - STORE.afterInsert++ - } - - void beforeLoad() { - STORE.beforeLoad++ - } - - void afterLoad() { - STORE.afterLoad++ - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Pet.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Pet.groovy deleted file mode 100644 index 23476ede1..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Pet.groovy +++ /dev/null @@ -1,28 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Pet implements Serializable { - String id - Long version - - String name - Date birthDate = new Date() - PetType type = new PetType(name: "Unknown") - Person owner - - String toString() { - "Pet{id='$id', name='$name', birthDate=$birthDate, type=$type, owner=$owner}" - } - - static constraints = { - owner nullable:true - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PetType.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PetType.groovy deleted file mode 100644 index 16b8761a3..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PetType.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class PetType implements Serializable { - String id - Long version - - String name - - static belongsTo = Pet -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Plant.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Plant.groovy deleted file mode 100644 index 161705a13..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Plant.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Plant implements Serializable { - String id - Long version - - boolean goesInPatch - String name -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PlantCategory.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PlantCategory.groovy deleted file mode 100644 index f0f75a748..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PlantCategory.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class PlantCategory implements Serializable { - String id - Long version - - Set plants - String name - - static hasMany = [plants:Plant] -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PlantNumericIdValue.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PlantNumericIdValue.groovy deleted file mode 100644 index a03f623b2..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PlantNumericIdValue.groovy +++ /dev/null @@ -1,26 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB, uses hilo id generator for DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class PlantNumericIdValue implements Serializable { - String id - Long version - - boolean goesInPatch - String name - - String toString() { - "PlantNumericIdValue{id='$id', version=$version, goesInPatch=$goesInPatch, name='$name'}" - } - - static mapping = { - id_generator type: 'hilo', maxLo: 5 - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy deleted file mode 100644 index 9d508239f..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package grails.gorm.tests - -import org.junit.Ignore - -/** - * Tests for criteria queries that compare two properties - */ -class PropertyComparisonQuerySpec extends GormDatastoreSpec{ - - @Ignore - void "Test eqProperty criterion"() { - // TODO: implement eqProperty query operations - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Publication.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Publication.groovy deleted file mode 100644 index f74a67ecd..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Publication.groovy +++ /dev/null @@ -1,81 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Publication implements Serializable { - String id - Long version - - String title - Date datePublished - Boolean paperback = true - - String toString() { - "Publication{id='$id', title='$title', paperback=$paperback, datePublished=$datePublished}" - } - - static namedQueries = { - lastPublishedBefore { date -> - uniqueResult = true - le 'datePublished', date - order 'datePublished', 'desc' - } - - recentPublications { - def now = new Date() - gt 'datePublished', now - 365 - } - - publicationsWithBookInTitle { - like 'title', 'Book%' - } - - recentPublicationsByTitle { title -> - recentPublications() - eq 'title', title - } - - latestBooks { - maxResults(10) - order("datePublished", "desc") - } - - publishedBetween { start, end -> - between 'datePublished', start, end - } - - publishedAfter { date -> - gt 'datePublished', date - } - - paperbackOrRecent { - or { - def now = new Date() - gt 'datePublished', now - 365 - paperbacks() - } - } - - paperbacks { - eq 'paperback', true - } - - paperbackAndRecent { - paperbacks() - recentPublications() - } - - thisWeeksPaperbacks() { - paperbacks() - def today = new Date() - publishedBetween(today - 7, today) - } - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/SimpleDBHiloSpec.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/SimpleDBHiloSpec.groovy deleted file mode 100644 index 56a5f5ae8..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/SimpleDBHiloSpec.groovy +++ /dev/null @@ -1,37 +0,0 @@ -package grails.gorm.tests - -/** - * Tests hilo dynamodb id generator - */ -class DynamoDBHiloSpec extends GormDatastoreSpec { - - void "Test one"() { - given: - def entity = new PlantNumericIdValue(name: "Single").save(flush:true) - - when: - def result = PlantNumericIdValue.get(entity.id) - - then: - result != null - Long.parseLong(result.id) > 0 - result.id == Long.toString(Long.parseLong(result.id)) - } - - void "Test multiple"() { - given: - def entities = [] - for (i in 1..10) { - entities.add(new PlantNumericIdValue(name: "OneOfThem-"+i).save(flush:true)) - } - - expect: - //make sure ids are monotonically increase - long previous = 0 - entities.each { it -> - long current = Long.parseLong(it.id) - assert current > previous - previous = current - } - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Simples.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Simples.groovy deleted file mode 100644 index 164fc09da..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Simples.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Simples implements Serializable { - String id - Long version - - boolean goesInPatch - String name -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy deleted file mode 100644 index 082db7656..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.tests.GormDatastoreSpec -import org.junit.Ignore - -/** - * Tests for querying the size of collections etc. - */ -class SizeQuerySpec extends GormDatastoreSpec { - - @Ignore - void "Test sizeEq criterion"() { - // TODO: implement sizeEq query operations - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Task.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Task.groovy deleted file mode 100644 index 5ee30730f..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/Task.groovy +++ /dev/null @@ -1,26 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class Task implements Serializable { - String id - Long version - - Set tasks - Task task - String name - - static mapping = { - table 'Task' - } - - static hasMany = [tasks:Task] -} \ No newline at end of file diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/TestEntity.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/TestEntity.groovy deleted file mode 100644 index abd26f994..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/TestEntity.groovy +++ /dev/null @@ -1,37 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class TestEntity implements Serializable { - String id - Long version - - String name - Integer age = 30 - - ChildEntity child - - String toString() { - "TestEntity(AWS){id='$id', name='$name', age=$age, child=$child}" - } - - static constraints = { -// name blank: false -// we change the constraint because in original ValidationSpec we are testing if we can actually save with empty string but dynamo does not allow empty strings - name nullable: false - - child nullable: true - } - - static mapping = { - table 'TestEntity' - child nullable:true - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/UniqueGroup.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/UniqueGroup.groovy deleted file mode 100644 index ec676f0be..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/UniqueGroup.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class UniqueGroup implements Serializable { - String id - Long version - - String name - static constraints = { - name unique: true - } - - String toString() { - "UniqueGroup{id='$id', version=$version, name='$name'}" - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy deleted file mode 100644 index 74c7d2bee..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy +++ /dev/null @@ -1,180 +0,0 @@ -package grails.gorm.tests - -import org.grails.datastore.mapping.validation.ValidatingEventListener - -/** - * Tests validation semantics. - * We change the constraint because in original ValidationSpec we are testing if we can actually save with empty string but dynamo does not allow empty strings - * so for dynamo we will be testing 'bad' data with null value - */ -class ValidationSpec extends GormDatastoreSpec { - - void "Test disable validation"() { - session.datastore.applicationContext.addApplicationListener( - new ValidatingEventListener(session.datastore)) - - // test assumes name should not be null - given: - def t - - when: - t = new TestEntity(name:null, child:new ChildEntity(name:"child")) - def validationResult = t.validate() - def errors = t.errors - - then: - !validationResult - t.hasErrors() - errors != null - errors.hasErrors() - - when: - t.save(validate:false, flush:true) - - then: - t.id != null - !t.hasErrors() - } - - void "Test validate() method"() { - // test assumes name cannot be blank - given: - def t - - when: - t = new TestEntity(name:null) - def validationResult = t.validate() - def errors = t.errors - - then: - !validationResult - t.hasErrors() - errors != null - errors.hasErrors() - - when: - t.clearErrors() - - then: - !t.hasErrors() - } - - void "Test that validate is called on save()"() { - - given: - def t - - when: - t = new TestEntity(name:null) - - then: - t.save() == null - t.hasErrors() == true - 0 == TestEntity.count() - - when: - t.clearErrors() - t.name = "Bob" - t.age = 45 - t.child = new ChildEntity(name:"Fred") - t = t.save() - - then: - t != null - 1 == TestEntity.count() - } - - void "Test beforeValidate gets called on save()"() { - given: - def entityWithNoArgBeforeValidateMethod - def entityWithListArgBeforeValidateMethod - def entityWithOverloadedBeforeValidateMethod - - when: - entityWithNoArgBeforeValidateMethod = new ClassWithNoArgBeforeValidate() - entityWithListArgBeforeValidateMethod = new ClassWithListArgBeforeValidate() - entityWithOverloadedBeforeValidateMethod = new ClassWithOverloadedBeforeValidate() - entityWithNoArgBeforeValidateMethod.save() - entityWithListArgBeforeValidateMethod.save() - entityWithOverloadedBeforeValidateMethod.save() - - then: - 1 == entityWithNoArgBeforeValidateMethod.noArgCounter - 1 == entityWithListArgBeforeValidateMethod.listArgCounter - 1 == entityWithOverloadedBeforeValidateMethod.noArgCounter - 0 == entityWithOverloadedBeforeValidateMethod.listArgCounter - } - - void "Test beforeValidate gets called on validate()"() { - given: - def entityWithNoArgBeforeValidateMethod - def entityWithListArgBeforeValidateMethod - def entityWithOverloadedBeforeValidateMethod - - when: - entityWithNoArgBeforeValidateMethod = new ClassWithNoArgBeforeValidate() - entityWithListArgBeforeValidateMethod = new ClassWithListArgBeforeValidate() - entityWithOverloadedBeforeValidateMethod = new ClassWithOverloadedBeforeValidate() - entityWithNoArgBeforeValidateMethod.validate() - entityWithListArgBeforeValidateMethod.validate() - entityWithOverloadedBeforeValidateMethod.validate() - - then: - 1 == entityWithNoArgBeforeValidateMethod.noArgCounter - 1 == entityWithListArgBeforeValidateMethod.listArgCounter - 1 == entityWithOverloadedBeforeValidateMethod.noArgCounter - 0 == entityWithOverloadedBeforeValidateMethod.listArgCounter - } - - void "Test beforeValidate gets called on validate() and passing a list of field names to validate"() { - given: - def entityWithNoArgBeforeValidateMethod - def entityWithListArgBeforeValidateMethod - def entityWithOverloadedBeforeValidateMethod - - when: - entityWithNoArgBeforeValidateMethod = new ClassWithNoArgBeforeValidate() - entityWithListArgBeforeValidateMethod = new ClassWithListArgBeforeValidate() - entityWithOverloadedBeforeValidateMethod = new ClassWithOverloadedBeforeValidate() - entityWithNoArgBeforeValidateMethod.validate(['name']) - entityWithListArgBeforeValidateMethod.validate(['name']) - entityWithOverloadedBeforeValidateMethod.validate(['name']) - - then: - 1 == entityWithNoArgBeforeValidateMethod.noArgCounter - 1 == entityWithListArgBeforeValidateMethod.listArgCounter - 0 == entityWithOverloadedBeforeValidateMethod.noArgCounter - 1 == entityWithOverloadedBeforeValidateMethod.listArgCounter - ['name'] == entityWithOverloadedBeforeValidateMethod.propertiesPassedToBeforeValidate - } - - void "Test that validate works without a bound Session"() { - - given: - def t - - when: - session.disconnect() - t = new TestEntity(name:null) - - then: - !session.datastore.hasCurrentSession() - t.save() == null - t.hasErrors() == true - 1 == t.errors.allErrors.size() - TestEntity.getValidationErrorsMap().get(System.identityHashCode(t)).is(t.errors) - 0 == TestEntity.count() - - when: - t.clearErrors() - t.name = "Bob" - t.age = 45 - t.child = new ChildEntity(name:"Fred") - t = t.save(flush: true) - - then: - !session.datastore.hasCurrentSession() - t != null - 1 == TestEntity.count() - } -} diff --git a/grails-datastore-gorm-dynamodb/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-dynamodb/src/test/groovy/org/grails/datastore/gorm/Setup.groovy deleted file mode 100644 index e43838bcd..000000000 --- a/grails-datastore-gorm-dynamodb/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ /dev/null @@ -1,171 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.PlantNumericIdValue - -import java.util.concurrent.CountDownLatch -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors - -import org.grails.datastore.gorm.dynamodb.DynamoDBGormEnhancer -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.dynamodb.DynamoDBDatastore -import org.grails.datastore.mapping.dynamodb.config.DynamoDBMappingContext -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBAssociationInfo -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBTableResolver -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBTableResolverFactory -import org.grails.datastore.mapping.dynamodb.util.DynamoDBTemplate -import org.grails.datastore.mapping.dynamodb.util.DynamoDBUtil -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager -import org.springframework.context.support.GenericApplicationContext -import org.springframework.util.StringUtils -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -/** - * In order to run AWS DynamoDB tests you have to define a file called 'aws.properties' in your home dir - * with the following properties: - * AWS_ACCESS_KEY and AWS_SECRET_KEY - * - * your aws credentials and then invoke this command from main directory: - * gradlew grails-datastore-gorm-dynamodb:test - * - * or this one to run one specific test: - * gradlew -Dtest.single=CrudOperationsSpec grails-datastore-gorm-dynamodb:test - * - * @author graemerocher - * @author Roman Stepanenko - */ -class Setup { - - static Set tableNames = new HashSet() //we keep track of each table to drop at the end because DynamoDB is expensive for a large number of tables - - static dynamoDB - static session - - static destroy() { -// session.nativeInterface.dropDatabase() - List existingTables = dynamoDB.getDynamoDBTemplate().listTables() - println ''+ new Date() + ': currently existing dynamodb tables: '+existingTables.size()+" : "+existingTables - tableNames.each { table-> - boolean delete=false - if (delete && existingTables.contains(table)) { - println ''+ new Date() + ': deleting dynamodb table: '+table - dynamoDB.getDynamoDBTemplate().deleteTable(table) - } - } - } - - static Session setup(classes) { - classes.add(PlantNumericIdValue.class) - - def env = System.getenv() - final userHome = System.getProperty("user.home") - def settingsFile = new File(userHome, "aws.properties") - def connectionDetails = [:] - if (settingsFile.exists()) { - def props = new Properties() - settingsFile.withReader { reader -> - props.load(reader) - } - connectionDetails.put(DynamoDBDatastore.ACCESS_KEY, props['AWS_ACCESS_KEY']) - connectionDetails.put(DynamoDBDatastore.SECRET_KEY, props['AWS_SECRET_KEY']) - } - - connectionDetails.put(DynamoDBDatastore.TABLE_NAME_PREFIX_KEY, "TEST_") - connectionDetails.put(DynamoDBDatastore.DELAY_AFTER_WRITES_MS, "3000") //this flag will cause pausing for that many MS after each write - to fight eventual consistency - - dynamoDB = new DynamoDBDatastore(new DynamoDBMappingContext(), connectionDetails) - def ctx = new GenericApplicationContext() - ctx.refresh() - dynamoDB.applicationContext = ctx - dynamoDB.afterPropertiesSet() - - for (cls in classes) { - dynamoDB.mappingContext.addPersistentEntity(cls) - } - - cleanOrCreateDomainsIfNeeded(classes, dynamoDB.mappingContext, dynamoDB) - - PersistentEntity entity = dynamoDB.mappingContext.persistentEntities.find { PersistentEntity e -> e.name.contains("TestEntity")} - - dynamoDB.mappingContext.addEntityValidator(entity, [ - supports: { Class c -> true }, - validate: { Object o, Errors errors -> - if (!StringUtils.hasText(o.name)) { - errors.rejectValue("name", "name.is.blank") - } - } - ] as Validator) - - def enhancer = new DynamoDBGormEnhancer(dynamoDB, new DatastoreTransactionManager(datastore: dynamoDB)) - enhancer.enhance() - - dynamoDB.mappingContext.addMappingContextListener({ e -> - enhancer.enhance e - } as MappingContext.Listener) - - dynamoDB.applicationContext.addApplicationListener new DomainEventListener(dynamoDB) - dynamoDB.applicationContext.addApplicationListener new AutoTimestampEventListener(dynamoDB) - - session = dynamoDB.connect() - - return session - } - - /** - * Creates AWS domain if AWS domain corresponding to a test entity class does not exist, or cleans it if it does exist. - * @param domainClasses - * @param mappingContext - * @param dynamoDBDatastore - */ - static void cleanOrCreateDomainsIfNeeded(def domainClasses, mappingContext, dynamoDBDatastore) { - DynamoDBTemplate template = dynamoDBDatastore.getDynamoDBTemplate() - List existingTables = template.listTables() - DynamoDBTableResolverFactory resolverFactory = new DynamoDBTableResolverFactory() - - ExecutorService executorService = Executors.newFixedThreadPool(10) //dynamodb allows no more than 10 tables to be created simultaneously - CountDownLatch latch = new CountDownLatch(domainClasses.size()) - for (dc in domainClasses) { - def domainClass = dc //explicitly declare local variable which we will be using from the thread - //do dynamoDB work in parallel threads for each entity to speed things up - executorService.execute({ - try { - PersistentEntity entity = mappingContext.getPersistentEntity(domainClass.getName()) - DynamoDBTableResolver tableResolver = resolverFactory.buildResolver(entity, dynamoDBDatastore) - def tables = tableResolver.getAllTablesForEntity() - tables.each { table -> - tableNames.add(table) - clearOrCreateTable(dynamoDBDatastore, existingTables, table) - //create domains for associations - entity.getAssociations().each { association -> - DynamoDBAssociationInfo associationInfo = dynamoDBDatastore.getAssociationInfo(association) - if (associationInfo) { - tableNames.add(associationInfo.getTableName()) - clearOrCreateTable(dynamoDBDatastore, existingTables, associationInfo.getTableName()) - } - } - } - } finally { - latch.countDown() - } - } as Runnable) - } - latch.await() - } - - static clearOrCreateTable(DynamoDBDatastore datastore, def existingTables, String tableName) { - if (existingTables.contains(tableName)) { - datastore.getDynamoDBTemplate().deleteAllItems(tableName) //delete all items there - } else { - //create it - datastore.getDynamoDBTemplate().createTable(tableName, - DynamoDBUtil.createIdKeySchema(), - DynamoDBUtil.createDefaultProvisionedThroughput(datastore) - ) - } - } -} diff --git a/grails-datastore-gorm-gemfire/build.gradle b/grails-datastore-gorm-gemfire/build.gradle deleted file mode 100644 index 4734a8fef..000000000 --- a/grails-datastore-gorm-gemfire/build.gradle +++ /dev/null @@ -1,15 +0,0 @@ -version = "1.0.0.BUILD-SNAPSHOT" - -repositories { - maven { url "http://dist.gemstone.com/maven/release" } -} - -dependencies { - - compile project(":grails-datastore-gorm"), - project(":grails-datastore-gemfire"), - project(":grails-datastore-core") - - testCompile project(":grails-datastore-gorm-test"), - project(":grails-datastore-gorm-tck") -} diff --git a/grails-datastore-gorm-gemfire/src/main/groovy/org/grails/datastore/gorm/gemfire/ContinuousQueryApi.groovy b/grails-datastore-gorm-gemfire/src/main/groovy/org/grails/datastore/gorm/gemfire/ContinuousQueryApi.groovy deleted file mode 100644 index a7474dffc..000000000 --- a/grails-datastore-gorm-gemfire/src/main/groovy/org/grails/datastore/gorm/gemfire/ContinuousQueryApi.groovy +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (C) 2010 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.gemfire - -import org.grails.datastore.gorm.finders.DynamicFinder -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.gemfire.GemfireDatastore -import org.grails.datastore.mapping.gemfire.query.GemfireQuery -import org.grails.datastore.mapping.model.PersistentEntity -import org.springframework.util.Assert - -import com.gemstone.gemfire.cache.query.CqAttributes -import com.gemstone.gemfire.cache.query.CqAttributesFactory -import com.gemstone.gemfire.cache.query.CqEvent -import com.gemstone.gemfire.cache.query.CqListener - -/** - * Extended API for doing Continous queries in Gemfire - */ -class ContinuousQueryApi { - - final PersistentEntity entity - final GemfireDatastore gemfire - - private dynamicFinders - - ContinuousQueryApi(PersistentEntity entity, GemfireDatastore gemfire, List finders) { - this.entity = entity - this.gemfire = gemfire - this.dynamicFinders = finders - } - - def invokeMethod(String methodName, args) { - - def gemfirePool = gemfire.gemfirePool - Assert.notNull(gemfirePool, "Cannot invoke a continuous query without an appropriately initialized Gemfire Pool") - - FinderMethod method = dynamicFinders.find { FinderMethod f -> f.isMethodMatch(methodName) } - if (!method || !args || !(args[-1] instanceof Closure) || !(method instanceof DynamicFinder)) { - throw new MissingMethodException(methodName, entity.javaClass, args) - } - - DynamicFinder dynamicFinder = method - - def invocation = dynamicFinder.createFinderInvocation(entity.javaClass, methodName, null, args) - // TODO not sure if current session makes sense for continuous query - GemfireQuery q = dynamicFinder.buildQuery(invocation, gemfire.currentSession) - def queryString = q.getQueryString() - - def queryService = gemfirePool.getQueryService() - - CqAttributesFactory cqf = new CqAttributesFactory() - def listeners = [new ClosureInvokingCqListener(args[-1])] as CqListener[] - cqf.initCqListeners(listeners) - CqAttributes attrs = cqf.create() - - def cqName = "${entity.name}.${methodName}(${args[0..-2].join(',')})" - def continuousQuery = queryService.newCq(cqName,queryString, attrs) - - continuousQuery.execute() - gemfire.addContinuousQuery(continuousQuery) - return continuousQuery - } -} - -class ClosureInvokingCqListener implements CqListener { - - Closure callable - - ClosureInvokingCqListener(Closure callable) { - this.callable = callable - } - - void onEvent(CqEvent cqEvent) { - callable?.call(cqEvent) - } - - void onError(CqEvent cqEvent) { - callable?.call(cqEvent) - } - - void close() { - // do nothing - } -} diff --git a/grails-datastore-gorm-gemfire/src/main/groovy/org/grails/datastore/gorm/gemfire/GemfireGormEnhancer.groovy b/grails-datastore-gorm-gemfire/src/main/groovy/org/grails/datastore/gorm/gemfire/GemfireGormEnhancer.groovy deleted file mode 100644 index 06ee07aff..000000000 --- a/grails-datastore-gorm-gemfire/src/main/groovy/org/grails/datastore/gorm/gemfire/GemfireGormEnhancer.groovy +++ /dev/null @@ -1,229 +0,0 @@ -/* Copyright (C) 2010 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.gemfire - -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.gemfire.GemfireDatastore -import org.grails.datastore.mapping.query.Query -import org.grails.datastore.mapping.query.order.ManualEntityOrdering -import org.springframework.data.gemfire.GemfireCallback -import org.springframework.data.gemfire.GemfireTemplate -import org.springframework.util.ReflectionUtils - -import com.gemstone.gemfire.cache.Region -import com.gemstone.gemfire.cache.execute.FunctionAdapter -import com.gemstone.gemfire.cache.execute.FunctionContext -import com.gemstone.gemfire.cache.execute.FunctionService -import com.gemstone.gemfire.cache.execute.RegionFunctionContext -import com.gemstone.gemfire.cache.execute.ResultSender -import com.gemstone.gemfire.cache.partition.PartitionRegionHelper - -/** - * Extends the default GORM capabilities adding Gemfire specific methods - */ -class GemfireGormEnhancer extends GormEnhancer { - - GemfireGormEnhancer(GemfireDatastore datastore) { - super(datastore) - } - - GemfireGormEnhancer(GemfireDatastore datastore, transactionManager) { - super(datastore, transactionManager) - } - - protected GormStaticApi getStaticApi(Class cls) { - return new GemfireStaticApi (cls, datastore, getFinders()) - } -} - -/** - * Wrapper for invoking Gemfire functions - */ -class ClosureInvokingFunction extends FunctionAdapter { - - Closure callable - String id - - ClosureInvokingFunction(Closure callable, id) { - this.callable = callable - this.id = id - - disableOwner(callable) - } - - protected void disableOwner(Closure callable) { - // disable owner to prevent the owner being serialized with the function - nullifyField(callable, "owner") - nullifyField(callable, "delegate") - nullifyField(callable, "thisObject") - } - - protected void nullifyField(Closure callable, String fieldName) { - def field = ReflectionUtils.findField(callable.getClass(), fieldName) - ReflectionUtils.makeAccessible field - field.set callable, null - } - - ClosureInvokingFunction(callable) { - this(callable, callable.getClass().name) - } - - void execute(FunctionContext functionContext) { - def helper = new FunctionContextHelper(functionContext) - callable.resolveStrategy = Closure.DELEGATE_FIRST - callable?.call(helper) - } -} - -class FunctionContextHelper implements RegionFunctionContext, ResultSender, Serializable { - @Delegate RegionFunctionContext context - @Delegate ResultSender resultSender - FunctionContextHelper(RegionFunctionContext context) { - this.context = context - this.resultSender = context.resultSender - } - - Region getLocalData() { - PartitionRegionHelper.getLocalDataForContext(context) - } - - Set getFilter() { context.filter } - - @SuppressWarnings("unchecked") - Region getDataSet() { context.dataSet } - - Serializable getArguments() { context.arguments } - - String getFunctionId() { context.functionId } - - void sendResult(Serializable t) { - resultSender.sendResult t - } - - void lastResult(Serializable t) { - resultSender.lastResult t - } -} - -/** - * Adds support for String-based queries using OQL and continuous queries - */ -class GemfireStaticApi extends GormStaticApi { - - ContinuousQueryApi cqApi - List finders - - GemfireStaticApi(Class persistentClass, GemfireDatastore datastore, List finders) { - super(persistentClass, datastore, finders) - cqApi = new ContinuousQueryApi(persistentEntity, datastore, finders) - } - - ContinuousQueryApi getCq() { cqApi } - - def executeFunction(Collection keys, Closure callable) { - GemfireDatastore gemfire = datastore - GemfireTemplate template = gemfire.getTemplate(persistentClass) - def resultCollector = FunctionService.onRegion(template.region) - .withFilter(keys as Set) - .execute(new ClosureInvokingFunction(callable)) - - return resultCollector.getResult() - } - - def executeFunction(Closure callable) { - GemfireDatastore gemfire = datastore - GemfireTemplate template = gemfire.getTemplate(persistentClass) - def resultCollector = FunctionService.onRegion(template.region) - .execute(new ClosureInvokingFunction(callable)) - - return resultCollector.getResult() - } - - List executeQuery(String query) { - GemfireDatastore gemfire = datastore - GemfireTemplate template = gemfire.getTemplate(persistentClass) - - template?.query(query)?.asList() ?: Collections.emptyList() - } - - List executeQuery(String query, Collection params) { - executeQuery(query, params, Collections.emptyMap()) - } - - List executeQuery(String query, Map args) { - executeQuery(query, Collections.emptyList(), args) - } - - List executeQuery(String query, Collection params, Map args) { - GemfireDatastore gemfire = datastore - GemfireTemplate template = gemfire.getTemplate(persistentClass) - - template.execute({ Region region -> - def cache = gemfire.gemfireCache - def queryService = cache.queryService - - def q = queryService.newQuery("SELECT DISTINCT * FROM /${persistentEntity.decapitalizedName} WHERE ${query}") - def results = q.execute(params.toArray()).asList() - - if (args?.sort) { - def prop = args.sort - def ordering = new ManualEntityOrdering(persistentEntity) - if (args?.order == 'desc') { - results = ordering.applyOrder(results, Query.Order.desc(prop)) - } - else { - results = ordering.applyOrder(results, Query.Order.asc(prop)) - } - } - - return results - } as GemfireCallback) - } - - D find(String query) { - executeQuery("$query LIMIT 1")[0] - } - - D find(String query, Collection params) { - executeQuery("$query LIMIT 1", params)[0] - } - - D find(String query, Map args) { - executeQuery("$query LIMIT 1", args)[0] - } - - D find(String query, Collection params, Map args) { - executeQuery("$query LIMIT 1", params, args)[0] - } - - List findAll(String query) { - executeQuery(query) - } - - List findAll(String query, Collection params) { - executeQuery(query, params) - } - - List findAll(String query, Collection params, Map args) { - executeQuery(query, params, args) - } - - List findAll(String query, Map args) { - executeQuery(query, args) - } -} diff --git a/grails-datastore-gorm-gemfire/src/main/groovy/org/grails/datastore/gorm/gemfire/config/CacheServerConfigGenerator.groovy b/grails-datastore-gorm-gemfire/src/main/groovy/org/grails/datastore/gorm/gemfire/config/CacheServerConfigGenerator.groovy deleted file mode 100644 index 5d092a5bd..000000000 --- a/grails-datastore-gorm-gemfire/src/main/groovy/org/grails/datastore/gorm/gemfire/config/CacheServerConfigGenerator.groovy +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2010 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.gemfire.config - -import org.grails.datastore.mapping.gemfire.GemfireDatastore -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.gemfire.config.Region - -/** - * Generates a Gemfire cache.xml configuration for the Datastore. - * - * @author Graeme Rocher - * @since 1.0 - */ -class CacheServerConfigGenerator { - - GemfireDatastore datastore - - CacheServerConfigGenerator(GemfireDatastore datastore) { - this.datastore = datastore - } - - void generate(File target) { - def regions = [] - for (PersistentEntity entity in datastore.mappingContext.persistentEntities) { - Region r = entity.mapping.mappedForm - def regionName = r?.region ?: entity.decapitalizedName - regions << """\ - - - - - - """ - } - target.withWriter { w -> - w << """\ - - - - - ${regions.join(System.getProperty('line.separator'))} - - """ - } - } -} diff --git a/grails-datastore-gorm-gemfire/src/main/groovy/org/grails/datastore/gorm/gemfire/config/PoolFactoryBean.groovy b/grails-datastore-gorm-gemfire/src/main/groovy/org/grails/datastore/gorm/gemfire/config/PoolFactoryBean.groovy deleted file mode 100644 index f0136a2c7..000000000 --- a/grails-datastore-gorm-gemfire/src/main/groovy/org/grails/datastore/gorm/gemfire/config/PoolFactoryBean.groovy +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (C) 2010 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.gemfire.config - -import org.springframework.beans.factory.BeanNameAware -import org.springframework.beans.factory.FactoryBean - -import com.gemstone.gemfire.cache.client.Pool -import com.gemstone.gemfire.cache.client.PoolFactory - -/** - * Factory bean for constructing pools. - */ -class PoolFactoryBean implements FactoryBean, BeanNameAware { - - PoolFactory poolFactory - String beanName - - Pool getObject() { - poolFactory.create(beanName) - } - - Class getObjectType() { Pool } - - boolean isSingleton() { true } -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy deleted file mode 100644 index 94076ccae..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy +++ /dev/null @@ -1,191 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.DetachedCriteria - -import spock.lang.Ignore - -class DetachedCriteriaSpec extends GormDatastoreSpec { - - void "Test updateAll method"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria is created that deletes all matching records" - def criteria = new DetachedCriteria(Person).build { - eq 'lastName', 'Simpson' - } - int total = criteria.updateAll(lastName:"Bloggs") - - then:"The number of deletions is correct" - total == 4 - Person.count() == 6 - criteria.count() == 0 - Person.countByLastName("Bloggs") == 4 - } - - void "Test deleteAll method"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria is created that deletes all matching records" - def criteria = new DetachedCriteria(Person).build { - eq 'lastName', 'Simpson' - } - int total = criteria.deleteAll() - - then:"The number of deletions is correct" - total == 4 - Person.count() == 2 - } - - void "Test iterate of detached criteria"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria is created that matches the last name and then iterated over" - def criteria = new DetachedCriteria(Person).build { - eq 'lastName', 'Simpson' - } - int total = 0 - criteria.each { - total++ - } - - then:"The number of iterations is correct" - total == 4 - } - void "Test dynamic finder on detached criteria"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - def result = criteria.findByFirstNameLike("B%") - - then:"The list method returns the right results" - result != null - result.firstName == "Bart" - } - - void "Test get method on detached criteria and additional criteria"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - def result = criteria.get { - like 'firstName', 'B%' - } - then:"The list method returns the right results" - result != null - result.firstName == "Bart" - } - - void "Test list method on detached criteria and additional criteria"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - def results = criteria.list { - like 'firstName', 'B%' - } - then:"The list method returns the right results" - results.size() == 1 - results[0].firstName == "Bart" - - when:"The original detached criteria is queried" - results = criteria.list() - - then:"The additional criteria didn't modify the original instance and the correct results are returned" - results.size() == 4 - results.every { it.lastName == 'Simpson'} - } - - void "Test count method on detached criteria and additional criteria"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria instance is created matching the last name and count is called with additional criteria" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - def result = criteria.count { - like 'firstName', 'B%' - } - then:"The count method returns the right results" - result == 1 - - } - - void "Test count method on detached criteria"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - def result = criteria.count() - then:"The count method returns the right results" - result == 4 - - } - void "Test list method on detached criteria"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - def results = criteria.list() - then:"The list method returns the right results" - results.size() == 4 - results.every { it.lastName == 'Simpson'} - } - - @Ignore // Gemfire doesn't support - void "Test list method on detached criteria with pagination"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.build { - eq 'lastName', 'Simpson' - } - - def results = criteria.list(max: 2) - then:"The list method returns the right results" - results.size() == 2 - results.every { it.lastName == 'Simpson'} - } - - protected void createPeople() { - new Person(firstName: "Homer", lastName: "Simpson").save() - new Person(firstName: "Marge", lastName: "Simpson").save() - new Person(firstName: "Bart", lastName: "Simpson").save() - new Person(firstName: "Lisa", lastName: "Simpson").save() - new Person(firstName: "Barney", lastName: "Rubble").save() - new Person(firstName: "Fred", lastName: "Flinstone").save() - } -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/EnumSpec.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/EnumSpec.groovy deleted file mode 100644 index c9bdb4755..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/EnumSpec.groovy +++ /dev/null @@ -1,120 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -import org.grails.datastore.mapping.core.Session - -// TODO fix querying by enum for Gemfire -class EnumSpec extends GormDatastoreSpec { - - void "Test save()"() { - given: - - EnumThing t = new EnumThing(name: 'e1', en: TestEnum.V1) - - when: - t.save(failOnError: true) - - then: - t != null - !t.hasErrors() - - when: - t = t.get(t.id) - - then: - t != null - 'e1' == t.name - TestEnum.V1 == t.en - } - -// void "Test findBy()"() { -// given: -// -// new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true) -// new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true) -// new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true) -// -// EnumThing instance1 -// EnumThing instance2 -// EnumThing instance3 -// -// when: -// instance1 = EnumThing.findByEn(TestEnum.V1) -// instance2 = EnumThing.findByEn(TestEnum.V2) -// instance3 = EnumThing.findByEn(TestEnum.V3) -// -// then: -// instance1 != null -// instance1.en == TestEnum.V1 -// -// instance2 != null -// instance2.en == TestEnum.V2 -// -// instance3 == null -// } - -// void "Test findAllBy()"() { -// given: -// -// new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true) -// new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true) -// new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true) -// -// def v1Instances -// def v2Instances -// def v3Instances -// -// when: -// v1Instances = EnumThing.findAllByEn(TestEnum.V1) -// v2Instances = EnumThing.findAllByEn(TestEnum.V2) -// v3Instances = EnumThing.findAllByEn(TestEnum.V3) -// -// then: -// v1Instances != null -// v1Instances.size() == 2 -// v1Instances.every { it.en == TestEnum.V1 } -// -// v2Instances != null -// v2Instances.size() == 1 -// v2Instances.every { it.en == TestEnum.V2 } -// -// v3Instances != null -// v3Instances.isEmpty() -// } - -// void "Test countBy()"() { -// given: -// -// new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true) -// new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true) -// new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true) -// -// def v1Count -// def v2Count -// def v3Count -// -// when: -// v1Count = EnumThing.countByEn(TestEnum.V1) -// v2Count = EnumThing.countByEn(TestEnum.V2) -// v3Count = EnumThing.countByEn(TestEnum.V3) -// -// then: -// 2 == v1Count -// 1 == v2Count -// 0 == v3Count -// } -} - -@Entity -class EnumThing { - Long id - Long version - String name - TestEnum en - - static mapping = { - name index: true - en index: true - } -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy deleted file mode 100644 index 7b8653813..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy +++ /dev/null @@ -1,9 +0,0 @@ -package grails.gorm.tests - -/** - * @author Burt Beckwith - */ -class OptimisticLockingSpec { - // TODO implement optimistic locking for Gemfire and delete this - void testNothing() {} -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy deleted file mode 100644 index 2bb20999e..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy +++ /dev/null @@ -1,53 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.PagedResultList - -import spock.lang.Ignore - -/** - * Ignored for Gemfire because Gemfire doesn't support pagination. - */ -@Ignore -class PagedResultSpec extends GormDatastoreSpec { - - void "Test that a paged result list is returned from the list() method with pagination params"() { - given:"Some people" - createPeople() - - when:"The list method is used with pagination params" - def results = Person.list(offset:2, max:2) - - then:"You get a paged result list back" - results instanceof PagedResultList - results.size() == 2 - results[0].firstName == "Bart" - results[1].firstName == "Lisa" - results.totalCount == 6 - } - - void "Test that a paged result list is returned from the critera with pagination params"() { - given:"Some people" - createPeople() - - when:"The list method is used with pagination params" - def results = Person.createCriteria().list(offset:1, max:2) { - eq 'lastName', 'Simpson' - } - - then:"You get a paged result list back" - results instanceof PagedResultList - results.size() == 2 - results[0].firstName == "Marge" - results[1].firstName == "Bart" - results.totalCount == 4 - } - - protected void createPeople() { - new Person(firstName: "Homer", lastName: "Simpson", age:45).save() - new Person(firstName: "Marge", lastName: "Simpson", age:40).save() - new Person(firstName: "Bart", lastName: "Simpson", age:9).save() - new Person(firstName: "Lisa", lastName: "Simpson", age:7).save() - new Person(firstName: "Barney", lastName: "Rubble", age:35).save() - new Person(firstName: "Fred", lastName: "Flinstone", age:41).save() - } -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy deleted file mode 100644 index 3b12204c3..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package grails.gorm.tests - -import org.junit.Ignore - -/** - * Tests for criteria queries that compare two properties. - */ -class PropertyComparisonQuerySpec extends GormDatastoreSpec { - - @Ignore - void "Test eqProperty criterion"() { - // TODO: implement eqProperty query operations - } -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy deleted file mode 100644 index 082db7656..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.tests.GormDatastoreSpec -import org.junit.Ignore - -/** - * Tests for querying the size of collections etc. - */ -class SizeQuerySpec extends GormDatastoreSpec { - - @Ignore - void "Test sizeEq criterion"() { - // TODO: implement sizeEq query operations - } -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/Setup.groovy deleted file mode 100644 index cccf95e70..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ /dev/null @@ -1,70 +0,0 @@ -package org.grails.datastore.gorm - -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.gorm.gemfire.GemfireGormEnhancer -import org.springframework.context.support.GenericApplicationContext -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.gemfire.GemfireDatastore -import org.grails.datastore.mapping.gemfire.config.GormGemfireMappingFactory -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager -import org.springframework.util.StringUtils -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -import com.gemstone.gemfire.cache.DataPolicy - -/** - * @author graemerocher - */ -class Setup { - - static gemfire - - static destroy() { - gemfire?.destroy() - } - - static Session setup(classes) { - def context = new KeyValueMappingContext("") - def factory = new GormGemfireMappingFactory() - factory.defaultDataPolicy = DataPolicy.REPLICATE - context.mappingFactory = factory - def ctx = new GenericApplicationContext() - ctx.refresh() - gemfire = new GemfireDatastore(context, ctx) - gemfire.afterPropertiesSet() - for (cls in classes) { - gemfire.mappingContext.addPersistentEntity(cls) - } - - PersistentEntity entity = gemfire.mappingContext.persistentEntities.find { - PersistentEntity e -> e.name.contains("TestEntity") - } - - gemfire.mappingContext.addEntityValidator(entity, [ - supports: { Class c -> true }, - validate: { Object o, Errors errors -> - if (!StringUtils.hasText(o.name)) { - errors.rejectValue("name", "name.is.blank") - } - } - ] as Validator) - - def enhancer = new GemfireGormEnhancer(gemfire, - new DatastoreTransactionManager(datastore: gemfire)) - enhancer.enhance() - - gemfire.mappingContext.addMappingContextListener({ e -> - enhancer.enhance e - } as MappingContext.Listener) - - gemfire.applicationContext.addApplicationListener new DomainEventListener(gemfire) - gemfire.applicationContext.addApplicationListener new AutoTimestampEventListener(gemfire) - - gemfire.connect() - } -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/ContinuousQuerySpec.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/ContinuousQuerySpec.groovy deleted file mode 100644 index f26f4fb5a..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/ContinuousQuerySpec.groovy +++ /dev/null @@ -1,26 +0,0 @@ -package org.grails.datastore.gorm.gemfire - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Plant -import spock.lang.Ignore - -/** - * @author graemerocher - */ -class ContinuousQuerySpec extends GormDatastoreSpec { - - @Ignore - void "Test that we receive insert events from a continuous query"() { - given: - Plant.cq.findAllByGoesInPatch(true) { event -> - println "GOT EVENT ${event}" - } - - when: - sleep(1000) - def p = new Plant(name:"cabbage", goesInPatch:true).save() - - then: - 1 == Plant.count() - } -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/FunctionExecutionSpec.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/FunctionExecutionSpec.groovy deleted file mode 100644 index f50bfa012..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/FunctionExecutionSpec.groovy +++ /dev/null @@ -1,44 +0,0 @@ -package org.grails.datastore.gorm.gemfire - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Plant -import spock.lang.Ignore - -/** - * @author graemerocher - */ -class FunctionExecutionSpec extends GormDatastoreSpec { - - @Ignore - void "Test a function can be invoked"() { - given: - def p = new Plant(name:"cabbage", goesInPatch:true).save() - - when: - def results = Plant.executeFunction { - it.lastResult it.localData[p.id] - } - - then: - p != null - results != null - results.size() == 1 - } - - @Ignore - void "Test a function can be invoked with a filter"() { - given: - def p1 = new Plant(name:"cabbage", goesInPatch:true).save() - def p2 = new Plant(name:"carrot", goesInPatch:true).save() - - when: - def results = Plant.executeFunction([p1.id]) { - it.lastResult it.localData[it.filter.iterator().next()] - } - - then: - results != null - results.size() == 1 - results[0].name == 'cabbage' - } -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/GemfireMappingConfigSpec.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/GemfireMappingConfigSpec.groovy deleted file mode 100644 index d3e4c4701..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/GemfireMappingConfigSpec.groovy +++ /dev/null @@ -1,38 +0,0 @@ -package org.grails.datastore.gorm.gemfire - -import grails.gorm.tests.GormDatastoreSpec - -import org.grails.datastore.mapping.gemfire.config.Region - -import com.gemstone.gemfire.cache.DataPolicy - -/** - * @author graemerocher - */ -class GemfireMappingConfigSpec extends GormDatastoreSpec { - - void "Test custom region configuration"() { - given: - session.mappingContext.addPersistentEntity(CustomConfig) - - when: - def entity = session.mappingContext.getPersistentEntity(CustomConfig.name) - Region region = entity.mapping.mappedForm - - then: - region != null - region.dataPolicy == DataPolicy.PARTITION - region.region == "foo" - } -} - -class CustomConfig { - - Long id - String name - - static mapping = { - dataPolicy DataPolicy.PARTITION - region "foo" - } -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/GemfireSuite.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/GemfireSuite.groovy deleted file mode 100644 index 470cce347..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/GemfireSuite.groovy +++ /dev/null @@ -1,42 +0,0 @@ -package org.grails.datastore.gorm.gemfire - -import grails.gorm.tests.* -import org.junit.runners.Suite.SuiteClasses -import org.junit.runners.Suite -import org.junit.runner.RunWith - -/** - * @author graemerocher - */ -@RunWith(Suite) -@SuiteClasses([ -// RangeQuerySpec, -// NamedQuerySpec, -//OneToOneSpec, -// CriteriaBuilderSpec, -// OrderBySpec, -// CommonTypesPersistenceSpec, -// QueryAfterPropertyChangeSpec, -// QueryByAssociationSpec, -// UpdateWithProxyPresentSpec, -// DomainEventsSpec - PersistenceEventListenerSpec -// ProxyLoadingSpec, -// QueryAfterPropertyChangeSpec, -// CircularOneToManySpec, -// InheritanceSpec, -// FindByMethodSpec, -// ListOrderBySpec, -// GroovyProxySpec, -// CommonTypesPersistenceSpec, -// GormEnhancerSpec, -// NegationSpec, -// -// ValidationSpec, -// UpdateWithProxyPresentSpec, -// AttachMethodSpec, -// WithTransactionSpec, -// CrudOperationsSpec -]) -class GemfireSuite { -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/GemfireUuidSpec.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/GemfireUuidSpec.groovy deleted file mode 100644 index 3084cbfd7..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/GemfireUuidSpec.groovy +++ /dev/null @@ -1,44 +0,0 @@ -package org.grails.datastore.gorm.gemfire - -import grails.gorm.tests.GormDatastoreSpec - -/** - * @author Burt Beckwith - */ -class GemfireUuidSpec extends GormDatastoreSpec { - - void "Test UUID"() { - given: - session.datastore.mappingContext.addPersistentEntity UsesUuid - def u = new UsesUuid(name: 'Bob').save(flush: true) - session.clear() - - when: - u = UsesUuid.get(u.id) - - then: - u.name == 'Bob' - u.id instanceof String - u.id ==~ /[a-f\d]{8}\-[a-f\d]{4}\-[a-f\d]{4}\-[a-f\d]{4}\-[a-f\d]{12}/ - - when: - u = UsesUuid.get(u.id) - u.name = 'Not Bob' - u.save(flush: true) - session.clear() - u = UsesUuid.get(u.id) - - then: - u.name == 'Not Bob' - } -} - -class UsesUuid { - - String id - String name - - static mapping = { - id generator: 'uuid' - } -} diff --git a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/OqlQuerySpec.groovy b/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/OqlQuerySpec.groovy deleted file mode 100644 index a5f429452..000000000 --- a/grails-datastore-gorm-gemfire/src/test/groovy/org/grails/datastore/gorm/gemfire/OqlQuerySpec.groovy +++ /dev/null @@ -1,128 +0,0 @@ -package org.grails.datastore.gorm.gemfire - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Plant - -/** - * @author graemerocher - */ -class OqlQuerySpec extends GormDatastoreSpec{ - - void "test executeQuery method"() { - given: - new Plant(name:"rose", goesInPatch:false).save() - new Plant(name:"oak", goesInPatch:false).save() - new Plant(name:"daisy", goesInPatch:true).save(flush:true) - - when: - def results = Plant.executeQuery("goesInPatch = false") - - then: - results.size() == 2 - } - - void "test executeQuery method with positional parameters"() { - given: - new Plant(name:"rose", goesInPatch:false).save() - new Plant(name:"oak", goesInPatch:false).save() - new Plant(name:"daisy", goesInPatch:true).save(flush:true) - - when: - def results = Plant.executeQuery('goesInPatch = $1', [false]) - - then: - results.size() == 2 - } - - void "test findAll method"() { - given: - new Plant(name:"rose", goesInPatch:false).save() - new Plant(name:"oak", goesInPatch:false).save() - new Plant(name:"daisy", goesInPatch:true).save(flush:true) - - when: - def results = Plant.findAll("goesInPatch = false") - - then: - results.size() == 2 - } - - void "test findAll method with arguments"() { - given: - new Plant(name:"rose", goesInPatch:false).save() - new Plant(name:"oak", goesInPatch:false).save() - new Plant(name:"daisy", goesInPatch:true).save(flush:true) - - when: - def results = Plant.findAll("goesInPatch = false", [sort:'name']).sort { it.name } - - then: - results.size() == 2 - results[0].name == 'oak' - results[1].name == 'rose' - - when: - results = Plant.findAll("goesInPatch = false", [sort:'name', order:"desc"]).sort { it.name }.reverse() - - then: - results.size() == 2 - results[0].name == 'rose' - results[1].name == 'oak' - } - - void "test findAll method with positional parameters"() { - given: - new Plant(name:"rose", goesInPatch:false).save() - new Plant(name:"oak", goesInPatch:false).save() - new Plant(name:"daisy", goesInPatch:true).save(flush:true) - - when: - def results = Plant.findAll('goesInPatch = $1', [false]) - - then: - results.size() == 2 - } - - void "test findAll method with positional parameters and arguments"() { - given: - new Plant(name:"rose", goesInPatch:false).save() - new Plant(name:"oak", goesInPatch:false).save() - new Plant(name:"daisy", goesInPatch:true).save(flush:true) - - when: - def results = Plant.findAll('goesInPatch = $1', [false], [sort:'name']).sort { it.name } - - then: - results.size() == 2 - results[0].name == 'oak' - results[1].name == 'rose' - } - - void "test find method"() { - given: - new Plant(name:"rose", goesInPatch:false).save() - new Plant(name:"oak", goesInPatch:false).save() - new Plant(name:"daisy", goesInPatch:true).save(flush:true) - - when: - def result = Plant.find("name = 'rose'") - - then: - result != null - result.name == 'rose' - } - - void "test find method with positional parameters"() { - given: - new Plant(name:"rose", goesInPatch:false).save() - new Plant(name:"oak", goesInPatch:false).save() - new Plant(name:"daisy", goesInPatch:true).save(flush:true) - - when: - def result = Plant.find('name = $1', ['rose']) - - then: - result != null - result.name == 'rose' - } -} diff --git a/grails-datastore-gorm-hibernate-core/build.gradle b/grails-datastore-gorm-hibernate-core/build.gradle deleted file mode 100644 index 8981ba4e3..000000000 --- a/grails-datastore-gorm-hibernate-core/build.gradle +++ /dev/null @@ -1,141 +0,0 @@ -configurations { - provided -} - -dependencies { - - provided("org.grails:grails-core:$grailsVersion") { - exclude group:'commons-logging',module:'commons-logging' - } - provided("org.grails:grails-bootstrap:$grailsVersion") - provided("org.grails:grails-plugin-domain-class:$grailsVersion") { - exclude group: 'org.grails', module:'grails-plugin-testing' - exclude group: 'org.grails', module:'grails-datastore-core' - exclude group: 'org.grails', module:'grails-datastore-gorm' - exclude group: 'org.grails', module:'grails-datastore-simple' - } - provided("org.grails:grails-web:$grailsVersion") - provided 'javax.servlet:servlet-api:2.5' - - provided(project(":grails-datastore-gorm")) { - exclude group: 'org.grails', module:'grails-bootstrap' - exclude group: 'org.grails', module:'grails-core' - exclude group: 'org.grails', module:'grails-async' - exclude group: 'org.grails', module:'grails-plugin-testing' - exclude group: 'org.slf4j', module:'jcl-over-slf4j' - exclude group: 'org.slf4j', module:'jul-to-slf4j' - exclude group: 'org.slf4j', module:'slf4j-api' - exclude group: 'org.slf4j', module:'slf4j-simple' - } - provided(project(":grails-datastore-gorm-plugin-support")) { - exclude group: 'org.grails', module:'grails-bootstrap' - exclude group: 'org.grails', module:'grails-core' - exclude group: 'org.grails', module:'grails-plugin-testing' - } - provided(project(":grails-datastore-core")) { - exclude group: 'org.grails', module:'grails-plugin-testing' - } - - provided "org.springframework:spring-jdbc:$springVersion" - provided "org.springframework:spring-orm:$springVersion" - provided "org.springframework:spring-tx:$springVersion" - provided "org.springframework:spring-web:$springVersion" - - provided 'javax.transaction:jta:1.1' - - provided 'org.hibernate:hibernate-entitymanager:3.6.10.Final', { - exclude group: 'javassist', module: 'javassist' - } - provided('org.hibernate:hibernate-core:3.6.10.Final') { - exclude group:'commons-logging', module:'commons-logging' - exclude group:'commons-collections', module:'commons-collections' - exclude group:'org.slf4j', module:'slf4j-api' - exclude group:'xml-apis', module:'xml-apis' - exclude group:'dom4j', module:'dom4j' - exclude group:'antlr', module: 'antlr' - } - provided('org.hibernate:hibernate-commons-annotations:3.2.0.Final'){ - exclude group: 'org.slf4j', module:'slf4j-api' - exclude group: 'commons-logging', module:'commons-logging' - } - provided('org.hibernate:hibernate-validator:4.1.0.Final') { - exclude group:'commons-logging', module:'commons-logging' - exclude group:'commons-collections', module:'commons-collections' - exclude group:'org.slf4j', module:'slf4j-api' - } - provided('org.hibernate:hibernate-ehcache:3.6.10.Final') { - exclude group:'commons-logging', module:'commons-logging' - exclude group:'commons-collections', module:'commons-collections' - exclude group:'org.slf4j', module:'slf4j-api' - exclude group:'xml-apis', module:'xml-apis' - exclude group:'dom4j', module:'dom4j' - exclude group:'org.hibernate', module:'hibernate-core' - exclude group:'net.sf.ehcache', module:'ehcache' - exclude group:'net.sf.ehcache', module:'ehcache-core' - } - - provided 'org.javassist:javassist:3.17.1-GA' - provided 'javax.transaction:jta:1.1' - provided('dom4j:dom4j:1.6.1') { - exclude group: 'xml-apis', module:'xml-apis' - } - - provided ("net.sf.ehcache:ehcache-core:2.4.6") { - exclude group: 'commons-logging', module:'commons-logging' - } - provided ('antlr:antlr:2.7.7') { - exclude group: 'commons-logging', module:'commons-logging' - } - provided 'javax.validation:validation-api:1.0.0.GA' - - provided "commons-lang:commons-lang:2.4" - provided("commons-beanutils:commons-beanutils:1.8.0") { - exclude group: 'commons-logging', module:'commons-logging' - } - - testCompile project(":grails-datastore-gorm-test") - testCompile project(":grails-datastore-gorm-tck") - testCompile "com.h2database:h2:1.3.164" - - testCompile("org.grails:grails-core:$grailsVersion") - testCompile("org.grails:grails-bootstrap:$grailsVersion") - testCompile("org.grails:grails-plugin-domain-class:$grailsVersion") { - transitive = false - exclude group: 'org.grails', module:'grails-plugin-testing' - exclude group: 'org.grails', module:'grails-datastore-core' - exclude group: 'org.grails', module:'grails-datastore-gorm' - exclude group: 'org.grails', module:'grails-datastore-simple' - } - testCompile("org.grails:grails-web:$grailsVersion") - testCompile("org.grails:grails-plugin-controllers:$grailsVersion") { - transitive = false - exclude group: 'org.grails', module:'grails-plugin-domain-class' - exclude group: 'org.grails', module:'grails-web' - } - testCompile("org.grails:grails-plugin-validation:$grailsVersion") { - exclude group: 'org.grails', module:'grails-plugin-domain-class' - } - - testRuntime "javax.servlet:servlet-api:2.5" -} - -sourceSets { - main { - compileClasspath += configurations.provided - } - javadoc { - classpath = configurations.provided - } -} - -idea { - module { - scopes.PROVIDED.plus += configurations.provided - } -} -/* -test { - jvmArgs '-Xmx1024m', '-Xdebug', '-Xnoagent', '-Dgrails.full.stacktrace=true', '-Djava.compiler=NONE', - '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005' -} -*/ 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 deleted file mode 100644 index 908adf559..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractEventTriggeringInterceptor.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 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.codehaus.groovy.grails.orm.hibernate; - -import java.util.Collections; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -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.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener; -import org.hibernate.SessionFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationEvent; - -/** - *

    Invokes closure events on domain entities such as beforeInsert, beforeUpdate and beforeDelete. - * - * @author Graeme Rocher - * @author Lari Hotari - * @author Burt Beckwith - * @since 2.0 - */ -public abstract class AbstractEventTriggeringInterceptor extends AbstractPersistenceEventListener { - - protected transient ConcurrentMap>, Boolean> cachedShouldTrigger = - new ConcurrentHashMap>, Boolean>(); - protected boolean failOnError; - protected List failOnErrorPackages = Collections.emptyList(); - protected Logger log = LoggerFactory.getLogger(getClass()); - - protected AbstractEventTriggeringInterceptor(Datastore datastore) { - super(datastore); - } - - protected boolean isDefinedByCurrentDataStore(Object entity, AbstractGrailsDomainBinder binder) { - SessionFactory currentDataStoreSessionFactory = ((AbstractHibernateDatastore) datastore).getSessionFactory(); - ApplicationContext applicationContext = datastore.getApplicationContext(); - - Mapping mapping = binder.getMapping(entity.getClass()); - List dataSourceNames = null; - if (mapping == null) { - GrailsApplication grailsApplication = applicationContext.getBean("grailsApplication", GrailsApplication.class); - GrailsDomainClass dc = (GrailsDomainClass) grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, entity.getClass().getName()); - if (dc != null) { - dataSourceNames = getDatasourceNames(dc); - } - } - else { - dataSourceNames = mapping.getDatasources(); - } - - if (dataSourceNames == null) { - return false; - } - - for (String dataSource : dataSourceNames) { - if (GrailsDomainClassProperty.ALL_DATA_SOURCES.equals(dataSource)) { - return true; - } - boolean isDefault = dataSource.equals(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE); - String suffix = isDefault ? "" : "_" + dataSource; - String sessionFactoryBeanName = "sessionFactory" + suffix; - - if (applicationContext.containsBean(sessionFactoryBeanName)) { - SessionFactory sessionFactory = applicationContext.getBean(sessionFactoryBeanName, SessionFactory.class); - if (currentDataStoreSessionFactory == sessionFactory) { - return true; - } - } - else { - log.warn("Cannot resolve SessionFactory for dataSource {} and entity {}", - new Object[] { dataSource, entity.getClass().getName()}); - } - } - return false; - } - - protected abstract List getDatasourceNames(GrailsDomainClass dc); - - /** - * {@inheritDoc} - * @see org.springframework.context.event.SmartApplicationListener#supportsEventType( - * java.lang.Class) - */ - public boolean supportsEventType(Class eventType) { - return AbstractPersistenceEvent.class.isAssignableFrom(eventType); - } -} 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 deleted file mode 100644 index 823e6d506..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractGrailsHibernateDomainClass.java +++ /dev/null @@ -1,303 +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; - -import java.beans.PropertyDescriptor; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashMap; -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 org.hibernate.SessionFactory; -import org.hibernate.metadata.ClassMetadata; -import org.hibernate.type.AnyType; -import org.hibernate.type.AssociationType; -import org.hibernate.type.Type; -import org.springframework.context.ApplicationContext; -import org.springframework.context.MessageSource; -import org.springframework.core.type.StandardAnnotationMetadata; -import org.springframework.validation.Validator; - -@SuppressWarnings("rawtypes") -public abstract class AbstractGrailsHibernateDomainClass extends AbstractGrailsClass implements ExternalGrailsDomainClass { - - public static final String HIBERNATE = "hibernate"; - - protected GrailsHibernateDomainClassProperty identifier; - protected GrailsHibernateDomainClassProperty version; - - protected GrailsDomainClassProperty[] properties; - - protected Map propertyMap = new LinkedHashMap(); - - protected Validator validator; - protected GrailsApplication application; - protected SessionFactory sessionFactory; - protected String sessionFactoryName; - - protected Set subClasses = new HashSet(); - protected Map constraints = Collections.emptyMap(); - - /** - * Contructor to be used by all child classes to create a new instance - * and get the name right. - * - * @param clazz the Grails class - * @param sessionFactory The Hibernate SessionFactory instance - * @param sessionFactoryName - * @param application - * @param metaData The ClassMetaData for this class retrieved from the SF - */ - public AbstractGrailsHibernateDomainClass(Class clazz, SessionFactory sessionFactory, String sessionFactoryName, - GrailsApplication application, ClassMetadata metaData) { - super(clazz, ""); - this.application = application; - this.sessionFactory = sessionFactory; - this.sessionFactoryName = sessionFactoryName; - - new StandardAnnotationMetadata(clazz); - String ident = metaData.getIdentifierPropertyName(); - if (ident != null) { - Class identType = getPropertyType(ident); - identifier = new GrailsHibernateDomainClassProperty(this, ident); - identifier.setIdentity(true); - identifier.setType(identType); - propertyMap.put(ident, identifier); - } - - // configure the version property - final int versionIndex = metaData.getVersionProperty(); - String versionPropertyName = null; - if (versionIndex >- 1) { - versionPropertyName = metaData.getPropertyNames()[versionIndex]; - version = new GrailsHibernateDomainClassProperty(this, versionPropertyName); - version.setType(getPropertyType(versionPropertyName)); - } - - // configure remaining properties - String[] propertyNames = metaData.getPropertyNames(); - for (String propertyName : propertyNames) { - if (!propertyName.equals(ident) && !(versionPropertyName != null && - propertyName.equals(versionPropertyName))) { - - PropertyDescriptor pd = GrailsClassUtils.getProperty(clazz,propertyName); - if (pd == null) continue; - - GrailsHibernateDomainClassProperty prop = new GrailsHibernateDomainClassProperty(this, propertyName); - prop.setType(getPropertyType(propertyName)); - Type hibernateType = metaData.getPropertyType(propertyName); - - // if its an association type - if (hibernateType.isAssociationType()) { - prop.setAssociation(true); - // get the associated type from the session factory and set it on the property - AssociationType assType = (AssociationType) hibernateType; - if (assType instanceof AnyType) { - continue; - } - setRelatedClassType(prop, assType, hibernateType); - // configure type of relationship - if (hibernateType.isCollectionType()) { - prop.setOneToMany(true); - } - else if (hibernateType.isEntityType()) { - prop.setManyToOne(true); - // might not really be true, but for our purposes this is ok - prop.setOneToOne(true); - } - } - propertyMap.put(propertyName, prop); - } - } - - properties = propertyMap.values().toArray(new GrailsDomainClassProperty[propertyMap.size()]); - // process the constraints - evaluateConstraints(); - } - - protected abstract void setRelatedClassType(GrailsHibernateDomainClassProperty prop, AssociationType assType, Type hibernateType); - - public SessionFactory getSessionFactory() { - return sessionFactory; - } - - public String getSessionFactoryName() { - return sessionFactoryName; - } - - /** - * Evaluates the constraints closure to build the list of constraints. - */ - protected void evaluateConstraints() { - Map existing = (Map) getPropertyOrStaticPropertyOrFieldValue(GrailsDomainClassProperty.CONSTRAINTS, Map.class); - if (existing == null) { - constraints = getConstraintsEvaluator().evaluate(getClazz(), getProperties()); - } - else { - constraints = existing; - } - } - - protected ConstraintsEvaluator getConstraintsEvaluator() { - if (application != null && application.getMainContext() != null) { - final ApplicationContext context = application.getMainContext(); - if (context.containsBean(ConstraintsEvaluator.BEAN_NAME)) { - return context.getBean(ConstraintsEvaluator.BEAN_NAME, ConstraintsEvaluator.class); - } - } - return new DefaultConstraintEvaluator(); - } - - public boolean isOwningClass(Class domainClass) { - return false; - } - - public GrailsDomainClassProperty[] getProperties() { - return properties; - } - - /** - * @deprecated - */ - @Deprecated - public GrailsDomainClassProperty[] getPersistantProperties() { - return properties; - } - - public GrailsDomainClassProperty[] getPersistentProperties() { - return properties; - } - - public GrailsDomainClassProperty getIdentifier() { - return identifier; - } - - public GrailsDomainClassProperty getVersion() { - return version; - } - - public GrailsDomainClassProperty getPersistentProperty(String name) { - if (propertyMap.containsKey(name)) { - return propertyMap.get(name); - } - - return null; - } - - public GrailsDomainClassProperty getPropertyByName(String name) { - if (propertyMap.containsKey(name)) { - return propertyMap.get(name); - } - - throw new InvalidPropertyException("No property found for name ["+name+"] for class ["+getClazz()+"]"); - } - - public String getFieldName(String propertyName) { - return getPropertyByName(propertyName).getFieldName(); - } - - public boolean hasSubClasses() { - return false; - } - - public Map getMappedBy() { - return Collections.emptyMap(); - } - - public boolean hasPersistentProperty(String propertyName) { - for (GrailsDomainClassProperty persistantProperty : properties) { - if (persistantProperty.getName().equals(propertyName)) return true; - } - return false; - } - - public void setMappingStrategy(String strategy) { - // do nothing, read-only - } - - public boolean isOneToMany(String propertyName) { - GrailsDomainClassProperty prop = getPropertyByName(propertyName); - return prop != null && prop.isOneToMany(); - } - - public boolean isManyToOne(String propertyName) { - GrailsDomainClassProperty prop = getPropertyByName(propertyName); - return prop != null && prop.isManyToOne(); - } - - public boolean isBidirectional(String propertyName) { - return false; - } - - public Class getRelatedClassType(String propertyName) { - GrailsDomainClassProperty prop = getPropertyByName(propertyName); - if (prop == null) { - return null; - } - - return prop.getReferencedPropertyType(); - } - - public Map getConstrainedProperties() { - return constraints; - } - - public Validator getValidator() { - if (validator == null) { - GrailsDomainClassValidator gdcv = new GrailsDomainClassValidator(); - gdcv.setDomainClass(this); - MessageSource messageSource = application.getMainContext().getBean(MessageSource.class); - gdcv.setMessageSource(messageSource); - validator = gdcv; - } - return validator; - } - - public void setValidator(Validator validator) { - this.validator = validator; - } - - public String getMappingStrategy() { - return HIBERNATE; - } - - @SuppressWarnings("unchecked") - public Set getSubClasses() { - return subClasses; - } - - public void refreshConstraints() { - evaluateConstraints(); - } - - public boolean isRoot() { - return getClazz().getSuperclass().equals(Object.class); - } - - public Map getAssociationMap() { - return Collections.emptyMap(); - } -} 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 deleted file mode 100644 index e1abd7ad4..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateDatastore.java +++ /dev/null @@ -1,65 +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.codehaus.groovy.grails.orm.hibernate; - -import groovy.util.ConfigObject; - -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.model.MappingContext; -import org.hibernate.SessionFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; - -/** - * Datastore implementation that uses a Hibernate SessionFactory underneath. - * - * @author Graeme Rocher - * @since 2.0 - */ -public abstract class AbstractHibernateDatastore extends AbstractDatastore implements ApplicationContextAware { - - protected SessionFactory sessionFactory; - protected ConfigObject config; - protected AbstractEventTriggeringInterceptor eventTriggeringInterceptor; - - protected AbstractHibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config) { - super(mappingContext); - this.sessionFactory = sessionFactory; - this.config = config; - initializeConverters(mappingContext); - } - - public AbstractHibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config, ApplicationContext applicationContext) { - this(mappingContext, sessionFactory, config); - setApplicationContext(applicationContext); - } - - /** - * @return The Hibernate {@link SessionFactory} being used by this datastore instance - */ - public SessionFactory getSessionFactory() { - return sessionFactory; - } - - @Override - protected boolean registerValidationListener() { - return false; - } - - // for testing - public AbstractEventTriggeringInterceptor getEventTriggeringInterceptor() { - return eventTriggeringInterceptor; - } -} 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 deleted file mode 100644 index de10c30b4..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormEnhancer.groovy +++ /dev/null @@ -1,68 +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.codehaus.groovy.grails.orm.hibernate - -import groovy.transform.CompileStatic - -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.orm.hibernate.cfg.HibernateNamedQueriesBuilder -import org.grails.datastore.gorm.GormEnhancer -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 -import org.grails.datastore.mapping.proxy.ProxyFactory -import org.grails.datastore.mapping.model.types.ToOne - -@CompileStatic -abstract class AbstractHibernateGormEnhancer extends GormEnhancer { - - protected ClassLoader classLoader - protected GrailsApplication grailsApplication - - protected AbstractHibernateGormEnhancer(AbstractHibernateDatastore datastore, - PlatformTransactionManager transactionManager, - GrailsApplication grailsApplication) { - super(datastore, transactionManager) - this.grailsApplication = grailsApplication - classLoader = grailsApplication.classLoader - getFinders() - } - - @Override - protected void registerConstraints(Datastore datastore) { - // no-op - } - - @Override - protected void registerNamedQueries(PersistentEntity entity, namedQueries) { - if (grailsApplication == null) { - return - } - - def domainClass = grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, entity.name) - if (domainClass) { - new HibernateNamedQueriesBuilder(domainClass, getFinders(), entity.mappingContext.conversionService).evaluate((Closure)namedQueries) - } - } - - protected void registerAssociationIdentifierGetter(ProxyFactory proxyFactory, MetaClass metaClass, ToOne association) { - // 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 deleted file mode 100644 index 2c9b4c3cd..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy +++ /dev/null @@ -1,45 +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 - -import groovy.transform.CompileStatic - -import org.grails.datastore.gorm.GormInstanceApi -import org.hibernate.SessionFactory - -@CompileStatic -class AbstractHibernateGormInstanceApi extends GormInstanceApi { - protected static final Object[] EMPTY_ARRAY = [] - - protected SessionFactory sessionFactory - protected ClassLoader classLoader - protected boolean cacheQueriesByDefault = false - - Map config = Collections.emptyMap() - - protected AbstractHibernateGormInstanceApi(Class persistentClass, AbstractHibernateDatastore datastore, ClassLoader classLoader) { - super(persistentClass, datastore) - this.classLoader = classLoader - sessionFactory = datastore.getSessionFactory() - } - - 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-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 deleted file mode 100644 index 06e872078..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateGormValidationApi.groovy +++ /dev/null @@ -1,69 +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 - -import groovy.transform.CompileStatic - -import org.grails.datastore.gorm.GormValidationApi -import groovy.transform.CompileStatic - -import org.codehaus.groovy.grails.commons.metaclass.DynamicMethodInvocation -import org.grails.datastore.gorm.GormValidationApi - -@CompileStatic -abstract class AbstractHibernateGormValidationApi extends GormValidationApi { - - protected ClassLoader classLoader - - protected AbstractHibernateGormValidationApi(Class persistentClass, AbstractHibernateDatastore datastore, ClassLoader classLoader) { - super(persistentClass, datastore) - this.classLoader = classLoader - } - - protected abstract DynamicMethodInvocation getValidateMethod() - - @Override - boolean validate(D instance) { - if (getValidateMethod()) { - return getValidateMethod().invoke(instance, "validate", [] as Object[]) - } - return super.validate(instance) - } - - @Override - boolean validate(D instance, boolean evict) { - if (getValidateMethod()) { - return getValidateMethod().invoke(instance, "validate", [evict] as Object[]) - } - return super.validate(instance, evict) - } - - @Override - boolean validate(D instance, Map arguments) { - if (getValidateMethod()) { - return getValidateMethod().invoke(instance, "validate", [arguments] as Object[]) - } - return super.validate(instance, arguments) - } - - @Override - boolean validate(D instance, List fields) { - if (getValidateMethod()) { - return getValidateMethod().invoke(instance, "validate", [fields] as Object[]) - } - return super.validate(instance, fields) - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateSession.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateSession.java deleted file mode 100644 index 7572d178a..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/AbstractHibernateSession.java +++ /dev/null @@ -1,177 +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.codehaus.groovy.grails.orm.hibernate; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import org.grails.datastore.mapping.core.AbstractAttributeStoringSession; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.transactions.Transaction; -import org.hibernate.LockMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; - -/** - * Session implementation that wraps a Hibernate {@link Session}. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractHibernateSession extends AbstractAttributeStoringSession { - - protected AbstractHibernateDatastore datastore; - protected boolean connected = true; - protected IHibernateTemplate hibernateTemplate; - - protected AbstractHibernateSession(AbstractHibernateDatastore hibernateDatastore, SessionFactory sessionFactory) { - datastore = hibernateDatastore; - } - - public Serializable insert(Object o) { - return persist(o); - } - - @Override - public boolean isConnected() { - return connected; - } - - @Override - public void disconnect() { - connected = false; // don't actually do any disconnection here. This will be handled by OSVI - } - - public Transaction beginTransaction() { - throw new UnsupportedOperationException("Use HibernatePlatformTransactionManager instead"); - } - - public MappingContext getMappingContext() { - return getDatastore().getMappingContext(); - } - - public Serializable persist(Object o) { - return hibernateTemplate.save(o); - } - - public void refresh(Object o) { - hibernateTemplate.refresh(o); - } - - public void attach(Object o) { - hibernateTemplate.lock(o, LockMode.NONE); - } - - public void flush() { - hibernateTemplate.flush(); - } - - public void clear() { - hibernateTemplate.clear(); - } - - public void clear(Object o) { - hibernateTemplate.evict(o); - } - - public boolean contains(Object o) { - return hibernateTemplate.contains(o); - } - - public void lock(Object o) { - hibernateTemplate.lock(o, LockMode.PESSIMISTIC_WRITE); - } - - public void unlock(Object o) { - // do nothing - } - - public List persist(Iterable objects) { - List identifiers = new ArrayList(); - for (Object object : objects) { - identifiers.add(hibernateTemplate.save(object)); - } - return identifiers; - } - - public T retrieve(Class type, Serializable key) { - return hibernateTemplate.get(type, key); - } - - public T proxy(Class type, Serializable key) { - return hibernateTemplate.load(type, key); - } - - public T lock(Class type, Serializable key) { - return hibernateTemplate.get(type, key, LockMode.PESSIMISTIC_WRITE); - } - - public void delete(Iterable objects) { - Collection list = getIterableAsCollection(objects); - hibernateTemplate.deleteAll(list); - } - - @SuppressWarnings("unchecked") - protected Collection getIterableAsCollection(Iterable objects) { - Collection list; - if (objects instanceof Collection) { - list = (Collection)objects; - } - else { - list = new ArrayList(); - for (Object object : objects) { - list.add(object); - } - } - return list; - } - - public void delete(Object obj) { - hibernateTemplate.delete(obj); - } - - public List retrieveAll(Class type, Serializable... keys) { - return retrieveAll(type, Arrays.asList(keys)); - } - - public Persister getPersister(Object o) { - return null; - } - - public Transaction getTransaction() { - throw new UnsupportedOperationException("Use HibernatePlatformTransactionManager instead"); - } - - public Datastore getDatastore() { - return datastore; - } - - public boolean isDirty(Object o) { - // not used, Hibernate manages dirty checking itself - return true; - } - - public Object getNativeInterface() { - return hibernateTemplate; - } - - -} 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 deleted file mode 100644 index dc3b3487c..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClassProperty.java +++ /dev/null @@ -1,262 +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; - -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; - -/** - * An implementation of the GrailsDomainClassProperty interface that allows Classes mapped in - * Hibernate to integrate with Grails' validation, dynamic methods etc. seamlessly. - * - * @author Graeme Rocher - * @since 0.1 - */ -public class GrailsHibernateDomainClassProperty implements GrailsDomainClassProperty { - protected AbstractGrailsHibernateDomainClass domainClass; - - protected String name; - protected String naturalName; - protected Class type; - protected boolean identity; - protected boolean oneToOne; - protected boolean manyToOne; - protected boolean association; - protected boolean oneToMany; - protected boolean manyToMany; - protected boolean bidirectional; - protected boolean optional; - protected Class relatedClassType; - protected GrailsDomainClass referencedDomainClass; - protected GrailsDomainClassProperty otherSide; - protected boolean owingSide; - protected String columnName; - protected boolean explicitSaveUpdateCascade; - - public GrailsHibernateDomainClassProperty(AbstractGrailsHibernateDomainClass domainClass, String propertyName) { - this.domainClass = domainClass; - name = propertyName; - naturalName = GrailsNameUtils.getNaturalName(propertyName); - } - - public String getName() { - return name; - } - - public Class getType() { - if (type == null) { - attemptResolveType(); - } - return type; - } - - protected void attemptResolveType() { - PropertyDescriptor propertyDescriptor = BeanUtils.getPropertyDescriptor(domainClass.getClazz(), name); - type = propertyDescriptor == null ? null : propertyDescriptor.getPropertyType(); - if (type == null) { - Field field = ReflectionUtils.findField(domainClass.getClazz(), name); - if (field != null) { - type = field.getType(); - } - } - } - - public void setType(Class type) { - this.type = type; - } - - public String getTypePropertyName() { - return GrailsNameUtils.getPropertyNameRepresentation(type); - } - - public GrailsDomainClass getDomainClass() { - return domainClass; - } - - public boolean isPersistent() { - return true; - } - - public String getNaturalName() { - return naturalName; - } - - public void setReferencedDomainClass(GrailsDomainClass referencedGrailsDomainClass) { - this.referencedDomainClass = referencedGrailsDomainClass; - } - - public void setOtherSide(GrailsDomainClassProperty referencedProperty) { - otherSide = referencedProperty; - } - - public boolean isExplicitSaveUpdateCascade() { - return explicitSaveUpdateCascade; - } - - public void setExplicitSaveUpdateCascade(boolean explicitSaveUpdateCascade) { - this.explicitSaveUpdateCascade = explicitSaveUpdateCascade; - } - - public GrailsDomainClassProperty getOtherSide() { - return otherSide; - } - - public Class getReferencedPropertyType() { - return relatedClassType; - } - - public boolean isIdentity() { - return identity; - } - - public void setIdentity(boolean identity) { - this.identity = identity; - } - - public boolean isOptional() { - return optional; - } - - public void setOptional(boolean optional) { - this.optional = optional; - } - - public boolean isOneToOne() { - return oneToOne; - } - - public void setOneToOne(boolean oneToOne) { - this.oneToOne = oneToOne; - } - - public boolean isManyToOne() { - return manyToOne; - } - - public void setManyToOne(boolean manyToOne) { - this.manyToOne = manyToOne; - } - - public boolean isAssociation() { - return association; - } - - public boolean isEnum() { - return getType().isEnum(); - } - - public void setAssociation(boolean association) { - this.association = association; - } - - public boolean isOneToMany() { - return oneToMany; - } - - public void setOneToMany(boolean oneToMany) { - this.oneToMany = oneToMany; - } - - public boolean isManyToMany() { - return manyToMany; - } - - public void setManyToMany(boolean manyToMany) { - this.manyToMany = manyToMany; - } - - public boolean isBidirectional() { - return bidirectional; - } - - public String getFieldName() { - return getName().toUpperCase(); - } - - public void setBidirectional(boolean bidirectional) { - this.bidirectional = bidirectional; - } - - public GrailsDomainClass getReferencedDomainClass() { - return referencedDomainClass; - } - - public void setRelatedClassType(Class relatedType) { - relatedClassType = relatedType; - } - - public boolean isInherited() { - return false; - } - - public int getFetchMode() { - return FETCH_LAZY; - } - - public boolean isOwningSide() { - return owingSide; - } - - public boolean isCircular() { - return false; - } - - public String getReferencedPropertyName() { - return null; - } - - public boolean isEmbedded() { - return false; - } - - public GrailsDomainClass getComponent() { - return null; - } - - public void setOwningSide(boolean b) { - owingSide = b; - } - - public boolean isBasicCollectionType() { - return false; - } - - public boolean isHasOne() { - return false; - } - - public void setColumnName(String columnName) { - this.columnName = columnName; - } - - public String getColumnName() { - return columnName; - } - - public void setDerived(boolean derived) { - // ignored - } - - public boolean isDerived() { - return false; - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateEventListeners.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateEventListeners.java deleted file mode 100644 index f9f093902..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateEventListeners.java +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright 2004-2010 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; - -import java.util.Map; - -public class HibernateEventListeners { - - private Map listenerMap; - - public Map getListenerMap() { - return listenerMap; - } - - public void setListenerMap(Map listenerMap) { - this.listenerMap = listenerMap; - } -} 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 deleted file mode 100644 index 395519f06..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/IHibernateTemplate.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2013 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.codehaus.groovy.grails.orm.hibernate; - -import java.io.Serializable; -import java.util.Collection; - -import org.hibernate.LockMode; -import org.hibernate.SessionFactory; - -/** - * @author Burt Beckwith - */ -public interface IHibernateTemplate { - - Serializable save(Object o); - - void refresh(Object o); - - void lock(Object o, LockMode lockMode); - - void flush(); - - void clear(); - - void evict(Object o); - - boolean contains(Object o); - - void setFlushMode(int mode); - - int getFlushMode(); - - void deleteAll(Collection list); - - T get(Class type, Serializable key); - - T get(Class type, Serializable key, LockMode mode); - - T load(Class type, Serializable key); - - void delete(Object o); - - SessionFactory getSessionFactory(); -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/SessionFactoryHolder.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/SessionFactoryHolder.java deleted file mode 100644 index 2d42a1e4d..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/SessionFactoryHolder.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 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.codehaus.groovy.grails.orm.hibernate; - -import org.hibernate.SessionFactory; - -/** - * Holds a reference to the SessionFactory, used to allow proxying of the - * session factory in development mode. - * - * @since 2.0 - * @author Graeme Rocher - */ -public class SessionFactoryHolder { - - public static final String BEAN_ID = "org.grails.internal.SESSION_FACTORY_HOLDER"; - - private SessionFactory sessionFactory; - - public SessionFactory getSessionFactory() { - return sessionFactory; - } - - public void setSessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } -} 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 deleted file mode 100644 index 6fa220539..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/AbstractGrailsDomainBinder.java +++ /dev/null @@ -1,3218 +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.cfg; - -import grails.util.GrailsNameUtils; -import groovy.lang.Closure; - -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Modifier; -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.sql.Types; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.SortedSet; -import java.util.StringTokenizer; - -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.math.NumberUtils; -import org.codehaus.groovy.grails.commons.DefaultGrailsDomainClassProperty; -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.GrailsDomainException; -import org.codehaus.groovy.grails.plugins.GrailsPlugin; -import org.codehaus.groovy.grails.plugins.GrailsPluginManager; -import org.codehaus.groovy.grails.validation.ConstrainedProperty; -import org.dom4j.Attribute; -import org.dom4j.Element; -import org.hibernate.FetchMode; -import org.hibernate.MappingException; -import org.hibernate.cfg.BinderHelper; -import org.hibernate.cfg.ImprovedNamingStrategy; -import org.hibernate.cfg.Mappings; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.cfg.SecondPass; -import org.hibernate.id.PersistentIdentifierGenerator; -import org.hibernate.mapping.Backref; -import org.hibernate.mapping.Bag; -import org.hibernate.mapping.Collection; -import org.hibernate.mapping.Column; -import org.hibernate.mapping.Component; -import org.hibernate.mapping.DependantValue; -import org.hibernate.mapping.Formula; -import org.hibernate.mapping.IndexBackref; -import org.hibernate.mapping.IndexedCollection; -import org.hibernate.mapping.JoinedSubclass; -import org.hibernate.mapping.KeyValue; -import org.hibernate.mapping.ManyToOne; -import org.hibernate.mapping.OneToMany; -import org.hibernate.mapping.OneToOne; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.mapping.RootClass; -import org.hibernate.mapping.Selectable; -import org.hibernate.mapping.SimpleValue; -import org.hibernate.mapping.SingleTableSubclass; -import org.hibernate.mapping.Subclass; -import org.hibernate.mapping.UnionSubclass; -import org.hibernate.mapping.Table; -import org.hibernate.mapping.UniqueKey; -import org.hibernate.mapping.Value; -import org.hibernate.persister.entity.UnionSubclassEntityPersister; -import org.hibernate.type.ForeignKeyDirection; -import org.hibernate.type.IntegerType; -import org.hibernate.type.LongType; -import org.hibernate.type.StandardBasicTypes; -import org.hibernate.type.TimestampType; -import org.hibernate.type.Type; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; - -/** - * Handles the binding Grails domain classes and properties to the Hibernate runtime meta model. - * Based on the HbmBinder code in Hibernate core and influenced by AnnotationsBinder. - * - * @author Graeme Rocher - * @since 0.1 - */ -public abstract class AbstractGrailsDomainBinder { - - protected static final String CASCADE_ALL_DELETE_ORPHAN = "all-delete-orphan"; - protected static final String FOREIGN_KEY_SUFFIX = "_id"; - protected static final String STRING_TYPE = "string"; - protected static final String EMPTY_PATH = ""; - protected static final char UNDERSCORE = '_'; - protected static final String CASCADE_ALL = "all"; - protected static final String CASCADE_SAVE_UPDATE = "save-update"; - protected static final String CASCADE_NONE = "none"; - protected static final String BACKTICK = "`"; - - protected static final Map, Mapping> MAPPING_CACHE = new HashMap, Mapping>(); - protected static final String ENUM_TYPE_CLASS = "org.hibernate.type.EnumType"; - protected static final String ENUM_CLASS_PROP = "enumClass"; - protected static final String ENUM_TYPE_PROP = "type"; - protected static final String DEFAULT_ENUM_TYPE = "default"; - - protected final Logger LOG = LoggerFactory.getLogger(getClass()); - - protected final CollectionType CT = new CollectionType(null, this) { - public Collection create(GrailsDomainClassProperty property, PersistentClass owner, String path, Mappings mappings, String sessionFactoryBeanName) { - return null; - } - }; - - /** - * Overrideable naming strategy. Defaults to ImprovedNamingStrategy but can - * be configured in DataSource.groovy via hibernate.naming_strategy = .... - */ - public static Map NAMING_STRATEGIES = new HashMap(); - static { - NAMING_STRATEGIES.put(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE, ImprovedNamingStrategy.INSTANCE); - } - - /** - * Second pass class for grails relationships. This is required as all - * persistent classes need to be loaded in the first pass and then relationships - * established in the second pass compile - * - * @author Graeme - */ - class GrailsCollectionSecondPass implements SecondPass { - - private static final long serialVersionUID = -5540526942092611348L; - - protected GrailsDomainClassProperty property; - protected Mappings mappings; - protected Collection collection; - protected String sessionFactoryBeanName; - - public GrailsCollectionSecondPass(GrailsDomainClassProperty property, Mappings mappings, - Collection coll, String sessionFactoryBeanName) { - this.property = property; - this.mappings = mappings; - this.collection = coll; - this.sessionFactoryBeanName = sessionFactoryBeanName; - } - - public void doSecondPass(Map persistentClasses, Map inheritedMetas) throws MappingException { - bindCollectionSecondPass(property, mappings, persistentClasses, collection, sessionFactoryBeanName); - createCollectionKeys(); - } - - protected void createCollectionKeys() { - collection.createAllKeys(); - - if (LOG.isDebugEnabled()) { - String msg = "Mapped collection key: " + columns(collection.getKey()); - if (collection.isIndexed()) - msg += ", index: " + columns(((IndexedCollection) collection).getIndex()); - if (collection.isOneToMany()) { - msg += ", one-to-many: " - + ((OneToMany) collection.getElement()).getReferencedEntityName(); - } else { - msg += ", element: " + columns(collection.getElement()); - } - LOG.debug(msg); - } - } - - protected String columns(Value val) { - StringBuilder columns = new StringBuilder(); - Iterator iter = val.getColumnIterator(); - while (iter.hasNext()) { - columns.append(((Selectable) iter.next()).getText()); - if (iter.hasNext()) columns.append(", "); - } - return columns.toString(); - } - - @SuppressWarnings("rawtypes") - public void doSecondPass(Map persistentClasses) throws MappingException { - bindCollectionSecondPass(property, mappings, persistentClasses, collection, sessionFactoryBeanName); - createCollectionKeys(); - } - } - - class ListSecondPass extends GrailsCollectionSecondPass { - private static final long serialVersionUID = -3024674993774205193L; - - public ListSecondPass(GrailsDomainClassProperty property, Mappings mappings, - Collection coll, String sessionFactoryBeanName) { - super(property, mappings, coll, sessionFactoryBeanName); - } - - @Override - public void doSecondPass(Map persistentClasses, Map inheritedMetas) throws MappingException { - bindListSecondPass(property, mappings, persistentClasses, - (org.hibernate.mapping.List) collection, sessionFactoryBeanName); - } - - @SuppressWarnings("rawtypes") - @Override - public void doSecondPass(Map persistentClasses) throws MappingException { - bindListSecondPass(property, mappings, persistentClasses, - (org.hibernate.mapping.List) collection, sessionFactoryBeanName); - } - } - - class MapSecondPass extends GrailsCollectionSecondPass { - private static final long serialVersionUID = -3244991685626409031L; - - public MapSecondPass(GrailsDomainClassProperty property, Mappings mappings, - Collection coll, String sessionFactoryBeanName) { - super(property, mappings, coll, sessionFactoryBeanName); - } - - @Override - public void doSecondPass(Map persistentClasses, Map inheritedMetas) throws MappingException { - bindMapSecondPass(property, mappings, persistentClasses, - (org.hibernate.mapping.Map)collection, sessionFactoryBeanName); - } - - @SuppressWarnings("rawtypes") - @Override - public void doSecondPass(Map persistentClasses) throws MappingException { - bindMapSecondPass(property, mappings, persistentClasses, - (org.hibernate.mapping.Map) collection, sessionFactoryBeanName); - } - } - - /** - * Override the default naming strategy for the default datasource given a Class or a full class name. - * @param strategy the class or name - * @throws ClassNotFoundException - * @throws InstantiationException - * @throws IllegalAccessException - */ - public void configureNamingStrategy(final Object strategy) throws ClassNotFoundException, InstantiationException, IllegalAccessException { - configureNamingStrategy(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE, strategy); - } - - /** - * Override the default naming strategy given a Class or a full class name, - * or an instance of a NamingStrategy. - * - * @param datasourceName the datasource name - * @param strategy the class, name, or instance - * @throws ClassNotFoundException - * @throws InstantiationException - * @throws IllegalAccessException - */ - public void configureNamingStrategy(final String datasourceName, final Object strategy) throws ClassNotFoundException, InstantiationException, IllegalAccessException { - Class namingStrategyClass = null; - NamingStrategy namingStrategy; - if (strategy instanceof Class) { - namingStrategyClass = (Class)strategy; - } - else if (strategy instanceof CharSequence) { - namingStrategyClass = Thread.currentThread().getContextClassLoader().loadClass(strategy.toString()); - } - - if (namingStrategyClass == null) { - namingStrategy = (NamingStrategy)strategy; - } - else { - namingStrategy = (NamingStrategy)namingStrategyClass.newInstance(); - } - - NAMING_STRATEGIES.put(datasourceName, namingStrategy); - } - - protected void bindMapSecondPass(GrailsDomainClassProperty property, Mappings mappings, - Map persistentClasses, org.hibernate.mapping.Map map, String sessionFactoryBeanName) { - bindCollectionSecondPass(property, mappings, persistentClasses, map, sessionFactoryBeanName); - - SimpleValue value = new SimpleValue(mappings, map.getCollectionTable()); - - bindSimpleValue(getIndexColumnType(property, STRING_TYPE), value, true, - getIndexColumnName(property, sessionFactoryBeanName), mappings); - PropertyConfig pc = getPropertyConfig(property); - if (pc != null && pc.getIndexColumn() != null) { - bindColumnConfigToColumn(getColumnForSimpleValue(value), getSingleColumnConfig(pc.getIndexColumn())); - } - - if (!value.isTypeSpecified()) { - throw new MappingException("map index element must specify a type: " + map.getRole()); - } - map.setIndex(value); - - if (!property.isOneToMany() && !property.isManyToMany()) { - SimpleValue elt = new SimpleValue(mappings, map.getCollectionTable()); - map.setElement(elt); - - String typeName = getTypeName(property,getPropertyConfig(property), getMapping(property.getDomainClass())); - if (typeName == null) { - if (property.isBasicCollectionType()) { - typeName = property.getReferencedPropertyType().getName(); - } - else { - typeName = StandardBasicTypes.STRING.getName(); - } - } - bindSimpleValue(typeName, elt, false, getMapElementName(property, sessionFactoryBeanName), mappings); - - elt.setTypeName(typeName); - - map.setInverse(false); - } - else { - map.setInverse(false); - } - } - - protected ColumnConfig getSingleColumnConfig(PropertyConfig propertyConfig) { - if (propertyConfig != null) { - List columns = propertyConfig.getColumns(); - if (columns != null && !columns.isEmpty()) { - return columns.get(0); - } - } - return null; - } - - protected void bindListSecondPass(GrailsDomainClassProperty property, Mappings mappings, - Map persistentClasses, org.hibernate.mapping.List list, String sessionFactoryBeanName) { - - bindCollectionSecondPass(property, mappings, persistentClasses, list, sessionFactoryBeanName); - - String columnName = getIndexColumnName(property, sessionFactoryBeanName); - final boolean isManyToMany = property.isManyToMany(); - - if (isManyToMany && !property.isOwningSide()) { - throw new MappingException("Invalid association [" + property.getDomainClass().getName() + "->" + property.getName() + - "]. List collection types only supported on the owning side of a many-to-many relationship."); - } - - Table collectionTable = list.getCollectionTable(); - SimpleValue iv = new SimpleValue(mappings, collectionTable); - bindSimpleValue("integer", iv, true, columnName, mappings); - iv.setTypeName("integer"); - list.setIndex(iv); - list.setBaseIndex(0); - list.setInverse(false); - - Value v = list.getElement(); - v.createForeignKey(); - - if (property.isBidirectional()) { - - String entityName; - Value element = list.getElement(); - if (element instanceof ManyToOne) { - ManyToOne manyToOne = (ManyToOne) element; - entityName = manyToOne.getReferencedEntityName(); - } else { - entityName = ((OneToMany) element).getReferencedEntityName(); - } - - PersistentClass referenced = mappings.getClass(entityName); - - Class mappedClass = referenced.getMappedClass(); - Mapping m = getMapping(mappedClass); - - boolean compositeIdProperty = isCompositeIdProperty(m, property.getOtherSide()); - if (!compositeIdProperty) { - Backref prop = new Backref(); - prop.setEntityName(property.getDomainClass().getFullName()); - prop.setName(UNDERSCORE + addUnderscore(property.getDomainClass().getShortName(), property.getName()) + "Backref"); - prop.setSelectable(false); - prop.setUpdateable(false); - if (isManyToMany) { - prop.setInsertable(false); - } - prop.setCollectionRole(list.getRole()); - prop.setValue(list.getKey()); - - DependantValue value = (DependantValue) prop.getValue(); - if (!property.isCircular()) { - value.setNullable(false); - } - value.setUpdateable(true); - prop.setOptional(false); - - referenced.addProperty(prop); - } - - if ((!list.getKey().isNullable() && !list.isInverse()) || compositeIdProperty) { - IndexBackref ib = new IndexBackref(); - ib.setName(UNDERSCORE + property.getName() + "IndexBackref"); - ib.setUpdateable(false); - ib.setSelectable(false); - if (isManyToMany) { - ib.setInsertable(false); - } - ib.setCollectionRole(list.getRole()); - ib.setEntityName(list.getOwner().getEntityName()); - ib.setValue(list.getIndex()); - referenced.addProperty(ib); - } - } - } - - protected void bindCollectionSecondPass(GrailsDomainClassProperty property, Mappings mappings, - Map persistentClasses, Collection collection, String sessionFactoryBeanName) { - - PersistentClass associatedClass = null; - - if (LOG.isDebugEnabled()) - LOG.debug("Mapping collection: " - + collection.getRole() - + " -> " - + collection.getCollectionTable().getName()); - - PropertyConfig propConfig = getPropertyConfig(property); - - if (propConfig != null && !StringUtils.isBlank(propConfig.getSort())) { - if (!property.isBidirectional() && property.isOneToMany()) { - throw new GrailsDomainException("Default sort for associations ["+property.getDomainClass().getName()+"->" + property.getName() + - "] are not supported with unidirectional one to many relationships."); - } - GrailsDomainClass referenced = property.getReferencedDomainClass(); - if (referenced != null) { - GrailsDomainClassProperty propertyToSortBy = referenced.getPropertyByName(propConfig.getSort()); - - String associatedClassName = property.getReferencedDomainClass().getFullName(); - - associatedClass = (PersistentClass) persistentClasses.get(associatedClassName); - if (associatedClass != null) { - collection.setOrderBy(buildOrderByClause(propertyToSortBy.getName(), associatedClass, collection.getRole(), - propConfig.getOrder() != null ? propConfig.getOrder() : "asc")); - } - } - } - - // Configure one-to-many - if (collection.isOneToMany()) { - - GrailsDomainClass referenced = property.getReferencedDomainClass(); - Mapping m = getRootMapping(referenced); - boolean tablePerSubclass = m != null && !m.getTablePerHierarchy(); - - if (referenced != null && !referenced.isRoot() && !tablePerSubclass) { - Mapping rootMapping = getRootMapping(referenced); - String discriminatorColumnName = RootClass.DEFAULT_DISCRIMINATOR_COLUMN_NAME; - - if (rootMapping != null) { - final ColumnConfig discriminatorColumn = rootMapping.getDiscriminatorColumn(); - if (discriminatorColumn != null) { - discriminatorColumnName = discriminatorColumn.getName(); - } - if (rootMapping.getDiscriminatorMap().get("formula") != null) { - discriminatorColumnName = (String)m.getDiscriminatorMap().get("formula"); - } - } - //NOTE: this will build the set for the in clause if it has sublcasses - Set discSet = buildDiscriminatorSet(referenced); - String inclause = StringUtils.join(discSet, ','); - - collection.setWhere(discriminatorColumnName + " in (" + inclause + ")"); - } - - OneToMany oneToMany = (OneToMany) collection.getElement(); - String associatedClassName = oneToMany.getReferencedEntityName(); - - associatedClass = (PersistentClass) persistentClasses.get(associatedClassName); - // if there is no persistent class for the association throw exception - if (associatedClass == null) { - throw new MappingException("Association references unmapped class: " + oneToMany.getReferencedEntityName()); - } - - oneToMany.setAssociatedClass(associatedClass); - if (shouldBindCollectionWithForeignKey(property)) { - collection.setCollectionTable(associatedClass.getTable()); - } - - bindCollectionForPropertyConfig(collection, propConfig); - } - - if (isSorted(property)) { - collection.setSorted(true); - } - - // setup the primary key references - DependantValue key = createPrimaryKeyValue(mappings, property, collection, persistentClasses); - - // link a bidirectional relationship - if (property.isBidirectional()) { - GrailsDomainClassProperty otherSide = property.getOtherSide(); - if (otherSide.isManyToOne() && shouldBindCollectionWithForeignKey(property)) { - linkBidirectionalOneToMany(collection, associatedClass, key, otherSide); - } else if (property.isManyToMany() || Map.class.isAssignableFrom(property.getType())) { - bindDependentKeyValue(property, key, mappings, sessionFactoryBeanName); - } - } else { - if (hasJoinKeyMapping(propConfig)) { - bindSimpleValue("long", key,false, propConfig.getJoinTable().getKey().getName(), mappings); - } else { - bindDependentKeyValue(property, key, mappings, sessionFactoryBeanName); - } - } - collection.setKey(key); - - // get cache config - if (propConfig != null) { - CacheConfig cacheConfig = propConfig.getCache(); - if (cacheConfig != null) { - collection.setCacheConcurrencyStrategy(cacheConfig.getUsage()); - } - } - - // if we have a many-to-many - if (property.isManyToMany() || isBidirectionalOneToManyMap(property)) { - GrailsDomainClassProperty otherSide = property.getOtherSide(); - - if (property.isBidirectional()) { - if (LOG.isDebugEnabled()) - LOG.debug("[GrailsDomainBinder] Mapping other side " + otherSide.getDomainClass().getName() + "." + otherSide.getName() + " -> " + collection.getCollectionTable().getName() + " as ManyToOne"); - ManyToOne element = new ManyToOne(mappings, collection.getCollectionTable()); - bindManyToMany(otherSide, element, mappings, sessionFactoryBeanName); - collection.setElement(element); - bindCollectionForPropertyConfig(collection, propConfig); - if (property.isCircular()) { - collection.setInverse(false); - } - } else { - // TODO support unidirectional many-to-many - } - } else if (shouldCollectionBindWithJoinColumn(property)) { - bindCollectionWithJoinTable(property, mappings, collection, propConfig, sessionFactoryBeanName); - - } else if (isUnidirectionalOneToMany(property)) { - // for non-inverse one-to-many, with a not-null fk, add a backref! - // there are problems with list and map mappings and join columns relating to duplicate key constraints - // TODO change this when HHH-1268 is resolved - bindUnidirectionalOneToMany(property, mappings, collection); - } - } - - @SuppressWarnings("unchecked") - protected String buildOrderByClause(String hqlOrderBy, PersistentClass associatedClass, String role, String defaultOrder) { - String orderByString = null; - if (hqlOrderBy != null) { - List properties = new ArrayList(); - List ordering = new ArrayList(); - StringBuilder orderByBuffer = new StringBuilder(); - if (hqlOrderBy.length() == 0) { - //order by id - Iterator it = associatedClass.getIdentifier().getColumnIterator(); - while (it.hasNext()) { - Selectable col = (Selectable) it.next(); - orderByBuffer.append(col.getText()).append(" asc").append(", "); - } - } - else { - StringTokenizer st = new StringTokenizer(hqlOrderBy, " ,", false); - String currentOrdering = defaultOrder; - //FIXME make this code decent - while (st.hasMoreTokens()) { - String token = st.nextToken(); - if (isNonPropertyToken(token)) { - if (currentOrdering != null) { - throw new GrailsDomainException( - "Error while parsing sort clause: " + hqlOrderBy - + " (" + role + ")" - ); - } - currentOrdering = token; - } - else { - //Add ordering of the previous - if (currentOrdering == null) { - //default ordering - ordering.add("asc"); - } - else { - ordering.add(currentOrdering); - currentOrdering = null; - } - properties.add(token); - } - } - ordering.remove(0); //first one is the algorithm starter - // add last one ordering - if (currentOrdering == null) { - //default ordering - ordering.add(defaultOrder); - } - else { - ordering.add(currentOrdering); - currentOrdering = null; - } - int index = 0; - - for (String property : properties) { - Property p = BinderHelper.findPropertyByName(associatedClass, property); - if (p == null) { - throw new GrailsDomainException( - "property from sort clause not found: " - + associatedClass.getEntityName() + "." + property - ); - } - PersistentClass pc = p.getPersistentClass(); - String table; - if (pc == null) { - table = ""; - } - - else if (pc == associatedClass - || (associatedClass instanceof SingleTableSubclass && - pc.getMappedClass().isAssignableFrom(associatedClass.getMappedClass()))) { - table = ""; - } else { - table = pc.getTable().getQuotedName() + "."; - } - - Iterator propertyColumns = p.getColumnIterator(); - while (propertyColumns.hasNext()) { - Selectable column = (Selectable) propertyColumns.next(); - orderByBuffer.append(table) - .append(column.getText()) - .append(" ") - .append(ordering.get(index)) - .append(", "); - } - index++; - } - } - orderByString = orderByBuffer.substring(0, orderByBuffer.length() - 2); - } - return orderByString; - } - - protected boolean isNonPropertyToken(String token) { - if (" ".equals(token)) return true; - if (",".equals(token)) return true; - if (token.equalsIgnoreCase("desc")) return true; - if (token.equalsIgnoreCase("asc")) return true; - return false; - } - - protected Set buildDiscriminatorSet(GrailsDomainClass domainClass) { - Set theSet = new HashSet(); - - Mapping mapping = getMapping(domainClass); - String discriminator = domainClass.getFullName(); - if (mapping != null && mapping.getDiscriminator() != null) { - discriminator = mapping.getDiscriminator(); - } - Mapping rootMapping = getRootMapping(domainClass); - String quote = "'"; - if (rootMapping != null && rootMapping.getDiscriminatorMap() != null && - rootMapping.getDiscriminatorMap().get("type") != null && rootMapping.getDiscriminatorMap().get("type") != "string") { - quote = ""; - } - theSet.add(quote + discriminator + quote); - - for (GrailsDomainClass subClass : domainClass.getSubClasses()) { - theSet.addAll(buildDiscriminatorSet(subClass)); - } - return theSet; - } - - protected Mapping getRootMapping(GrailsDomainClass referenced) { - if (referenced == null) return null; - Class current = referenced.getClazz(); - while (true) { - Class superClass = current.getSuperclass(); - if (Object.class.equals(superClass)) break; - current = superClass; - } - - return getMapping(current); - } - - protected boolean isBidirectionalOneToManyMap(GrailsDomainClassProperty property) { - return Map.class.isAssignableFrom(property.getType()) && property.isBidirectional(); - } - - protected void bindCollectionWithJoinTable(GrailsDomainClassProperty property, - Mappings mappings, Collection collection, PropertyConfig config, String sessionFactoryBeanName) { - - NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); - - SimpleValue element; - if (property.isBasicCollectionType()) { - element = new SimpleValue(mappings, collection.getCollectionTable()); - } - else { - // for a normal unidirectional one-to-many we use a join column - element = new ManyToOne(mappings, collection.getCollectionTable()); - bindUnidirectionalOneToManyInverseValues(property, (ManyToOne) element); - } - collection.setInverse(false); - - String columnName; - - final boolean hasJoinColumnMapping = hasJoinColumnMapping(config); - if (property.isBasicCollectionType()) { - final Class referencedType = property.getReferencedPropertyType(); - String className = referencedType.getName(); - final boolean isEnum = referencedType.isEnum(); - if (hasJoinColumnMapping) { - columnName = config.getJoinTable().getColumn().getName(); - } - else { - columnName = isEnum ? namingStrategy.propertyToColumnName(className) : - addUnderscore(namingStrategy.propertyToColumnName(property.getName()), - namingStrategy.propertyToColumnName(className)); - } - - if (isEnum) { - bindEnumType(property, referencedType,element,columnName); - } - else { - - String typeName = getTypeName(property, config, getMapping(property.getDomainClass())); - if (typeName == null) { - Type type = mappings.getTypeResolver().basic(className); - if (type != null) { - typeName = type.getName(); - } - } - if (typeName == null) { - String domainName = property.getDomainClass().getName(); - throw new MappingException("Missing type or column for column["+columnName+"] on domain["+domainName+"] referencing["+className+"]"); - } - - bindSimpleValue(typeName, element,true, columnName, mappings); - if (hasJoinColumnMapping) { - bindColumnConfigToColumn(getColumnForSimpleValue(element), config.getJoinTable().getColumn()); - } - } - } else { - final GrailsDomainClass domainClass = property.getReferencedDomainClass(); - - Mapping m = getMapping(domainClass.getClazz()); - if (hasCompositeIdentifier(m)) { - CompositeIdentity ci = (CompositeIdentity) m.getIdentity(); - bindCompositeIdentifierToManyToOne(property, element, ci, domainClass, - EMPTY_PATH, sessionFactoryBeanName); - } - else { - if (hasJoinColumnMapping) { - columnName = config.getJoinTable().getColumn().getName(); - } - else { - columnName = namingStrategy.propertyToColumnName(domainClass.getPropertyName()) + FOREIGN_KEY_SUFFIX; - } - - bindSimpleValue("long", element,true, columnName, mappings); - } - } - - collection.setElement(element); - - bindCollectionForPropertyConfig(collection, config); - } - - protected String addUnderscore(String s1, String s2) { - return removeBackticks(s1) + UNDERSCORE + removeBackticks(s2); - } - - protected String removeBackticks(String s) { - return s.startsWith("`") && s.endsWith("`") ? s.substring(1, s.length() - 1) : s; - } - - protected Column getColumnForSimpleValue(SimpleValue element) { - return (Column)element.getColumnIterator().next(); - } - - protected String getTypeName(GrailsDomainClassProperty property, PropertyConfig config, Mapping mapping) { - if (config != null && config.getType() != null) { - final Object typeObj = config.getType(); - if (typeObj instanceof Class) { - return ((Class)typeObj).getName(); - } - return typeObj.toString(); - } - - if (mapping != null) { - return mapping.getTypeName(property.getType()); - } - - return null; - } - - protected void bindColumnConfigToColumn(Column column, ColumnConfig columnConfig) { - if (columnConfig == null) { - return; - } - - if (columnConfig.getLength() != -1) { - column.setLength(columnConfig.getLength()); - } - if (columnConfig.getPrecision() != -1) { - column.setPrecision(columnConfig.getPrecision()); - } - if (columnConfig.getScale() != -1) { - column.setScale(columnConfig.getScale()); - } - if (columnConfig.getSqlType() != null && !columnConfig.getSqlType().isEmpty()) { - column.setSqlType(columnConfig.getSqlType()); - } - column.setUnique(columnConfig.getUnique()); - } - - protected boolean hasJoinColumnMapping(PropertyConfig config) { - return config != null && config.getJoinTable() != null && config.getJoinTable().getColumn() != null; - } - - protected boolean shouldCollectionBindWithJoinColumn(GrailsDomainClassProperty property) { - PropertyConfig config = getPropertyConfig(property); - JoinTable jt = config != null ? config.getJoinTable() : new JoinTable(); - - return (isUnidirectionalOneToMany(property) || property.isBasicCollectionType()) && jt != null; - } - - /** - * @param property - * @param manyToOne - */ - protected void bindUnidirectionalOneToManyInverseValues(GrailsDomainClassProperty property, ManyToOne manyToOne) { - PropertyConfig config = getPropertyConfig(property); - if (config != null) { - manyToOne.setLazy(config.getLazy()); - manyToOne.setIgnoreNotFound(config.getIgnoreNotFound()); - } else { - manyToOne.setLazy(true); - } - - // set referenced entity - manyToOne.setReferencedEntityName(property.getReferencedPropertyType().getName()); - } - - protected void bindCollectionForPropertyConfig(Collection collection, PropertyConfig config) { - if (config == null) { - collection.setLazy(true); - collection.setExtraLazy(false); - } else { - collection.setLazy(config.getLazy()); - } - } - - public PropertyConfig getPropertyConfig(GrailsDomainClassProperty property) { - Mapping m = getMapping(property.getDomainClass().getClazz()); - PropertyConfig config = m != null ? m.getPropertyConfig(property.getName()) : null; - return config; - } - - /** - * Checks whether a property is a unidirectional non-circular one-to-many - * - * @param property The property to check - * @return true if it is unidirectional and a one-to-many - */ - protected boolean isUnidirectionalOneToMany(GrailsDomainClassProperty property) { - return property.isOneToMany() && !property.isBidirectional(); - } - - /** - * Binds the primary key value column - * - * @param property The property - * @param key The key - * @param mappings The mappings - */ - protected void bindDependentKeyValue(GrailsDomainClassProperty property, DependantValue key, - Mappings mappings, String sessionFactoryBeanName) { - - if (LOG.isDebugEnabled()) { - LOG.debug("[GrailsDomainBinder] binding [" + property.getName() + "] with dependant key"); - } - - GrailsDomainClass refDomainClass = property.getDomainClass(); - final Mapping mapping = getMapping(refDomainClass.getClazz()); - if ((shouldCollectionBindWithJoinColumn(property) && hasCompositeIdentifier(mapping)) || - (hasCompositeIdentifier(mapping) && property.isManyToMany())) { - CompositeIdentity ci = (CompositeIdentity) mapping.getIdentity(); - bindCompositeIdentifierToManyToOne(property, key, ci, refDomainClass, EMPTY_PATH, sessionFactoryBeanName); - } - else { - bindSimpleValue(property, null, key, EMPTY_PATH, mappings, sessionFactoryBeanName); - } - } - - /** - * Creates the DependentValue object that forms a primary key reference for the collection. - * - * @param mappings - * @param property The grails property - * @param collection The collection object - * @param persistentClasses - * @return The DependantValue (key) - */ - protected DependantValue createPrimaryKeyValue(Mappings mappings, GrailsDomainClassProperty property, - Collection collection, Map persistentClasses) { - KeyValue keyValue; - DependantValue key; - String propertyRef = collection.getReferencedPropertyName(); - // this is to support mapping by a property - if (propertyRef == null) { - keyValue = collection.getOwner().getIdentifier(); - } else { - keyValue = (KeyValue) collection.getOwner().getProperty(propertyRef).getValue(); - } - - if (LOG.isDebugEnabled()) - LOG.debug("[GrailsDomainBinder] creating dependant key value to table [" + keyValue.getTable().getName() + "]"); - - key = new DependantValue(mappings, collection.getCollectionTable(), keyValue); - - key.setTypeName(null); - // make nullable and non-updateable - key.setNullable(true); - key.setUpdateable(false); - return key; - } - - /** - * Binds a unidirectional one-to-many creating a psuedo back reference property in the process. - * - * @param property - * @param mappings - * @param collection - */ - protected void bindUnidirectionalOneToMany(GrailsDomainClassProperty property, Mappings mappings, Collection collection) { - Value v = collection.getElement(); - v.createForeignKey(); - String entityName; - if (v instanceof ManyToOne) { - ManyToOne manyToOne = (ManyToOne) v; - - entityName = manyToOne.getReferencedEntityName(); - } else { - entityName = ((OneToMany) v).getReferencedEntityName(); - } - collection.setInverse(false); - PersistentClass referenced = mappings.getClass(entityName); - Backref prop = new Backref(); - prop.setEntityName(property.getDomainClass().getFullName()); - prop.setName(UNDERSCORE + addUnderscore(property.getDomainClass().getShortName(), property.getName()) + "Backref"); - prop.setUpdateable(false); - prop.setInsertable(true); - prop.setCollectionRole(collection.getRole()); - prop.setValue(collection.getKey()); - prop.setOptional(true); - - referenced.addProperty(prop); - } - - protected Property getProperty(PersistentClass associatedClass, String propertyName) throws MappingException { - try { - return associatedClass.getProperty(propertyName); - } - catch (MappingException e) { - //maybe it's squirreled away in a composite primary key - if (associatedClass.getKey() instanceof Component) { - return ((Component) associatedClass.getKey()).getProperty(propertyName); - } - throw e; - } - } - - /** - * Links a bidirectional one-to-many, configuring the inverse side and using a column copy to perform the link - * - * @param collection The collection one-to-many - * @param associatedClass The associated class - * @param key The key - * @param otherSide The other side of the relationship - */ - protected void linkBidirectionalOneToMany(Collection collection, PersistentClass associatedClass, DependantValue key, GrailsDomainClassProperty otherSide) { - collection.setInverse(true); - - // Iterator mappedByColumns = associatedClass.getProperty(otherSide.getName()).getValue().getColumnIterator(); - Iterator mappedByColumns = getProperty(associatedClass, otherSide.getName()).getValue().getColumnIterator(); - while (mappedByColumns.hasNext()) { - Column column = (Column) mappedByColumns.next(); - linkValueUsingAColumnCopy(otherSide, column, key); - } - } - - /** - * Establish whether a collection property is sorted - * - * @param property The property - * @return true if sorted - */ - protected boolean isSorted(GrailsDomainClassProperty property) { - return SortedSet.class.isAssignableFrom(property.getType()); - } - - /** - * Binds a many-to-many relationship. A many-to-many consists of - * - a key (a DependentValue) - * - an element - *

    - * The element is a ManyToOne from the association table to the target entity - * - * @param property The grails property - * @param element The ManyToOne element - * @param mappings The mappings - */ - protected void bindManyToMany(GrailsDomainClassProperty property, ManyToOne element, - Mappings mappings, String sessionFactoryBeanName) { - bindManyToOne(property, element, EMPTY_PATH, mappings, sessionFactoryBeanName); - element.setReferencedEntityName(property.getDomainClass().getFullName()); - } - - protected void linkValueUsingAColumnCopy(GrailsDomainClassProperty prop, Column column, DependantValue key) { - Column mappingColumn = new Column(); - mappingColumn.setName(column.getName()); - mappingColumn.setLength(column.getLength()); - mappingColumn.setNullable(prop.isOptional()); - mappingColumn.setSqlType(column.getSqlType()); - - mappingColumn.setValue(key); - key.addColumn(mappingColumn); - key.getTable().addColumn(mappingColumn); - } - - /** - * First pass to bind collection to Hibernate metamodel, sets up second pass - * - * @param property The GrailsDomainClassProperty instance - * @param collection The collection - * @param owner The owning persistent class - * @param mappings The Hibernate mappings instance - * @param path - */ - protected void bindCollection(GrailsDomainClassProperty property, Collection collection, - PersistentClass owner, Mappings mappings, String path, String sessionFactoryBeanName) { - - // set role - String propertyName = getNameForPropertyAndPath(property, path); - collection.setRole(qualify(property.getDomainClass().getFullName(), propertyName)); - - PropertyConfig pc = getPropertyConfig(property); - // configure eager fetching - if (property.getFetchMode() == GrailsDomainClassProperty.FETCH_EAGER) { - collection.setFetchMode(FetchMode.JOIN); - } - else if (pc != null && pc.getFetch() != null) { - collection.setFetchMode(pc.getFetch()); - } - else { - collection.setFetchMode(FetchMode.DEFAULT); - } - - if (pc != null && pc.getCascade() != null) { - collection.setOrphanDelete(pc.getCascade().equals(CASCADE_ALL_DELETE_ORPHAN)); - } - // if it's a one-to-many mapping - if (shouldBindCollectionWithForeignKey(property)) { - OneToMany oneToMany = new OneToMany(mappings, collection.getOwner()); - collection.setElement(oneToMany); - bindOneToMany(property, oneToMany, mappings); - } else { - bindCollectionTable(property, mappings, collection, owner.getTable(), sessionFactoryBeanName); - - if (!property.isOwningSide()) { - collection.setInverse(true); - } - } - - if (pc != null && pc.getBatchSize() != null) { - collection.setBatchSize(pc.getBatchSize().intValue()); - } - - // set up second pass - if (collection instanceof org.hibernate.mapping.Set) { - mappings.addSecondPass(new GrailsCollectionSecondPass(property, mappings, collection, sessionFactoryBeanName)); - } - else if (collection instanceof org.hibernate.mapping.List) { - mappings.addSecondPass(new ListSecondPass(property, mappings, collection, sessionFactoryBeanName)); - } - else if (collection instanceof org.hibernate.mapping.Map) { - mappings.addSecondPass(new MapSecondPass(property, mappings, collection, sessionFactoryBeanName)); - } - else { // Collection -> Bag - mappings.addSecondPass(new GrailsCollectionSecondPass(property, mappings, collection, sessionFactoryBeanName)); - } - } - - /* - * We bind collections with foreign keys if specified in the mapping and only if - * it is a unidirectional one-to-many that is. - */ - protected boolean shouldBindCollectionWithForeignKey(GrailsDomainClassProperty property) { - return (property.isOneToMany() && property.isBidirectional() || - !shouldCollectionBindWithJoinColumn(property)) && !Map.class.isAssignableFrom(property.getType()) && !property.isManyToMany() && !property.isBasicCollectionType(); - } - - protected String getNameForPropertyAndPath(GrailsDomainClassProperty property, String path) { - if (isNotEmpty(path)) { - return qualify(path, property.getName()); - } - return property.getName(); - } - - protected void bindCollectionTable(GrailsDomainClassProperty property, Mappings mappings, - Collection collection, Table ownerTable, String sessionFactoryBeanName) { - - String prefix = ownerTable.getSchema(); - PropertyConfig config = getPropertyConfig(property); - JoinTable jt = config != null ? config.getJoinTable() : null; - - NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); - String tableName = (prefix == null ? "" : prefix + '.') + (jt != null && jt.getName() != null ? jt.getName() : namingStrategy.tableName(calculateTableForMany(property, sessionFactoryBeanName))); - String schemaName = mappings.getSchemaName(); - String catalogName = mappings.getCatalogName(); - if(jt != null) { - if(jt.getSchema() != null) { - schemaName = jt.getSchema(); - } - if(jt.getCatalog() != null) { - catalogName = jt.getCatalog(); - } - } - - collection.setCollectionTable(mappings.addTable( - schemaName, catalogName, - tableName, null, false)); - } - - /** - * Calculates the mapping table for a many-to-many. One side of - * the relationship has to "own" the relationship so that there is not a situation - * where you have two mapping tables for left_right and right_left - */ - protected String calculateTableForMany(GrailsDomainClassProperty property, String sessionFactoryBeanName) { - NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); - - String propertyColumnName = namingStrategy.propertyToColumnName(property.getName()); - //fix for GRAILS-5895 - PropertyConfig config = getPropertyConfig(property); - JoinTable jt = config != null ? config.getJoinTable() : null; - boolean hasJoinTableMapping = jt != null && jt.getName() != null; - String left = getTableName(property.getDomainClass(), sessionFactoryBeanName); - - if (Map.class.isAssignableFrom(property.getType())) { - if (hasJoinTableMapping) { - return jt.getName(); - } - return addUnderscore(left, propertyColumnName); - } - - if (property.isBasicCollectionType()) { - if (hasJoinTableMapping) { - return jt.getName(); - } - return addUnderscore(left, propertyColumnName); - } - - String right = getTableName(property.getReferencedDomainClass(), sessionFactoryBeanName); - - if (property.isManyToMany()) { - if (hasJoinTableMapping) { - return jt.getName(); - } - if (property.isOwningSide()) { - return addUnderscore(left, propertyColumnName); - } - return addUnderscore(right, namingStrategy.propertyToColumnName(property.getOtherSide().getName())); - } - - if (shouldCollectionBindWithJoinColumn(property)) { - if (hasJoinTableMapping) { - return jt.getName(); - } - left = trimBackTigs(left); - right = trimBackTigs(right); - return addUnderscore(left, right); - } - - if (property.isOwningSide()) { - return addUnderscore(left, right); - } - return addUnderscore(right, left); - } - - protected String trimBackTigs(String tableName) { - if (tableName.startsWith(BACKTICK)) { - return tableName.substring(1, tableName.length() - 1); - } - return tableName; - } - - /** - * Evaluates the table name for the given property - * - * @param domainClass The domain class to evaluate - * @return The table name - */ - protected String getTableName(GrailsDomainClass domainClass, String sessionFactoryBeanName) { - Mapping m = getMapping(domainClass.getClazz()); - String tableName = null; - if (m != null && m.getTableName() != null) { - tableName = m.getTableName(); - } - if (tableName == null) { - String shortName = domainClass.getShortName(); - final GrailsApplication grailsApplication = domainClass.getGrailsApplication(); - if (grailsApplication != null) { - final ApplicationContext mainContext = grailsApplication.getMainContext(); - if (mainContext != null && mainContext.containsBean("pluginManager")) { - final GrailsPluginManager pluginManager = (GrailsPluginManager) mainContext.getBean("pluginManager"); - final GrailsPlugin pluginForClass = pluginManager.getPluginForClass(domainClass.getClazz()); - if (pluginForClass != null) { - final String pluginName = pluginForClass.getName(); - boolean shouldApplyPluginPrefix = false; - if (!shortName.toLowerCase().startsWith(pluginName.toLowerCase())) { - final String pluginSpecificConfigProperty = "grails.gorm." + GrailsNameUtils.getPropertyName(pluginName) + ".table.prefix.enabled"; - final Map flatConfig = grailsApplication.getFlatConfig(); - if (flatConfig.containsKey(pluginSpecificConfigProperty)) { - shouldApplyPluginPrefix = Boolean.TRUE.equals(flatConfig.get(pluginSpecificConfigProperty)); - } else { - shouldApplyPluginPrefix = Boolean.TRUE.equals(flatConfig.get("grails.gorm.table.prefix.enabled")); - } - } - if (shouldApplyPluginPrefix) { - shortName = pluginName + shortName; - } - } - } - } - tableName = getNamingStrategy(sessionFactoryBeanName).classToTableName(shortName); - } - return tableName; - } - - protected NamingStrategy getNamingStrategy(String sessionFactoryBeanName) { - String key = "sessionFactory".equals(sessionFactoryBeanName) ? - GrailsDomainClassProperty.DEFAULT_DATA_SOURCE : - sessionFactoryBeanName.substring("sessionFactory_".length()); - return NAMING_STRATEGIES.get(key); - } - - /** - * Binds a Grails domain class to the Hibernate runtime meta model - * - * @param domainClass The domain class to bind - * @param mappings The existing mappings - * @param sessionFactoryBeanName the session factory bean name - * @throws MappingException Thrown if the domain class uses inheritance which is not supported - */ - public void bindClass(GrailsDomainClass domainClass, Mappings mappings, String sessionFactoryBeanName) - throws MappingException { - //if (domainClass.getClazz().getSuperclass() == Object.class) { - if (domainClass.isRoot()) { - bindRoot(domainClass, mappings, sessionFactoryBeanName); - } - } - - /** - * Evaluates a Mapping object from the domain class if it has a mapping closure - * - * @param domainClass The domain class - * @return the mapping - */ - public Mapping evaluateMapping(GrailsDomainClass domainClass) { - return evaluateMapping(domainClass, null); - } - - public Mapping evaluateMapping(GrailsDomainClass domainClass, Closure defaultMapping) { - return evaluateMapping(domainClass, defaultMapping, true); - } - - public Mapping evaluateMapping(GrailsDomainClass domainClass, Closure defaultMapping, boolean cache) { - try { - Object o = GrailsClassUtils.getStaticPropertyValue(domainClass.getClazz(), GrailsDomainClassProperty.MAPPING); - if (o != null || defaultMapping != null) { - HibernateMappingBuilder builder = new HibernateMappingBuilder(domainClass.getFullName()); - GrailsApplication application = domainClass.getGrailsApplication(); - ApplicationContext ctx = null; - if (application != null) { - ctx = application.getMainContext(); - if (ctx == null) ctx = application.getParentContext(); - } - - Mapping m = null; - if (defaultMapping != null) { - m = builder.evaluate(defaultMapping,ctx); - } - - if (o instanceof Closure) { - m = builder.evaluate((Closure) o,ctx); - } - - final Object identity = m.getIdentity(); - if (identity instanceof Identity) { - final Identity identityObject = (Identity) identity; - final String idName = identityObject.getName(); - if (idName != null && !GrailsDomainClassProperty.IDENTITY.equals(idName)) { - GrailsDomainClassProperty persistentProperty = domainClass.getPersistentProperty(idName); - if (!persistentProperty.isIdentity()) { - if (persistentProperty instanceof DefaultGrailsDomainClassProperty) { - ((DefaultGrailsDomainClassProperty)persistentProperty).setIdentity(true); // fixed for 2.2 - } - } - } - } - - trackCustomCascadingSaves(m, domainClass.getPersistentProperties()); - - if (cache) { - MAPPING_CACHE.put(domainClass.getClazz(), m); - } - return m; - } - return null; - } catch (Exception e) { - throw new GrailsDomainException("Error evaluating ORM mappings block for domain [" + - domainClass.getFullName() + "]: " + e.getMessage(), e); - } - } - - /** - * Checks for any custom cascading saves set up via the mapping DSL and records them within the persistent property. - * @param mapping The Mapping. - * @param persistentProperties The persistent properties of the domain class. - */ - protected void trackCustomCascadingSaves(Mapping mapping, GrailsDomainClassProperty[] persistentProperties) { - for (GrailsDomainClassProperty property : persistentProperties) { - PropertyConfig propConf = mapping.getPropertyConfig(property.getName()); - - if (propConf != null && propConf.getCascade() != null) { - property.setExplicitSaveUpdateCascade(isSaveUpdateCascade(propConf.getCascade())); - } - } - } - - /** - * Check if a save-update cascade is defined within the Hibernate cascade properties string. - * @param cascade The string containing the cascade properties. - * @return True if save-update or any other cascade property that encompasses those is present. - */ - protected boolean isSaveUpdateCascade(String cascade) { - String[] cascades = cascade.split(","); - - for (String cascadeProp : cascades) { - String trimmedProp = cascadeProp.trim(); - - if (CASCADE_SAVE_UPDATE.equals(trimmedProp) || CASCADE_ALL.equals(trimmedProp) || CASCADE_ALL_DELETE_ORPHAN.equals(trimmedProp)) { - return true; - } - } - - return false; - } - - /** - * Obtains a mapping object for the given domain class nam - * - * @param theClass The domain class in question - * @return A Mapping object or null - */ - public Mapping getMapping(Class theClass) { - return theClass == null ? null : MAPPING_CACHE.get(theClass); - } - - /** - * Obtains a mapping object for the given domain class nam - * - * @param domainClass The domain class in question - * @return A Mapping object or null - */ - public Mapping getMapping(GrailsDomainClass domainClass) { - return domainClass == null ? null : MAPPING_CACHE.get(domainClass.getClazz()); - } - - public void clearMappingCache() { - MAPPING_CACHE.clear(); - } - - public void clearMappingCache(Class theClass) { - String className = theClass.getName(); - for(Iterator, Mapping>> it = MAPPING_CACHE.entrySet().iterator(); it.hasNext();) { - Map.Entry, Mapping> entry = it.next(); - if (className.equals(entry.getKey().getName())) { - it.remove(); - } - } - } - - /** - * Binds the specified persistant class to the runtime model based on the - * properties defined in the domain class - * - * @param domainClass The Grails domain class - * @param persistentClass The persistant class - * @param mappings Existing mappings - */ - protected void bindClass(GrailsDomainClass domainClass, PersistentClass persistentClass, Mappings mappings) { - - // set lazy loading for now - persistentClass.setLazy(true); - persistentClass.setEntityName(domainClass.getFullName()); - persistentClass.setJpaEntityName(unqualify(domainClass.getFullName())); - persistentClass.setProxyInterfaceName(domainClass.getFullName()); - persistentClass.setClassName(domainClass.getFullName()); - - // set dynamic insert to false - persistentClass.setDynamicInsert(false); - // set dynamic update to false - persistentClass.setDynamicUpdate(false); - // set select before update to false - persistentClass.setSelectBeforeUpdate(false); - - // add import to mappings - if (mappings.isAutoImport() && persistentClass.getEntityName().indexOf('.') > 0) { - mappings.addImport(persistentClass.getEntityName(), unqualify(persistentClass.getEntityName())); - } - } - - /** - * Binds a root class (one with no super classes) to the runtime meta model - * based on the supplied Grails domain class - * - * @param domainClass The Grails domain class - * @param mappings The Hibernate Mappings object - * @param sessionFactoryBeanName the session factory bean name - */ - public void bindRoot(GrailsDomainClass domainClass, Mappings mappings, String sessionFactoryBeanName) { - if (mappings.getClass(domainClass.getFullName()) != null) { - LOG.info("[GrailsDomainBinder] Class [" + domainClass.getFullName() + "] is already mapped, skipping.. "); - return; - } - - RootClass root = new RootClass(); - root.setAbstract(Modifier.isAbstract(domainClass.getClazz().getModifiers())); - if (!domainClass.hasSubClasses()) { - root.setPolymorphic(false); - } - bindClass(domainClass, root, mappings); - - Mapping m = getMapping(domainClass); - - bindRootPersistentClassCommonValues(domainClass, root, mappings, sessionFactoryBeanName); - - if (!domainClass.getSubClasses().isEmpty()) { - boolean tablePerSubclass = m != null && !m.getTablePerHierarchy(); - if (!tablePerSubclass) { - // if the root class has children create a discriminator property - bindDiscriminatorProperty(root.getTable(), root, mappings); - } - // bind the sub classes - bindSubClasses(domainClass, root, mappings, sessionFactoryBeanName); - } - - if (root.getEntityPersisterClass() == null) { - root.setEntityPersisterClass(getGroovyAwareSingleTableEntityPersisterClass()); - } - mappings.addClass(root); - } - - /** - * Binds the sub classes of a root class using table-per-heirarchy inheritance mapping - * - * @param domainClass The root domain class to bind - * @param parent The parent class instance - * @param mappings The mappings instance - * @param sessionFactoryBeanName the session factory bean name - */ - protected void bindSubClasses(GrailsDomainClass domainClass, PersistentClass parent, - Mappings mappings, String sessionFactoryBeanName) { - Set subClasses = new HashSet(domainClass.getSubClasses()); - - for (GrailsDomainClass sub : subClasses) { - if (sub.getClazz().getSuperclass().equals(domainClass.getClazz())) { - bindSubClass(sub, parent, mappings, sessionFactoryBeanName); - } - } - } - - /** - * Binds a sub class. - * - * @param sub The sub domain class instance - * @param parent The parent persistent class instance - * @param mappings The mappings instance - * @param sessionFactoryBeanName the session factory bean name - */ - protected void bindSubClass(GrailsDomainClass sub, PersistentClass parent, - Mappings mappings, String sessionFactoryBeanName) { - evaluateMapping(sub); - Mapping m = getMapping(parent.getMappedClass()); - Subclass subClass; - boolean tablePerSubclass = m != null && !m.getTablePerHierarchy() && !m.isTablePerConcreteClass(); - boolean tablePerConcreteClass = m != null && m.isTablePerConcreteClass(); - if (tablePerSubclass) { - subClass = new JoinedSubclass(parent); - } - else if(tablePerConcreteClass) { - subClass = new UnionSubclass(parent); - } - else { - subClass = new SingleTableSubclass(parent); - // set the descriminator value as the name of the class. This is the - // value used by Hibernate to decide what the type of the class is - // to perform polymorphic queries - Mapping subMapping = getMapping(sub); - subClass.setDiscriminatorValue(subMapping != null && subMapping.getDiscriminator() != null ? subMapping.getDiscriminator() : sub.getFullName()); - if (subMapping != null) { - configureDerivedProperties(sub, subMapping); - } - } - - subClass.setEntityName(sub.getFullName()); - subClass.setJpaEntityName(unqualify(sub.getFullName())); - - parent.addSubclass(subClass); - mappings.addClass(subClass); - - if (tablePerSubclass) { - bindJoinedSubClass(sub, (JoinedSubclass) subClass, mappings, m, sessionFactoryBeanName); - } - else if( tablePerConcreteClass) { - bindUnionSubclass(sub, (UnionSubclass) subClass, mappings, sessionFactoryBeanName); - } - else { - bindSubClass(sub, subClass, mappings, sessionFactoryBeanName); - } - - if (!sub.getSubClasses().isEmpty()) { - // bind the sub classes - bindSubClasses(sub, subClass, mappings, sessionFactoryBeanName); - } - } - - - public void bindUnionSubclass(GrailsDomainClass subClass, UnionSubclass unionSubclass, - Mappings mappings, String sessionFactoryBeanName) throws MappingException { - - - Mapping subMapping = getMapping(subClass.getClazz()); - - if ( unionSubclass.getEntityPersisterClass() == null ) { - unionSubclass.getRootClass().setEntityPersisterClass( - UnionSubclassEntityPersister.class ); - } - - String schema = subMapping != null && subMapping.getTable().getSchema() != null ? - subMapping.getTable().getSchema() : null; - - String catalog = subMapping != null && subMapping.getTable().getCatalog() != null ? - subMapping.getTable().getCatalog() : null; - - Table denormalizedSuperTable = unionSubclass.getSuperclass().getTable(); - Table mytable = mappings.addDenormalizedTable( - schema, - catalog, - getTableName(subClass, sessionFactoryBeanName), - unionSubclass.isAbstract() != null && unionSubclass.isAbstract(), - null, - denormalizedSuperTable - ); - unionSubclass.setTable( mytable ); - unionSubclass.setClassName(subClass.getFullName()); - - LOG.info( - "Mapping union-subclass: " + unionSubclass.getEntityName() + - " -> " + unionSubclass.getTable().getName() - ); - - createClassProperties(subClass, unionSubclass, mappings, sessionFactoryBeanName); - - } - /** - * Binds a joined sub-class mapping using table-per-subclass - * - * @param sub The Grails sub class - * @param joinedSubclass The Hibernate Subclass object - * @param mappings The mappings Object - * @param gormMapping The GORM mapping object - * @param sessionFactoryBeanName the session factory bean name - */ - protected void bindJoinedSubClass(GrailsDomainClass sub, JoinedSubclass joinedSubclass, - Mappings mappings, Mapping gormMapping, String sessionFactoryBeanName) { - bindClass(sub, joinedSubclass, mappings); - - if (joinedSubclass.getEntityPersisterClass() == null) { - joinedSubclass.getRootClass().setEntityPersisterClass(getGroovyAwareJoinedSubclassEntityPersisterClass()); - } - - Table mytable = mappings.addTable( - mappings.getSchemaName(), mappings.getCatalogName(), - getJoinedSubClassTableName(sub, joinedSubclass, null, mappings, sessionFactoryBeanName), - null, false); - - joinedSubclass.setTable(mytable); - LOG.info("Mapping joined-subclass: " + joinedSubclass.getEntityName() + - " -> " + joinedSubclass.getTable().getName()); - - SimpleValue key = new DependantValue(mappings, mytable, joinedSubclass.getIdentifier()); - joinedSubclass.setKey(key); - GrailsDomainClassProperty identifier = sub.getIdentifier(); - String columnName = getColumnNameForPropertyAndPath(identifier, EMPTY_PATH, null, sessionFactoryBeanName); - bindSimpleValue(identifier.getType().getName(), key, false, columnName, mappings); - - joinedSubclass.createPrimaryKey(); - - // properties - createClassProperties(sub, joinedSubclass, mappings, sessionFactoryBeanName); - } - - protected String getJoinedSubClassTableName( - GrailsDomainClass sub, PersistentClass model, Table denormalizedSuperTable, - Mappings mappings, String sessionFactoryBeanName) { - - String logicalTableName = unqualify(model.getEntityName()); - String physicalTableName = getTableName(sub, sessionFactoryBeanName); - - mappings.addTableBinding(mappings.getSchemaName(), mappings.getCatalogName(), logicalTableName, physicalTableName, denormalizedSuperTable); - return physicalTableName; - } - - /** - * Binds a sub-class using table-per-hierarchy inheritance mapping - * - * @param sub The Grails domain class instance representing the sub-class - * @param subClass The Hibernate SubClass instance - * @param mappings The mappings instance - */ - protected void bindSubClass(GrailsDomainClass sub, Subclass subClass, Mappings mappings, - String sessionFactoryBeanName) { - bindClass(sub, subClass, mappings); - - if (subClass.getEntityPersisterClass() == null) { - subClass.getRootClass().setEntityPersisterClass(getGroovyAwareSingleTableEntityPersisterClass()); - } - - if (LOG.isDebugEnabled()) - LOG.debug("Mapping subclass: " + subClass.getEntityName() + - " -> " + subClass.getTable().getName()); - - // properties - createClassProperties(sub, subClass, mappings, sessionFactoryBeanName); - } - - /** - * Creates and binds the discriminator property used in table-per-hierarchy inheritance to - * discriminate between sub class instances - * - * @param table The table to bind onto - * @param entity The root class entity - * @param mappings The mappings instance - */ - protected void bindDiscriminatorProperty(Table table, RootClass entity, Mappings mappings) { - Mapping m = getMapping(entity.getMappedClass()); - SimpleValue d = new SimpleValue(mappings, table); - entity.setDiscriminator(d); - entity.setDiscriminatorValue(m != null && m.getDiscriminator() != null ? m.getDiscriminator() : entity.getClassName()); - - if (m != null && m.getDiscriminatorMap().get("insert") != null) { - entity.setDiscriminatorInsertable((Boolean)m.getDiscriminatorMap().get("insert")); - } - if (m != null && m.getDiscriminatorMap().get("type") != null) { - d.setTypeName((String)m.getDiscriminatorMap().get("type")); - } - - if (m != null && m.getDiscriminatorMap().get("formula") != null) { - Formula formula = new Formula(); - formula.setFormula((String)m.getDiscriminatorMap().get("formula")); - d.addFormula(formula); - } - else{ - bindSimpleValue(STRING_TYPE, d, false, RootClass.DEFAULT_DISCRIMINATOR_COLUMN_NAME, mappings); - - ColumnConfig cc = m == null ? null : m.getDiscriminatorColumn(); - if (cc != null) { - Column c = (Column) d.getColumnIterator().next(); - if (cc.getName() != null) { - c.setName(cc.getName()); - } - bindColumnConfigToColumn(c, cc); - } - } - - entity.setPolymorphic(true); - } - - protected void configureDerivedProperties(GrailsDomainClass domainClass, Mapping m) { - for (GrailsDomainClassProperty prop : domainClass.getPersistentProperties()) { - PropertyConfig propertyConfig = m.getPropertyConfig(prop.getName()); - if (propertyConfig != null && propertyConfig.getFormula() != null) { - prop.setDerived(true); - } - } - } - - /* - * Binds a persistent classes to the table representation and binds the class properties - */ - protected void bindRootPersistentClassCommonValues(GrailsDomainClass domainClass, - RootClass root, Mappings mappings, String sessionFactoryBeanName) { - - // get the schema and catalog names from the configuration - Mapping m = getMapping(domainClass.getClazz()); - String schema = mappings.getSchemaName(); - String catalog = mappings.getCatalogName(); - - if (m != null) { - configureDerivedProperties(domainClass, m); - CacheConfig cc = m.getCache(); - if (cc != null && cc.getEnabled()) { - root.setCacheConcurrencyStrategy(cc.getUsage()); - if ("read-only".equals(cc.getUsage())) { - root.setMutable(false); - } - root.setLazyPropertiesCacheable(!"non-lazy".equals(cc.getInclude())); - } - - Integer bs = m.getBatchSize(); - if (bs != null) { - root.setBatchSize(bs); - } - - if (m.getDynamicUpdate()) { - root.setDynamicUpdate(true); - } - if (m.getDynamicInsert()) { - root.setDynamicInsert(true); - } - } - - final boolean hasTableDefinition = m != null && m.getTable() != null; - if (hasTableDefinition && m.getTable().getSchema() != null) { - schema = m.getTable().getSchema(); - } - if (hasTableDefinition && m.getTable().getCatalog() != null) { - catalog = m.getTable().getCatalog(); - } - - // create the table - Table table = mappings.addTable(schema, catalog, - getTableName(domainClass, sessionFactoryBeanName), - null, false); - root.setTable(table); - - if (LOG.isDebugEnabled()) { - LOG.debug("[GrailsDomainBinder] Mapping Grails domain class: " + domainClass.getFullName() + " -> " + root.getTable().getName()); - } - - bindIdentity(domainClass, root, mappings, m, sessionFactoryBeanName); - - if (m == null) { - bindVersion(domainClass.getVersion(), root, mappings, sessionFactoryBeanName); - } - else { - if (m.getVersioned()) { - bindVersion(domainClass.getVersion(), root, mappings, sessionFactoryBeanName); - } - } - - root.createPrimaryKey(); - - createClassProperties(domainClass, root, mappings, sessionFactoryBeanName); - } - - protected void bindIdentity(GrailsDomainClass domainClass, RootClass root, Mappings mappings, - Mapping gormMapping, String sessionFactoryBeanName) { - - GrailsDomainClassProperty identifierProp = domainClass.getIdentifier(); - if (gormMapping == null) { - bindSimpleId(identifierProp, root, mappings, null, sessionFactoryBeanName); - return; - } - - Object id = gormMapping.getIdentity(); - if (id instanceof CompositeIdentity) { - bindCompositeId(domainClass, root, (CompositeIdentity) id, mappings, sessionFactoryBeanName); - } else { - final Identity identity = (Identity) id; - String propertyName = identity.getName(); - if (propertyName != null) { - GrailsDomainClassProperty namedIdentityProp = domainClass.getPropertyByName(propertyName); - if (namedIdentityProp == null) { - throw new MappingException("Mapping specifies an identifier property name that doesn't exist ["+propertyName+"]"); - } - if (!namedIdentityProp.equals(identifierProp)) { - identifierProp = namedIdentityProp; - } - } - bindSimpleId(identifierProp, root, mappings, identity, sessionFactoryBeanName); - } - } - - protected void bindCompositeId(GrailsDomainClass domainClass, RootClass root, - CompositeIdentity compositeIdentity, Mappings mappings, String sessionFactoryBeanName) { - Component id = new Component(mappings, root); - id.setNullValue("undefined"); - root.setIdentifier(id); - root.setEmbeddedIdentifier(true); - id.setComponentClassName(domainClass.getFullName()); - id.setKey(true); - id.setEmbedded(true); - - String path = qualify(root.getEntityName(), "id"); - - id.setRoleName(path); - - String[] props = compositeIdentity.getPropertyNames(); - for (String propName : props) { - GrailsDomainClassProperty property = domainClass.getPropertyByName(propName); - if (property == null) { - throw new MappingException("Property [" + propName + - "] referenced in composite-id mapping of class [" + domainClass.getFullName() + - "] is not a valid property!"); - } - - bindComponentProperty(id, null, property, root, "", root.getTable(), mappings, sessionFactoryBeanName); - } - } - - /** - * Creates and binds the properties for the specified Grails domain class and PersistentClass - * and binds them to the Hibernate runtime meta model - * - * @param domainClass The Grails domain class - * @param persistentClass The Hibernate PersistentClass instance - * @param mappings The Hibernate Mappings instance - * @param sessionFactoryBeanName the session factory bean name - */ - protected void createClassProperties(GrailsDomainClass domainClass, PersistentClass persistentClass, - Mappings mappings, String sessionFactoryBeanName) { - - GrailsDomainClassProperty[] persistentProperties = domainClass.getPersistentProperties(); - Table table = persistentClass.getTable(); - - Mapping gormMapping = getMapping(domainClass.getClazz()); - - if (gormMapping != null) { - table.setComment(gormMapping.getComment()); - } - - for (GrailsDomainClassProperty currentGrailsProp : persistentProperties) { - - // if its inherited skip - boolean isBidirectionalManyToOne = isBidirectionalManyToOne(currentGrailsProp); - if (currentGrailsProp.isInherited()) { - continue; - } - if (currentGrailsProp.isInherited() && isBidirectionalManyToOne && currentGrailsProp.isCircular()) { - continue; - } - if (isCompositeIdProperty(gormMapping, currentGrailsProp)) continue; - if (isIdentityProperty(gormMapping, currentGrailsProp)) continue; - - if (LOG.isDebugEnabled()) { - LOG.debug("[GrailsDomainBinder] Binding persistent property [" + currentGrailsProp.getName() + "]"); - } - - Value value = null; - - // see if it's a collection type - CollectionType collectionType = CT.collectionTypeForClass(currentGrailsProp.getType()); - - Class userType = getUserType(currentGrailsProp); - - if (collectionType != null) { - String typeName = getTypeName(currentGrailsProp, getPropertyConfig(currentGrailsProp),gormMapping); - if ("serializable".equals(typeName)) { - value = new SimpleValue(mappings, table); - bindSimpleValue(typeName, (SimpleValue) value, currentGrailsProp.isOptional(), - getColumnNameForPropertyAndPath(currentGrailsProp, EMPTY_PATH, null, sessionFactoryBeanName), mappings); - } - else { - // create collection - Collection collection = collectionType.create(currentGrailsProp, persistentClass, - EMPTY_PATH, mappings, sessionFactoryBeanName); - mappings.addCollection(collection); - value = collection; - } - } - else if (currentGrailsProp.isEnum()) { - value = new SimpleValue(mappings, table); - bindEnumType(currentGrailsProp, (SimpleValue) value, EMPTY_PATH, sessionFactoryBeanName); - } - // work out what type of relationship it is and bind value - else if (currentGrailsProp.isManyToOne()) { - if (LOG.isDebugEnabled()) - LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as ManyToOne"); - - value = new ManyToOne(mappings, table); - bindManyToOne(currentGrailsProp, (ManyToOne) value, EMPTY_PATH, mappings, sessionFactoryBeanName); - } - else if (currentGrailsProp.isOneToOne() && userType == null) { - if (LOG.isDebugEnabled()) - LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as OneToOne"); - - if (currentGrailsProp.isHasOne()&&!currentGrailsProp.isBidirectional()) { - throw new MappingException("hasOne property [" + currentGrailsProp.getDomainClass().getName() + - "." + currentGrailsProp.getName() + "] is not bidirectional. Specify the other side of the relationship!"); - } - else if (canBindOneToOneWithSingleColumnAndForeignKey(currentGrailsProp)) { - value = new OneToOne(mappings, table, persistentClass); - bindOneToOne(currentGrailsProp, (OneToOne) value, EMPTY_PATH, sessionFactoryBeanName); - } - else { - if (currentGrailsProp.isHasOne() && currentGrailsProp.isBidirectional()) { - value = new OneToOne(mappings, table, persistentClass); - bindOneToOne(currentGrailsProp, (OneToOne) value, EMPTY_PATH, sessionFactoryBeanName); - } - else { - value = new ManyToOne(mappings, table); - bindManyToOne(currentGrailsProp, (ManyToOne) value, EMPTY_PATH, mappings, sessionFactoryBeanName); - } - } - } - else if (currentGrailsProp.isEmbedded()) { - value = new Component(mappings, persistentClass); - - bindComponent((Component) value, currentGrailsProp, true, mappings, sessionFactoryBeanName); - } - else { - if (LOG.isDebugEnabled()) { - LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as SimpleValue"); - } - value = new SimpleValue(mappings, table); - bindSimpleValue(currentGrailsProp, null, (SimpleValue) value, EMPTY_PATH, mappings, sessionFactoryBeanName); - } - - if (value != null) { - Property property = createProperty(value, persistentClass, currentGrailsProp, mappings); - persistentClass.addProperty(property); - } - } - - bindNaturalIdentifier(table, gormMapping, persistentClass); - } - - protected void bindNaturalIdentifier(Table table, Mapping mapping, PersistentClass persistentClass) { - Object o = mapping != null ? mapping.getIdentity() : null; - if (!(o instanceof Identity)) { - return; - } - - Identity identity = (Identity) o; - final NaturalId naturalId = identity.getNatural(); - if (naturalId == null || naturalId.getPropertyNames().isEmpty()) { - return; - } - - UniqueKey uk = new UniqueKey(); - uk.setTable(table); - - boolean mutable = naturalId.isMutable(); - - for (String propertyName : naturalId.getPropertyNames()) { - Property property = persistentClass.getProperty(propertyName); - - property.setNaturalIdentifier(true); - if (!mutable) property.setUpdateable(false); - - uk.addColumns(property.getColumnIterator()); - } - - setUniqueName(uk); - - table.addUniqueKey(uk); - } - - protected void setUniqueName(UniqueKey uk) { - StringBuilder sb = new StringBuilder(uk.getTable().getName()).append('_'); - for (Object col : uk.getColumns()) { - sb.append(((Column) col).getName()).append('_'); - } - - MessageDigest md; - try { - md = MessageDigest.getInstance("MD5"); - } - catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - try { - md.update(sb.toString().getBytes("UTF-8")); - } - catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - - String name = "UK" + new BigInteger(1, md.digest()).toString(16); - if (name.length() > 30) { - // Oracle has a 30-char limit - name = name.substring(0, 30); - } - - uk.setName(name); - } - - protected boolean canBindOneToOneWithSingleColumnAndForeignKey(GrailsDomainClassProperty currentGrailsProp) { - if (currentGrailsProp.isBidirectional()) { - final GrailsDomainClassProperty otherSide = currentGrailsProp.getOtherSide(); - if (otherSide.isHasOne()) return false; - if (!currentGrailsProp.isOwningSide() && (otherSide.isOwningSide())) { - return true; - } - } - return false; - } - - protected boolean isIdentityProperty(Mapping gormMapping, GrailsDomainClassProperty currentGrailsProp) { - if (gormMapping == null) { - return false; - } - - Object identityMapping = gormMapping.getIdentity(); - if (!(identityMapping instanceof Identity)) { - return false; - } - - String identityName = ((Identity)identityMapping).getName(); - return identityName != null && identityName.equals(currentGrailsProp.getName()); - } - - protected void bindEnumType(GrailsDomainClassProperty property, SimpleValue simpleValue, - String path, String sessionFactoryBeanName) { - bindEnumType(property, property.getType(), simpleValue, - getColumnNameForPropertyAndPath(property, path, null, sessionFactoryBeanName)); - } - - protected void bindEnumType(GrailsDomainClassProperty property, Class propertyType, SimpleValue simpleValue, String columnName) { - - PropertyConfig pc = getPropertyConfig(property); - String typeName = getTypeName(property, getPropertyConfig(property), getMapping(property.getDomainClass())); - if (typeName == null) { - Properties enumProperties = new Properties(); - enumProperties.put(ENUM_CLASS_PROP, propertyType.getName()); - - String enumType = pc == null ? DEFAULT_ENUM_TYPE : pc.getEnumType(); - if (enumType.equals(DEFAULT_ENUM_TYPE) && identityEnumTypeSupports(propertyType)) { - simpleValue.setTypeName("org.codehaus.groovy.grails.orm.hibernate.cfg.IdentityEnumType"); - } else { - simpleValue.setTypeName(ENUM_TYPE_CLASS); - if (enumType.equals(DEFAULT_ENUM_TYPE) || "string".equalsIgnoreCase(enumType)) { - enumProperties.put(ENUM_TYPE_PROP, String.valueOf(Types.VARCHAR)); - } - else if (!"ordinal".equalsIgnoreCase(enumType)) { - LOG.warn("Invalid enumType specified when mapping property [" + property.getName() + - "] of class [" + property.getDomainClass().getClazz().getName() + - "]. Using defaults instead."); - } - } - simpleValue.setTypeParameters(enumProperties); - } - else { - simpleValue.setTypeName(typeName); - } - - Table t = simpleValue.getTable(); - Column column = new Column(); - - if (property.getDomainClass().isRoot()) { - column.setNullable(property.isOptional()); - } else { - Mapping mapping = getMapping(property.getDomainClass()); - if (mapping == null || mapping.getTablePerHierarchy()) { - if (LOG.isDebugEnabled()) { - LOG.debug("[GrailsDomainBinder] Sub class property [" + property.getName() + - "] for column name [" + column.getName() + "] set to nullable"); - } - column.setNullable(true); - } else { - column.setNullable(property.isOptional()); - } - } - column.setValue(simpleValue); - column.setName(columnName); - if (t != null) t.addColumn(column); - - simpleValue.addColumn(column); - - PropertyConfig propertyConfig = getPropertyConfig(property); - if (propertyConfig != null && !propertyConfig.getColumns().isEmpty()) { - bindIndex(columnName, column, propertyConfig.getColumns().get(0), t); - bindColumnConfigToColumn(column, propertyConfig.getColumns().get(0)); - } - } - - protected Class getUserType(GrailsDomainClassProperty currentGrailsProp) { - Class userType = null; - PropertyConfig config = getPropertyConfig(currentGrailsProp); - Object typeObj = config == null ? null : config.getType(); - if (typeObj instanceof Class) { - userType = (Class)typeObj; - } else if (typeObj != null) { - String typeName = typeObj.toString(); - try { - userType = Class.forName(typeName, true, Thread.currentThread().getContextClassLoader()); - } catch (ClassNotFoundException e) { - // only print a warning if the user type is in a package this excludes basic - // types like string, int etc. - if (typeName.indexOf(".")>-1) { - if (LOG.isWarnEnabled()) { - LOG.warn("UserType not found ", e); - } - } - } - } - return userType; - } - - protected boolean isCompositeIdProperty(Mapping gormMapping, GrailsDomainClassProperty currentGrailsProp) { - if (gormMapping != null && gormMapping.getIdentity() != null) { - Object id = gormMapping.getIdentity(); - if (id instanceof CompositeIdentity) { - if (ArrayUtils.contains(((CompositeIdentity)id).getPropertyNames(), currentGrailsProp.getName())) { - return true; - } - } - } - return false; - } - - protected boolean isBidirectionalManyToOne(GrailsDomainClassProperty currentGrailsProp) { - return (currentGrailsProp.isBidirectional() && currentGrailsProp.isManyToOne()); - } - - /** - * Binds a Hibernate component type using the given GrailsDomainClassProperty instance - * - * @param component The component to bind - * @param property The property - * @param isNullable Whether it is nullable or not - * @param mappings The Hibernate Mappings object - * @param sessionFactoryBeanName the session factory bean name - */ - protected void bindComponent(Component component, GrailsDomainClassProperty property, - boolean isNullable, Mappings mappings, String sessionFactoryBeanName) { - component.setEmbedded(true); - Class type = property.getType(); - String role = qualify(type.getName(), property.getName()); - component.setRoleName(role); - component.setComponentClassName(type.getName()); - - GrailsDomainClass domainClass = property.getReferencedDomainClass() != null ? property.getReferencedDomainClass() : property.getComponent(); - - evaluateMapping(domainClass); - GrailsDomainClassProperty[] properties = domainClass.getPersistentProperties(); - Table table = component.getOwner().getTable(); - PersistentClass persistentClass = component.getOwner(); - String path = property.getName(); - Class propertyType = property.getDomainClass().getClazz(); - - for (GrailsDomainClassProperty currentGrailsProp : properties) { - if (currentGrailsProp.isIdentity()) continue; - if (currentGrailsProp.getName().equals(GrailsDomainClassProperty.VERSION)) continue; - - if (currentGrailsProp.getType().equals(propertyType)) { - component.setParentProperty(currentGrailsProp.getName()); - continue; - } - - bindComponentProperty(component, property, currentGrailsProp, persistentClass, path, - table, mappings, sessionFactoryBeanName); - } - } - - protected void bindComponentProperty(Component component, GrailsDomainClassProperty componentProperty, - GrailsDomainClassProperty currentGrailsProp, PersistentClass persistentClass, - String path, Table table, Mappings mappings, String sessionFactoryBeanName) { - Value value; - // see if it's a collection type - CollectionType collectionType = CT.collectionTypeForClass(currentGrailsProp.getType()); - if (collectionType != null) { - // create collection - Collection collection = collectionType.create(currentGrailsProp, persistentClass, - path, mappings, sessionFactoryBeanName); - mappings.addCollection(collection); - value = collection; - } - // work out what type of relationship it is and bind value - else if (currentGrailsProp.isManyToOne()) { - if (LOG.isDebugEnabled()) - LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as ManyToOne"); - - value = new ManyToOne(mappings, table); - bindManyToOne(currentGrailsProp, (ManyToOne) value, path, mappings, sessionFactoryBeanName); - } else if (currentGrailsProp.isOneToOne()) { - if (LOG.isDebugEnabled()) - LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as OneToOne"); - - if (canBindOneToOneWithSingleColumnAndForeignKey(currentGrailsProp)) { - value = new OneToOne(mappings, table, persistentClass); - bindOneToOne(currentGrailsProp, (OneToOne) value, path, sessionFactoryBeanName); - } - else { - value = new ManyToOne(mappings, table); - bindManyToOne(currentGrailsProp, (ManyToOne) value, path, mappings, sessionFactoryBeanName); - } - } - else if (currentGrailsProp.isEmbedded()) { - value = new Component(mappings, persistentClass); - bindComponent((Component) value, currentGrailsProp, true, mappings, sessionFactoryBeanName); - } - else { - if (LOG.isDebugEnabled()) - LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as SimpleValue"); - - value = new SimpleValue(mappings, table); - if (currentGrailsProp.isEnum()) { - bindEnumType(currentGrailsProp, (SimpleValue) value, path, sessionFactoryBeanName); - } - else { - bindSimpleValue(currentGrailsProp, componentProperty, (SimpleValue) value, path, - mappings, sessionFactoryBeanName); - } - } - - if (value != null) { - Property persistentProperty = createProperty(value, persistentClass, currentGrailsProp, mappings); - component.addProperty(persistentProperty); - if (isComponentPropertyNullable(componentProperty)) { - final Iterator columnIterator = value.getColumnIterator(); - while (columnIterator.hasNext()) { - Column c = (Column) columnIterator.next(); - c.setNullable(true); - } - } - } - } - - protected boolean isComponentPropertyNullable(GrailsDomainClassProperty componentProperty) { - if (componentProperty == null) return false; - final GrailsDomainClass domainClass = componentProperty.getDomainClass(); - final Mapping mapping = getMapping(domainClass.getClazz()); - return !domainClass.isRoot() && (mapping == null || mapping.isTablePerHierarchy()) || componentProperty.isOptional(); - } - - /* - * Creates a persistent class property based on the GrailDomainClassProperty instance. - */ - protected Property createProperty(Value value, PersistentClass persistentClass, GrailsDomainClassProperty grailsProperty, Mappings mappings) { - // set type - value.setTypeUsingReflection(persistentClass.getClassName(), grailsProperty.getName()); - - if (value.getTable() != null) { - value.createForeignKey(); - } - - Property prop = new Property(); - prop.setValue(value); - bindProperty(grailsProperty, prop, mappings); - return prop; - } - - protected void bindOneToMany(GrailsDomainClassProperty currentGrailsProp, OneToMany one, Mappings mappings) { - one.setReferencedEntityName(currentGrailsProp.getReferencedPropertyType().getName()); - one.setIgnoreNotFound(true); - } - - /** - * Binds a many-to-one relationship to the - * - */ - @SuppressWarnings("unchecked") - protected void bindManyToOne(GrailsDomainClassProperty property, ManyToOne manyToOne, - String path, Mappings mappings, String sessionFactoryBeanName) { - - NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); - - bindManyToOneValues(property, manyToOne); - GrailsDomainClass refDomainClass = property.isManyToMany() ? property.getDomainClass() : property.getReferencedDomainClass(); - Mapping mapping = getMapping(refDomainClass); - boolean isComposite = hasCompositeIdentifier(mapping); - if (isComposite) { - CompositeIdentity ci = (CompositeIdentity) mapping.getIdentity(); - bindCompositeIdentifierToManyToOne(property, manyToOne, ci, refDomainClass, path, sessionFactoryBeanName); - } - else { - if (property.isCircular() && property.isManyToMany()) { - PropertyConfig pc = getPropertyConfig(property); - - if (pc == null) { - if (mapping == null) { - mapping = new Mapping(); - MAPPING_CACHE.put(refDomainClass.getClazz(), mapping); - } - pc = new PropertyConfig(); - mapping.getColumns().put(property.getName(), pc); - } - if (!hasJoinKeyMapping(pc)) { - JoinTable jt = new JoinTable(); - final ColumnConfig columnConfig = new ColumnConfig(); - columnConfig.setName(namingStrategy.propertyToColumnName(property.getName()) + - UNDERSCORE + FOREIGN_KEY_SUFFIX); - jt.setKey(columnConfig); - pc.setJoinTable(jt); - } - bindSimpleValue(property, manyToOne, path, pc, sessionFactoryBeanName); - } - else { - // bind column - bindSimpleValue(property, null, manyToOne, path, mappings, sessionFactoryBeanName); - } - } - - PropertyConfig config = getPropertyConfig(property); - if (property.isOneToOne() && !isComposite) { - manyToOne.setAlternateUniqueKey(true); - Column c = getColumnForSimpleValue(manyToOne); - if (config != null) { - c.setUnique(config.isUnique()); - } - else if (property.isBidirectional() && property.getOtherSide().isHasOne()) { - c.setUnique(true); - } - } - } - - protected void bindCompositeIdentifierToManyToOne(GrailsDomainClassProperty property, - SimpleValue value, CompositeIdentity compositeId, GrailsDomainClass refDomainClass, - String path, String sessionFactoryBeanName) { - - NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); - - String[] propertyNames = compositeId.getPropertyNames(); - PropertyConfig config = getPropertyConfig(property); - if (config == null) config = new PropertyConfig(); - - if (config.getColumns().size() != propertyNames.length) { - for (String propertyName : propertyNames) { - final ColumnConfig cc = new ColumnConfig(); - cc.setName(addUnderscore(namingStrategy.classToTableName(refDomainClass.getShortName()), - getDefaultColumnName(refDomainClass.getPropertyByName(propertyName), sessionFactoryBeanName))); - config.getColumns().add(cc); - } - } - bindSimpleValue(property, value, path, config, sessionFactoryBeanName); - } - - protected boolean hasCompositeIdentifier(Mapping mapping) { - return mapping != null && (mapping.getIdentity() instanceof CompositeIdentity); - } - - protected void bindOneToOne(final GrailsDomainClassProperty property, OneToOne oneToOne, - String path, String sessionFactoryBeanName) { - PropertyConfig config = getPropertyConfig(property); - final GrailsDomainClassProperty otherSide = property.getOtherSide(); - - oneToOne.setConstrained(otherSide.isHasOne()); - oneToOne.setForeignKeyType(oneToOne.isConstrained() ? - ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT : - ForeignKeyDirection.FOREIGN_KEY_TO_PARENT); - oneToOne.setAlternateUniqueKey(true); - - if (config != null && config.getFetch() != null) { - oneToOne.setFetchMode(config.getFetch()); - } - else { - oneToOne.setFetchMode(FetchMode.DEFAULT); - } - - oneToOne.setReferencedEntityName(otherSide.getDomainClass().getFullName()); - oneToOne.setPropertyName(property.getName()); - - if (otherSide.isHasOne()) { - PropertyConfig pc = getPropertyConfig(property); - bindSimpleValue(property, oneToOne, path, pc, sessionFactoryBeanName); - } - else { - oneToOne.setReferencedPropertyName(otherSide.getName()); - } - } - - /** - */ - protected void bindManyToOneValues(GrailsDomainClassProperty property, ManyToOne manyToOne) { - PropertyConfig config = getPropertyConfig(property); - - if (config != null && config.getFetch() != null) { - manyToOne.setFetchMode(config.getFetch()); - } - else { - manyToOne.setFetchMode(FetchMode.DEFAULT); - } - - manyToOne.setLazy(getLaziness(property)); - - if (config != null) { - manyToOne.setIgnoreNotFound(config.getIgnoreNotFound()); - } - - // set referenced entity - manyToOne.setReferencedEntityName(property.getReferencedPropertyType().getName()); - } - - protected void bindVersion(GrailsDomainClassProperty version, RootClass entity, - Mappings mappings, String sessionFactoryBeanName) { - - SimpleValue val = new SimpleValue(mappings, entity.getTable()); - - bindSimpleValue(version, null, val, EMPTY_PATH, mappings, sessionFactoryBeanName); - - if (val.isTypeSpecified()) { - if (!(val.getType() instanceof IntegerType || - val.getType() instanceof LongType || - val.getType() instanceof TimestampType)) { - LOG.warn("Invalid version class specified in " + version.getDomainClass().getClazz().getName() + - "; must be one of [int, Integer, long, Long, Timestamp, Date]. Not mapping the version."); - return; - } - } - else { - val.setTypeName("version".equals(version.getName()) ? "integer" : "timestamp"); - } - Property prop = new Property(); - prop.setValue(val); - - bindProperty(version, prop, mappings); - val.setNullValue("undefined"); - entity.setVersion(prop); - entity.addProperty(prop); - } - - @SuppressWarnings("unchecked") - protected void bindSimpleId(GrailsDomainClassProperty identifier, RootClass entity, - Mappings mappings, Identity mappedId, String sessionFactoryBeanName) { - - Mapping mapping = getMapping(identifier.getDomainClass()); - boolean useSequence = mapping != null && mapping.isTablePerConcreteClass(); - - // create the id value - SimpleValue id = new SimpleValue(mappings, entity.getTable()); - // set identifier on entity - - Properties params = new Properties(); - entity.setIdentifier(id); - - if (mappedId == null) { - // configure generator strategy - id.setIdentifierGeneratorStrategy(useSequence ? "sequence" : "native"); - } else { - String generator = mappedId.getGenerator(); - if("native".equals(generator) && useSequence) { - generator = "sequence"; - } - id.setIdentifierGeneratorStrategy(generator); - params.putAll(mappedId.getParams()); - if ("assigned".equals(generator)) { - id.setNullValue("undefined"); - } - } - - params.put(PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, mappings.getObjectNameNormalizer()); - - if (mappings.getSchemaName() != null) { - params.setProperty(PersistentIdentifierGenerator.SCHEMA, mappings.getSchemaName()); - } - if (mappings.getCatalogName() != null) { - params.setProperty(PersistentIdentifierGenerator.CATALOG, mappings.getCatalogName()); - } - id.setIdentifierGeneratorProperties(params); - - // bind value - bindSimpleValue(identifier, null, id, EMPTY_PATH, mappings, sessionFactoryBeanName); - - // create property - Property prop = new Property(); - prop.setValue(id); - - // bind property - bindProperty(identifier, prop, mappings); - // set identifier property - entity.setIdentifierProperty(prop); - - id.getTable().setIdentifierValue(id); - } - - /** - * Binds a property to Hibernate runtime meta model. Deals with cascade strategy based on the Grails domain model - * - * @param grailsProperty The grails property instance - * @param prop The Hibernate property - * @param mappings The Hibernate mappings - */ - protected void bindProperty(GrailsDomainClassProperty grailsProperty, Property prop, Mappings mappings) { - // set the property name - prop.setName(grailsProperty.getName()); - if (isBidirectionalManyToOneWithListMapping(grailsProperty, prop)) { - prop.setInsertable(false); - prop.setUpdateable(false); - } else { - prop.setInsertable(getInsertableness(grailsProperty)); - prop.setUpdateable(getUpdateableness(grailsProperty)); - } - - prop.setPropertyAccessorName(mappings.getDefaultAccess()); - prop.setOptional(grailsProperty.isOptional()); - - setCascadeBehaviour(grailsProperty, prop); - - // lazy to true - boolean isLazyable = grailsProperty.isOneToOne() || - grailsProperty.isManyToOne() || - grailsProperty.isEmbedded() || - grailsProperty.isPersistent() && !grailsProperty.isAssociation() && !grailsProperty.isIdentity(); - - if (isLazyable) { - final boolean isLazy = getLaziness(grailsProperty); - prop.setLazy(isLazy); - - if (isLazy && (grailsProperty.isManyToOne() || grailsProperty.isOneToOne())) { - handleLazyProxy(grailsProperty.getDomainClass(), grailsProperty); - } - } - } - - protected boolean getLaziness(GrailsDomainClassProperty grailsProperty) { - PropertyConfig config = getPropertyConfig(grailsProperty); - return config == null ? true : config.getLazy(); - } - - protected boolean getInsertableness(GrailsDomainClassProperty grailsProperty) { - PropertyConfig config = getPropertyConfig(grailsProperty); - return config == null ? true : config.getInsertable(); - } - - protected boolean getUpdateableness(GrailsDomainClassProperty grailsProperty) { - PropertyConfig config = getPropertyConfig(grailsProperty); - return config == null ? true : config.getUpdateable(); - } - - protected boolean isBidirectionalManyToOneWithListMapping(GrailsDomainClassProperty grailsProperty, Property prop) { - GrailsDomainClassProperty otherSide = grailsProperty.getOtherSide(); - return grailsProperty.isBidirectional() && otherSide != null && - prop.getValue() instanceof ManyToOne && - List.class.isAssignableFrom(otherSide.getType()); - } - - protected void setCascadeBehaviour(GrailsDomainClassProperty grailsProperty, Property prop) { - String cascadeStrategy = "none"; - // set to cascade all for the moment - GrailsDomainClass domainClass = grailsProperty.getDomainClass(); - PropertyConfig config = getPropertyConfig(grailsProperty); - GrailsDomainClass referenced = grailsProperty.getReferencedDomainClass(); - if (config != null && config.getCascade() != null) { - cascadeStrategy = config.getCascade(); - } else if (grailsProperty.isAssociation()) { - if (grailsProperty.isHasOne()) { - cascadeStrategy = CASCADE_ALL; - } - else if (grailsProperty.isOneToOne()) { - if (referenced != null && referenced.isOwningClass(domainClass.getClazz())) { - cascadeStrategy = CASCADE_ALL; - } - } else if (grailsProperty.isOneToMany()) { - if (referenced != null && referenced.isOwningClass(domainClass.getClazz())) { - cascadeStrategy = CASCADE_ALL; - } - else { - cascadeStrategy = CASCADE_SAVE_UPDATE; - } - } else if (grailsProperty.isManyToMany()) { - if ((referenced != null && referenced.isOwningClass(domainClass.getClazz())) || grailsProperty.isCircular()) { - cascadeStrategy = CASCADE_SAVE_UPDATE; - } - } else if (grailsProperty.isManyToOne()) { - if (referenced != null && referenced.isOwningClass(domainClass.getClazz()) && !isCircularAssociation(grailsProperty)) { - cascadeStrategy = CASCADE_ALL; - } - else { - cascadeStrategy = CASCADE_NONE; - } - } - } - else if (grailsProperty.isBasicCollectionType()) { - cascadeStrategy = CASCADE_ALL; - } - else if (Map.class.isAssignableFrom(grailsProperty.getType())) { - referenced = grailsProperty.getReferencedDomainClass(); - if (referenced != null && referenced.isOwningClass(grailsProperty.getDomainClass().getClazz())) { - cascadeStrategy = CASCADE_ALL; - } else { - cascadeStrategy = CASCADE_SAVE_UPDATE; - } - } - logCascadeMapping(grailsProperty, cascadeStrategy, referenced); - prop.setCascade(cascadeStrategy); - } - - protected boolean isCircularAssociation(GrailsDomainClassProperty grailsProperty) { - return grailsProperty.getType().equals(grailsProperty.getDomainClass().getClazz()); - } - - protected void logCascadeMapping(GrailsDomainClassProperty grailsProperty, String cascadeStrategy, GrailsDomainClass referenced) { - if (LOG.isDebugEnabled() && grailsProperty.isAssociation() && referenced != null) { - String assType = getAssociationDescription(grailsProperty); - LOG.debug("Mapping cascade strategy for " + assType + " property " + grailsProperty.getDomainClass().getFullName() + "." + grailsProperty.getName() + " referencing type [" + referenced.getClazz() + "] -> [CASCADE: " + cascadeStrategy + "]"); - } - } - - protected String getAssociationDescription(GrailsDomainClassProperty grailsProperty) { - String assType = "unknown"; - if (grailsProperty.isManyToMany()) { - assType = "many-to-many"; - } else if (grailsProperty.isOneToMany()) { - assType = "one-to-many"; - } else if (grailsProperty.isOneToOne()) { - assType = "one-to-one"; - } else if (grailsProperty.isManyToOne()) { - assType = "many-to-one"; - } else if (grailsProperty.isEmbedded()) { - assType = "embedded"; - } - return assType; - } - - /** - * Binds a simple value to the Hibernate metamodel. A simple value is - * any type within the Hibernate type system - * - * @param property - * @param parentProperty - * @param simpleValue The simple value to bind - * @param path - * @param mappings The Hibernate mappings instance - * @param sessionFactoryBeanName the session factory bean name - */ - protected void bindSimpleValue(GrailsDomainClassProperty property, GrailsDomainClassProperty parentProperty, - SimpleValue simpleValue, String path, Mappings mappings, String sessionFactoryBeanName) { - // set type - bindSimpleValue(property,parentProperty, simpleValue, path, getPropertyConfig(property), sessionFactoryBeanName); - } - - protected void bindSimpleValue(GrailsDomainClassProperty grailsProp, SimpleValue simpleValue, - String path, PropertyConfig propertyConfig, String sessionFactoryBeanName) { - bindSimpleValue(grailsProp, null, simpleValue, path, propertyConfig, sessionFactoryBeanName); - } - - protected void bindSimpleValue(GrailsDomainClassProperty grailsProp, - GrailsDomainClassProperty parentProperty, SimpleValue simpleValue, - String path, PropertyConfig propertyConfig, String sessionFactoryBeanName) { - setTypeForPropertyConfig(grailsProp, simpleValue, propertyConfig); - if (grailsProp.isDerived()) { - Formula formula = new Formula(); - formula.setFormula(propertyConfig.getFormula()); - simpleValue.addFormula(formula); - } else { - Table table = simpleValue.getTable(); - - // Add the column definitions for this value/property. Note that - // not all custom mapped properties will have column definitions, - // in which case we still need to create a Hibernate column for - // this value. - List columnDefinitions = propertyConfig != null ? propertyConfig.getColumns() - : Arrays.asList(new Object[] { null }); - if (columnDefinitions.isEmpty()) { - columnDefinitions = Arrays.asList(new Object[] { null }); - } - - for (int i = 0, n = columnDefinitions.size(); i < n; i++) { - ColumnConfig cc = (ColumnConfig) columnDefinitions.get(i); - Column column = new Column(); - - // Check for explicitly mapped column name and SQL type. - if (cc != null) { - if (cc.getName() != null) { - column.setName(cc.getName()); - } - if (cc.getSqlType() != null) { - column.setSqlType(cc.getSqlType()); - } - } - - column.setValue(simpleValue); - bindColumn(grailsProp, parentProperty, column, cc, path, table, sessionFactoryBeanName); - - if (cc != null) { - if (cc.getLength() != -1) { - column.setLength(cc.getLength()); - } - if (cc.getPrecision() != -1) { - column.setPrecision(cc.getPrecision()); - } - if (cc.getScale() != -1) { - column.setScale(cc.getScale()); - } - column.setUnique(cc.isUnique()); - } - - if (table != null) { - table.addColumn(column); - } - - simpleValue.addColumn(column); - } - } - } - - protected void setTypeForPropertyConfig(GrailsDomainClassProperty grailsProp, SimpleValue simpleValue, PropertyConfig config) { - final String typeName = getTypeName(grailsProp, getPropertyConfig(grailsProp), getMapping(grailsProp.getDomainClass())); - if (typeName == null) { - simpleValue.setTypeName(grailsProp.getType().getName()); - } - else { - simpleValue.setTypeName(typeName); - if (config != null) { - simpleValue.setTypeParameters(config.getTypeParams()); - } - } - } - - /** - * Binds a value for the specified parameters to the meta model. - * - * @param type The type of the property - * @param simpleValue The simple value instance - * @param nullable Whether it is nullable - * @param columnName The property name - * @param mappings The mappings - */ - protected void bindSimpleValue(String type, SimpleValue simpleValue, boolean nullable, - String columnName, Mappings mappings) { - - simpleValue.setTypeName(type); - Table t = simpleValue.getTable(); - Column column = new Column(); - column.setNullable(nullable); - column.setValue(simpleValue); - column.setName(columnName); - if (t != null) t.addColumn(column); - - simpleValue.addColumn(column); - } - - /** - * Binds a Column instance to the Hibernate meta model - * - * @param property The Grails domain class property - * @param parentProperty - * @param column The column to bind - * @param path - * @param table The table name - * @param sessionFactoryBeanName the session factory bean name - */ - protected void bindColumn(GrailsDomainClassProperty property, GrailsDomainClassProperty parentProperty, - Column column, ColumnConfig cc, String path, Table table, String sessionFactoryBeanName) { - - if (cc != null) { - column.setComment(cc.getComment()); - column.setDefaultValue(cc.getDefaultValue()); - } - - Class userType = getUserType(property); - String columnName = getColumnNameForPropertyAndPath(property, path, cc, sessionFactoryBeanName); - if ((property.isAssociation() || property.isBasicCollectionType()) && userType == null) { - // Only use conventional naming when the column has not been explicitly mapped. - if (column.getName() == null) { - column.setName(columnName); - } - if (property.isManyToMany()) { - column.setNullable(false); - } - else if (property.isOneToOne() && property.isBidirectional() && !property.isOwningSide()) { - if (property.getOtherSide().isHasOne()) { - column.setNullable(false); - } - else { - column.setNullable(true); - } - } - else if ((property.isManyToOne() || property.isOneToOne()) && property.isCircular()) { - column.setNullable(true); - } - else { - column.setNullable(property.isOptional()); - } - } - else { - column.setName(columnName); - column.setNullable(property.isOptional() || (parentProperty != null && parentProperty.isOptional())); - - // Use the constraints for this property to more accurately define - // the column's length, precision, and scale - ConstrainedProperty constrainedProperty = getConstrainedProperty(property); - if (constrainedProperty != null) { - if (String.class.isAssignableFrom(property.getType()) || byte[].class.isAssignableFrom(property.getType())) { - bindStringColumnConstraints(column, constrainedProperty); - } - - if (Number.class.isAssignableFrom(property.getType())) { - bindNumericColumnConstraints(column, constrainedProperty); - } - } - } - - handleUniqueConstraint(property, column, path, table, columnName, sessionFactoryBeanName); - - bindIndex(columnName, column, cc, table); - - if (!property.getDomainClass().isRoot()) { - Mapping mapping = getMapping(property.getDomainClass()); - if (mapping == null || mapping.getTablePerHierarchy()) { - if (LOG.isDebugEnabled()) - LOG.debug("[GrailsDomainBinder] Sub class property [" + property.getName() + "] for column name ["+column.getName()+"] set to nullable"); - column.setNullable(true); - } else { - column.setNullable(property.isOptional()); - } - } - - if (LOG.isDebugEnabled()) - LOG.debug("[GrailsDomainBinder] bound property [" + property.getName() + "] to column name ["+column.getName()+"] in table ["+table.getName()+"]"); - } - - protected abstract void handleUniqueConstraint(GrailsDomainClassProperty property, Column column, String path, Table table, String columnName, String sessionFactoryBeanName); - - protected void createKeyForProps(GrailsDomainClassProperty grailsProp, String path, Table table, - String columnName, List propertyNames, String sessionFactoryBeanName) { - List keyList = new ArrayList(); - keyList.add(new Column(columnName)); - for (Iterator i = propertyNames.iterator(); i.hasNext();) { - String propertyName = (String) i.next(); - GrailsDomainClassProperty otherProp = grailsProp.getDomainClass().getPropertyByName(propertyName); - String otherColumnName = getColumnNameForPropertyAndPath(otherProp, path, null, sessionFactoryBeanName); - keyList.add(new Column(otherColumnName)); - } - createUniqueKeyForColumns(table, columnName, keyList); - } - - protected void createUniqueKeyForColumns(Table table, String columnName, List keyList) { - Collections.reverse(keyList); - UniqueKey key = table.getOrCreateUniqueKey("unique-" + columnName); - List columns = key.getColumns(); - if (columns.isEmpty()) { - LOG.debug("create unique key for " + table.getName() + " columns = " + keyList); - key.addColumns(keyList.iterator()); - } - } - - protected void bindIndex(String columnName, Column column, ColumnConfig cc, Table table) { - if (cc == null) { - return; - } - - Object indexObj = cc.getIndex(); - String indexDefinition = null; - if (indexObj instanceof Boolean) { - Boolean b = (Boolean) indexObj; - if (b) { - indexDefinition = columnName + "_idx"; - } - } - else if (indexObj != null) { - indexDefinition = indexObj.toString(); - } - if (indexDefinition == null) { - return; - } - - String[] tokens = indexDefinition.split(","); - for (int i = 0; i < tokens.length; i++) { - String index = tokens[i]; - table.getOrCreateIndex(index).addColumn(column); - } - } - - protected String getColumnNameForPropertyAndPath(GrailsDomainClassProperty grailsProp, - String path, ColumnConfig cc, String sessionFactoryBeanName) { - - NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); - - // First try the column config. - String columnName = null; - if (cc == null) { - // No column config given, so try to fetch it from the mapping - GrailsDomainClass domainClass = grailsProp.getDomainClass(); - Mapping m = getMapping(domainClass.getClazz()); - if (m != null) { - PropertyConfig c = m.getPropertyConfig(grailsProp.getName()); - - if (supportsJoinColumnMapping(grailsProp) && hasJoinKeyMapping(c)) { - columnName = c.getJoinTable().getKey().getName(); - } - else if (c != null && c.getColumn() != null) { - columnName = c.getColumn(); - } - } - } - else { - if (supportsJoinColumnMapping(grailsProp)) { - PropertyConfig pc = getPropertyConfig(grailsProp); - if (hasJoinKeyMapping(pc)) { - columnName = pc.getJoinTable().getKey().getName(); - } - else { - columnName = cc.getName(); - } - } - else { - columnName = cc.getName(); - } - } - - if (columnName == null) { - if (isNotEmpty(path)) { - columnName = addUnderscore(namingStrategy.propertyToColumnName(path), - getDefaultColumnName(grailsProp, sessionFactoryBeanName)); - } else { - columnName = getDefaultColumnName(grailsProp, sessionFactoryBeanName); - } - } - return columnName; - } - - protected boolean hasJoinKeyMapping(PropertyConfig c) { - return c != null && c.getJoinTable() != null && c.getJoinTable().getKey() != null; - } - - protected boolean supportsJoinColumnMapping(GrailsDomainClassProperty grailsProp) { - return grailsProp.isManyToMany() || isUnidirectionalOneToMany(grailsProp) || grailsProp.isBasicCollectionType(); - } - - protected String getDefaultColumnName(GrailsDomainClassProperty property, String sessionFactoryBeanName) { - - NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); - - String columnName = namingStrategy.propertyToColumnName(property.getName()); - if (property.isAssociation() && property.getReferencedDomainClass() != null) { - - if (property.isManyToMany()) { - return getForeignKeyForPropertyDomainClass(property, sessionFactoryBeanName); - } - - if (!property.isBidirectional() && property.isOneToMany()) { - String prefix = namingStrategy.classToTableName(property.getDomainClass().getName()); - return addUnderscore(prefix, columnName) + FOREIGN_KEY_SUFFIX; - } - - if (property.isInherited() && isBidirectionalManyToOne(property)) { - return namingStrategy.propertyToColumnName(property.getDomainClass().getName()) + '_'+ columnName + FOREIGN_KEY_SUFFIX; - } - - return columnName + FOREIGN_KEY_SUFFIX; - } - - if (property.isBasicCollectionType()) { - return getForeignKeyForPropertyDomainClass(property, sessionFactoryBeanName); - } - - return columnName; - } - - protected String getForeignKeyForPropertyDomainClass(GrailsDomainClassProperty property, - String sessionFactoryBeanName) { - final String propertyName = property.getDomainClass().getPropertyName(); - NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); - return namingStrategy.propertyToColumnName(propertyName) + FOREIGN_KEY_SUFFIX; - } - - protected String getIndexColumnName(GrailsDomainClassProperty property, String sessionFactoryBeanName) { - PropertyConfig pc = getPropertyConfig(property); - if (pc != null && pc.getIndexColumn() != null && pc.getIndexColumn().getColumn() != null) { - return pc.getIndexColumn().getColumn(); - } - NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); - return namingStrategy.propertyToColumnName(property.getName()) + UNDERSCORE + IndexedCollection.DEFAULT_INDEX_COLUMN_NAME; - } - - protected String getIndexColumnType(GrailsDomainClassProperty property, String defaultType) { - PropertyConfig pc = getPropertyConfig(property); - if (pc != null && pc.getIndexColumn() != null && pc.getIndexColumn().getType() != null) { - return getTypeName(property, pc.getIndexColumn(), getMapping(property.getDomainClass())); - } - return defaultType; - } - - protected String getMapElementName(GrailsDomainClassProperty property, String sessionFactoryBeanName) { - PropertyConfig pc = getPropertyConfig(property); - - if (hasJoinTableColumnNameMapping(pc)) { - return pc.getJoinTable().getColumn().getName(); - } - - NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); - return namingStrategy.propertyToColumnName(property.getName()) + UNDERSCORE + IndexedCollection.DEFAULT_ELEMENT_COLUMN_NAME; - } - - protected boolean hasJoinTableColumnNameMapping(PropertyConfig pc) { - return pc != null && pc.getJoinTable() != null && pc.getJoinTable().getColumn() != null && pc.getJoinTable().getColumn().getName() != null; - } - - /** - * Returns the constraints applied to the specified domain class property. - * - * @param grailsProp the property whose constraints will be returned - * @return the ConstrainedProperty object representing the property's constraints - */ - protected ConstrainedProperty getConstrainedProperty(GrailsDomainClassProperty grailsProp) { - ConstrainedProperty constrainedProperty = null; - Map constraints = grailsProp.getDomainClass().getConstrainedProperties(); - for (Iterator constrainedPropertyIter = constraints.values().iterator(); constrainedPropertyIter.hasNext() && (constrainedProperty == null);) { - ConstrainedProperty tmpConstrainedProperty = (ConstrainedProperty) constrainedPropertyIter.next(); - if (tmpConstrainedProperty.getPropertyName().equals(grailsProp.getName())) { - constrainedProperty = tmpConstrainedProperty; - } - } - return constrainedProperty; - } - - /** - * Interrogates the specified constraints looking for any constraints that would limit the - * length of the property's value. If such constraints exist, this method adjusts the length - * of the column accordingly. - * - * @param column the column that corresponds to the property - * @param constrainedProperty the property's constraints - */ - protected void bindStringColumnConstraints(Column column, ConstrainedProperty constrainedProperty) { - Integer columnLength = constrainedProperty.getMaxSize(); - List inListValues = constrainedProperty.getInList(); - if (columnLength != null) { - column.setLength(columnLength.intValue()); - } else if (inListValues != null) { - column.setLength(getMaxSize(inListValues)); - } - } - - /** - * Interrogates the specified constraints looking for any constraints that would limit the - * precision and/or scale of the property's value. If such constraints exist, this method adjusts - * the precision and/or scale of the column accordingly. - * - * @param column the column that corresponds to the property - * @param constrainedProperty the property's constraints - */ - protected void bindNumericColumnConstraints(Column column, ConstrainedProperty constrainedProperty) { - int scale = Column.DEFAULT_SCALE; - int precision = Column.DEFAULT_PRECISION; - - if (constrainedProperty.getScale() != null) { - scale = constrainedProperty.getScale().intValue(); - column.setScale(scale); - } - - Comparable minConstraintValue = constrainedProperty.getMin(); - Comparable maxConstraintValue = constrainedProperty.getMax(); - - int minConstraintValueLength = 0; - if ((minConstraintValue != null) && (minConstraintValue instanceof Number)) { - minConstraintValueLength = Math.max( - countDigits((Number) minConstraintValue), - countDigits(((Number) minConstraintValue).longValue()) + scale); - } - int maxConstraintValueLength = 0; - if ((maxConstraintValue != null) && (maxConstraintValue instanceof Number)) { - maxConstraintValueLength = Math.max( - countDigits((Number) maxConstraintValue), - countDigits(((Number) maxConstraintValue).longValue()) + scale); - } - - if (minConstraintValueLength > 0 && maxConstraintValueLength > 0) { - // If both of min and max constraints are setted we could use - // maximum digits number in it as precision - precision = NumberUtils.max(new int[]{minConstraintValueLength, maxConstraintValueLength}); - } else { - // Overwise we should also use default precision - precision = NumberUtils.max(new int[]{precision, minConstraintValueLength, maxConstraintValueLength}); - } - - column.setPrecision(precision); - } - - /** - * @return a count of the digits in the specified number - */ - protected int countDigits(Number number) { - int numDigits = 0; - - if (number != null) { - // Remove everything that's not a digit (e.g., decimal points or signs) - String digitsOnly = number.toString().replaceAll("\\D", EMPTY_PATH); - numDigits = digitsOnly.length(); - } - - return numDigits; - } - - /** - * @return the maximum length of the strings in the specified list - */ - protected int getMaxSize(List inListValues) { - int maxSize = 0; - - for (Iterator iter = inListValues.iterator(); iter.hasNext();) { - String value = (String) iter.next(); - maxSize = Math.max(value.length(), maxSize); - } - - return maxSize; - } - - protected abstract String qualify(String prefix, String name); - - protected abstract String unqualify(String qualifiedName); - - protected abstract boolean isNotEmpty(String s); - - protected abstract Class getGroovyAwareSingleTableEntityPersisterClass(); - - protected abstract Class getGroovyAwareJoinedSubclassEntityPersisterClass(); - - protected abstract void handleLazyProxy(GrailsDomainClass domainClass, GrailsDomainClassProperty grailsProperty); - - protected abstract boolean identityEnumTypeSupports(Class propertyType); -} - -/** - * A Collection type, for the moment only Set is supported - * - * @author Graeme - */ -abstract class CollectionType { - - protected Class clazz; - protected AbstractGrailsDomainBinder binder; - - protected static CollectionType SET; - protected static CollectionType LIST; - protected static CollectionType BAG; - protected static CollectionType MAP; - protected static boolean initialized; - - protected static final Map, CollectionType> INSTANCES = new HashMap, CollectionType>(); - - public abstract Collection create(GrailsDomainClassProperty property, PersistentClass owner, - String path, Mappings mappings, String sessionFactoryBeanName) throws MappingException; - - protected CollectionType(Class clazz, AbstractGrailsDomainBinder binder) { - this.clazz = clazz; - this.binder = binder; - } - - @Override - public String toString() { - return clazz.getName(); - } - - protected void createInstances() { - - if (initialized) { - return; - } - - initialized = true; - - SET = new CollectionType(Set.class, binder) { - @Override - public Collection create(GrailsDomainClassProperty property, PersistentClass owner, - String path, Mappings mappings, String sessionFactoryBeanName) throws MappingException { - org.hibernate.mapping.Set coll = new org.hibernate.mapping.Set(mappings, owner); - coll.setCollectionTable(owner.getTable()); - binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); - return coll; - } - }; - INSTANCES.put(Set.class, SET); - INSTANCES.put(SortedSet.class, SET); - - LIST = new CollectionType(List.class, binder) { - @Override - public Collection create(GrailsDomainClassProperty property, PersistentClass owner, - String path, Mappings mappings, String sessionFactoryBeanName) throws MappingException { - org.hibernate.mapping.List coll = new org.hibernate.mapping.List(mappings, owner); - coll.setCollectionTable(owner.getTable()); - binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); - return coll; - } - }; - INSTANCES.put(List.class, LIST); - - BAG = new CollectionType(java.util.Collection.class, binder) { - @Override - public Collection create(GrailsDomainClassProperty property, PersistentClass owner, - String path, Mappings mappings, String sessionFactoryBeanName) throws MappingException { - Bag coll = new Bag(mappings, owner); - coll.setCollectionTable(owner.getTable()); - binder.bindCollection(property, coll, owner, mappings, path, sessionFactoryBeanName); - return coll; - } - }; - INSTANCES.put(java.util.Collection.class, BAG); - - MAP = new CollectionType(Map.class, binder) { - @Override - public Collection create(GrailsDomainClassProperty property, PersistentClass owner, - String path, Mappings mappings, String sessionFactoryBeanName) throws MappingException { - org.hibernate.mapping.Map map = new org.hibernate.mapping.Map(mappings, owner); - binder.bindCollection(property, map, owner, mappings, path, sessionFactoryBeanName); - return map; - } - }; - INSTANCES.put(Map.class, MAP); - } - - public CollectionType collectionTypeForClass(Class clazz) { - createInstances(); - return INSTANCES.get(clazz); - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/CacheConfig.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/CacheConfig.groovy deleted file mode 100644 index 646dbd2f3..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/CacheConfig.groovy +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2003-2007 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.cfg - -/** - * Defines the cache configuration. - * - * @author Graeme Rocher - * @since 1.0 - */ -class CacheConfig { - static final List USAGE_OPTIONS = ['read-only', 'read-write','nonstrict-read-write','transactional'] - static final List INCLUDE_OPTIONS = ['all', 'non-lazy'] - - String usage = "read-write" - boolean enabled = false - String include = "all" -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/ColumnConfig.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/ColumnConfig.groovy deleted file mode 100644 index 7923ca4b4..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/ColumnConfig.groovy +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2003-2007 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.cfg - -/** - * Defines a column within the mapping. - * - * @author Graeme Rocher - * @since 1.0 - */ -class ColumnConfig { - String name - String sqlType - String enumType = 'default' - def index - boolean unique = false - int length = -1 - int precision = -1 - int scale = -1 - String defaultValue - String comment - - String toString() { - "column[name:$name, index:$index, unique:$unique, length:$length, precision:$precision, scale:$scale]" - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/CompositeIdentity.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/CompositeIdentity.groovy deleted file mode 100644 index c9faad24a..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/CompositeIdentity.groovy +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2003-2007 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.cfg - -/** - * Represents a composite identity, equivalent to Hibernate mapping. - * - * @author Graeme Rocher - * @since 1.0 - */ -class CompositeIdentity { - String[] propertyNames - Class compositeClass -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GORMEnhancingBeanPostProcessor.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GORMEnhancingBeanPostProcessor.groovy deleted file mode 100644 index 67f809907..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GORMEnhancingBeanPostProcessor.groovy +++ /dev/null @@ -1,76 +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.cfg - -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin -import org.codehaus.groovy.grails.plugins.support.BeanPostProcessorAdapter -import org.hibernate.EntityMode -import org.hibernate.SessionFactory -import org.hibernate.metadata.ClassMetadata -import org.springframework.beans.BeanInstantiationException -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware - -/** - * Enhances an existing SessionFactory with GORM behavior. - * - * @author Graeme Rocher - * @since 1.1 - */ -class GORMEnhancingBeanPostProcessor extends BeanPostProcessorAdapter implements ApplicationContextAware { - - ApplicationContext applicationContext - - private static Class sessionFactoryBeanClass - static { - sessionFactoryBeanClass = Class.forName( - "org.codehaus.groovy.grails.orm.hibernate.ConfigurableLocalSessionFactoryBean", - true, Thread.currentThread().contextClassLoader) - } - - Object postProcessAfterInitialization(bean, String beanName) { - if (bean instanceof SessionFactory) { - GrailsApplication application - if (applicationContext.containsBean(GrailsApplication.APPLICATION_ID)) { - application = applicationContext.getBean(GrailsApplication.APPLICATION_ID) - } - else { - application = new DefaultGrailsApplication() - application.initialise() - } - - bean.allClassMetadata.each { className, ClassMetadata metadata -> - Class mappedClass = metadata.getMappedClass(EntityMode.POJO) - - if (!application.getDomainClass(mappedClass.name)) { - application.addDomainClass(mappedClass) - } - } - - try { - DomainClassGrailsPlugin.enhanceDomainClasses(application, applicationContext) - HibernateUtilities.enhanceSessionFactory(bean, application, applicationContext) - } - catch (Throwable e) { - throw new BeanInstantiationException(sessionFactoryBeanClass, - "Error configuring GORM dynamic behavior: $e.message", e) - } - } - return bean - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GORMNamespaceHandler.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GORMNamespaceHandler.java deleted file mode 100644 index fc672cc26..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GORMNamespaceHandler.java +++ /dev/null @@ -1,33 +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.cfg; - -import groovy.lang.ExpandoMetaClass; - -import org.springframework.beans.factory.xml.NamespaceHandlerSupport; - -/** - * A Spring namespace handler for the namespace tags - * - * @author Graeme Rocher - * @since 1.1 - */ -public class GORMNamespaceHandler extends NamespaceHandlerSupport { - - public void init() { - ExpandoMetaClass.enableGlobally(); - registerBeanDefinitionParser("sessionFactory", new GORMSessionFactoryDefinitionParser()); - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GORMSessionFactoryDefinitionParser.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GORMSessionFactoryDefinitionParser.java deleted file mode 100644 index 7310ddf8f..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GORMSessionFactoryDefinitionParser.java +++ /dev/null @@ -1,253 +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.cfg; - -import grails.persistence.Entity; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -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.orm.hibernate.support.SpringLobHandlerDetectorFactoryBean; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConstructorArgumentValues; -import org.springframework.beans.factory.config.MethodInvokingFactoryBean; -import org.springframework.beans.factory.config.RuntimeBeanReference; -import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; -import org.springframework.beans.factory.parsing.Location; -import org.springframework.beans.factory.parsing.Problem; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.GenericBeanDefinition; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry; -import org.springframework.beans.factory.xml.BeanDefinitionParser; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.beans.factory.xml.XmlReaderContext; -import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; -import org.springframework.core.type.filter.AnnotationTypeFilter; -import org.springframework.util.StringUtils; -import org.w3c.dom.Element; - -/** - * A BeanDefinitionParser that will scan for GORM entities to configure and automatically setup an - * appropriate Hibernate SessionFactory for usage with GORM. Example in XML: - * - *

    - * <gorm:sessionFactory
    - *          data-source-ref="myDataSource"
    - *          base-package="my.company.domain"
    - *          lob-handler-ref="lobHandler" <!--optional-->
    - *          config-location="classpath:hibernate.cfg.xml" <!--optional-->
    - *          config-class="org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration"> <!--optional-->
    - *
    - *      <property name="hibernateProperties"></property>
    - * </gorm:sessionFactory>
    - *
    - * 
    - *
    - * @see org.springframework.beans.factory.xml.BeanDefinitionParser
    - *
    - * @author Graeme Rocher
    - * @since 1.1
    - */
    -public class GORMSessionFactoryDefinitionParser implements BeanDefinitionParser {
    -
    -    private static final String ID_ATTRIBUTE = "id";
    -    private static final String DATA_SOURCE_ATTRIBUTE = "data-source-ref";
    -    private static final String MESSAGE_SOURCE_ATTRIBUTE = "message-source-ref";
    -    private static final String LOB_HANDLER_ATTRIBUTE = "lob-handler-ref";
    -    private static final String BASE_PACKAGE_ATTRIBUTE = "base-package";
    -    private static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager-ref";
    -    private static final String CONFIG_CLASS_ATTRIBUTE = "config-class";
    -    private static final String CONFIG_LOCATION_ATTRIBUTE = "config-location";
    -
    -    public BeanDefinition parse(Element element, ParserContext parserContext) {
    -
    -        final XmlReaderContext readerContext = parserContext.getReaderContext();
    -        final ClassLoader beanClassLoader = readerContext.getBeanClassLoader() != null ?
    -                readerContext.getBeanClassLoader() :
    -                Thread.currentThread().getContextClassLoader();
    -
    -        String[] basePackages = StringUtils.commaDelimitedListToStringArray(
    -                element.getAttribute(BASE_PACKAGE_ATTRIBUTE));
    -
    -        String dataSourceId = element.getAttribute(DATA_SOURCE_ATTRIBUTE);
    -        if (!StringUtils.hasText(dataSourceId)) {
    -            throw new BeanDefinitionParsingException(new Problem("Attribute [" + DATA_SOURCE_ATTRIBUTE +
    -                    "] of tag  must be specified!", new Location(readerContext.getResource())));
    -        }
    -
    -        // Actually scan for bean definitions and register them.
    -        BeanDefinitionRegistry targetRegistry = parserContext.getRegistry();
    -
    -        // setup the GrailsApplication instance
    -        parseGrailsApplication(element,parserContext, readerContext, beanClassLoader, basePackages);
    -
    -        GenericBeanDefinition postProccessingBeanDef = new GenericBeanDefinition();
    -        postProccessingBeanDef.setBeanClass(GORMEnhancingBeanPostProcessor.class);
    -
    -        targetRegistry.registerBeanDefinition("gormEnhancingPostProcessor", postProccessingBeanDef);
    -
    -        return parseSessionFactory(element, dataSourceId, targetRegistry, parserContext);
    -    }
    -
    -    private void parseGrailsApplication(Element element, ParserContext parserContext,
    -            XmlReaderContext readerContext, ClassLoader beanClassLoader, String[] basePackages) {
    -
    -        BeanDefinitionRegistry simpleRegistry = new SimpleBeanDefinitionRegistry();
    -        ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, simpleRegistry);
    -
    -        scanner.scan(basePackages);
    -
    -        BeanDefinitionRegistry targetRegistry = parserContext.getRegistry();
    -        AbstractBeanDefinition grailsApplicationBean = new GenericBeanDefinition();
    -        grailsApplicationBean.setBeanClass(DefaultGrailsApplication.class);
    -        grailsApplicationBean.setInitMethodName("initialise");
    -        ConstructorArgumentValues constructorArgs = grailsApplicationBean.getConstructorArgumentValues();
    -
    -        Set> classes = new HashSet>();
    -        for (String beanName : simpleRegistry.getBeanDefinitionNames()) {
    -            BeanDefinition beanDef = simpleRegistry.getBeanDefinition(beanName);
    -            try {
    -                Class entityClass = Class.forName(beanDef.getBeanClassName(), true, beanClassLoader);
    -                classes.add(entityClass);
    -                registerDomainBean(entityClass, targetRegistry, element.getAttribute(MESSAGE_SOURCE_ATTRIBUTE));
    -            }
    -            catch (ClassNotFoundException e) {
    -                throw new BeanDefinitionParsingException(new Problem(
    -                        "Unable to load class whilst configuring GORM: " + e.getMessage(),
    -                        new Location(readerContext.getResource()), null, e));
    -            }
    -        }
    -
    -        constructorArgs.addGenericArgumentValue(classes.toArray(new Class[classes.size()]));
    -        constructorArgs.addGenericArgumentValue(beanClassLoader);
    -        targetRegistry.registerBeanDefinition(GrailsApplication.APPLICATION_ID, grailsApplicationBean);
    -    }
    -
    -    private void registerDomainBean(final Class entityClass, BeanDefinitionRegistry targetRegistry, String messageSourceRef) {
    -        GenericBeanDefinition beanDef = new GenericBeanDefinition();
    -        beanDef.setBeanClass(entityClass);
    -        beanDef.setScope("prototype");
    -
    -        RootBeanDefinition domainDef = new RootBeanDefinition(MethodInvokingFactoryBean.class);
    -
    -        domainDef.getPropertyValues().addPropertyValue("targetObject", new RuntimeBeanReference(GrailsApplication.APPLICATION_ID));
    -        domainDef.getPropertyValues().addPropertyValue("targetMethod", "getArtefact");
    -        domainDef.getPropertyValues().addPropertyValue("arguments", Arrays.asList(
    -            DomainClassArtefactHandler.TYPE,
    -            entityClass.getName()));
    -
    -        final String domainRef = entityClass.getName() + "Domain";
    -        if (StringUtils.hasText(messageSourceRef)) {
    -            GenericBeanDefinition validatorDef = new GenericBeanDefinition();
    -            validatorDef.setBeanClassName("org.codehaus.groovy.grails.orm.hibernate.validation.HibernateDomainClassValidator");
    -            validatorDef.getPropertyValues().addPropertyValue("messageSource", new RuntimeBeanReference(messageSourceRef));
    -            validatorDef.getPropertyValues().addPropertyValue("domainClass", new RuntimeBeanReference(domainRef));
    -            validatorDef.getPropertyValues().addPropertyValue("sessionFactory", new RuntimeBeanReference("sessionFactory"));
    -            targetRegistry.registerBeanDefinition(entityClass.getName() + "Validator", validatorDef);
    -        }
    -
    -        targetRegistry.registerBeanDefinition(entityClass.getName(), beanDef);
    -        targetRegistry.registerBeanDefinition(domainRef, domainDef);
    -    }
    -
    -    private AbstractBeanDefinition parseSessionFactory(Element element, String dataSourceId,
    -              BeanDefinitionRegistry targetRegistry, ParserContext parserContext) {
    -        String sessionFactoryId = StringUtils.hasText(element.getAttribute(ID_ATTRIBUTE)) ?
    -                element.getAttribute(ID_ATTRIBUTE) : "sessionFactory";
    -        AbstractBeanDefinition sessionFactoryBean = new GenericBeanDefinition();
    -        sessionFactoryBean.setBeanClassName("org.codehaus.groovy.grails.orm.hibernate.ConfigurableLocalSessionFactoryBean");
    -
    -        MutablePropertyValues propertyValues = sessionFactoryBean.getPropertyValues();
    -        final RuntimeBeanReference dataSourceRef = new RuntimeBeanReference(dataSourceId);
    -        propertyValues.addPropertyValue("dataSource", dataSourceRef);
    -
    -        Class configClass = lookupConfigClass(element, parserContext);
    -        propertyValues.addPropertyValue("configClass", configClass);
    -
    -        final String configLocation = element.getAttribute(CONFIG_LOCATION_ATTRIBUTE);
    -        if (StringUtils.hasText(configLocation)) {
    -            propertyValues.addPropertyValue("configLocation", configLocation);
    -        }
    -
    -        propertyValues.addPropertyValue(GrailsApplication.APPLICATION_ID,
    -                new RuntimeBeanReference(GrailsApplication.APPLICATION_ID));
    -
    -        targetRegistry.registerBeanDefinition(sessionFactoryId,sessionFactoryBean);
    -
    -        final String lobHandlerRef = element.getAttribute(LOB_HANDLER_ATTRIBUTE);
    -        if (StringUtils.hasText(lobHandlerRef)) {
    -            propertyValues.addPropertyValue("lobHandler", new RuntimeBeanReference(lobHandlerRef));
    -        }
    -        else {
    -            GenericBeanDefinition lobHandler = new GenericBeanDefinition();
    -            lobHandler.setBeanClass(SpringLobHandlerDetectorFactoryBean.class);
    -            lobHandler.getPropertyValues().addPropertyValue("pooledConnection", true);
    -            lobHandler.getPropertyValues().addPropertyValue("dataSource", dataSourceRef);
    -            propertyValues.addPropertyValue("lobHandler", lobHandler);
    -        }
    -
    -        String transactionManagerRef = element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE);
    -        if (StringUtils.hasText(transactionManagerRef)) {
    -            targetRegistry.registerAlias(transactionManagerRef, "transactionManager");
    -        }
    -        else {
    -            GenericBeanDefinition transactionManagerBean = new GenericBeanDefinition();
    -            transactionManagerBean.setBeanClassName("org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTransactionManager");
    -            transactionManagerBean.getPropertyValues().addPropertyValue("sessionFactory", new RuntimeBeanReference(sessionFactoryId));
    -
    -            targetRegistry.registerBeanDefinition("transactionManager", transactionManagerBean);
    -        }
    -
    -        parserContext.getDelegate().parsePropertyElements(element, sessionFactoryBean);
    -        return sessionFactoryBean;
    -    }
    -
    -    private Class lookupConfigClass(Element element, ParserContext parserContext)  {
    -        final ClassLoader classLoader = parserContext.getReaderContext().getBeanClassLoader();
    -        final String configClassName = element.getAttribute(CONFIG_CLASS_ATTRIBUTE);
    -        try {
    -            if (StringUtils.hasText(configClassName)) {
    -                return classLoader.loadClass(configClassName);
    -            }
    -            return classLoader.loadClass("org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration");
    -        }
    -        catch (ClassNotFoundException e) {
    -            throw new BeanDefinitionParsingException(new Problem(
    -                    "Unable to load specified SessionFactory configClass implementation: " + e.getMessage(),
    -                    new Location(parserContext.getReaderContext().getResource()),null, e));
    -        }
    -    }
    -
    -    private ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, BeanDefinitionRegistry registry) {
    -        XmlReaderContext readerContext = parserContext.getReaderContext();
    -        // Delegate bean definition registration to scanner class.
    -        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false);
    -        scanner.setIncludeAnnotationConfig(false);
    -        scanner.addIncludeFilter(new AnnotationTypeFilter(Entity.class));
    -
    -        scanner.setResourceLoader(readerContext.getResourceLoader());
    -        scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
    -        scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
    -
    -        return scanner;
    -    }
    -}
    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
    deleted file mode 100644
    index c8d8ecd11..000000000
    --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainConfiguration.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.cfg;
    -
    -import org.codehaus.groovy.grails.commons.GrailsApplication;
    -import org.codehaus.groovy.grails.commons.GrailsDomainClass;
    -
    -/**
    - * @author Graeme Rocher
    - */
    -public interface GrailsDomainConfiguration {
    -
    -    /**
    -     * Adds a domain class to the configuration.
    -     * @param domainClass
    -     * @return this
    -     */
    -    GrailsDomainConfiguration addDomainClass(GrailsDomainClass domainClass);
    -
    -    /**
    -     * Sets the grails application instance.
    -     * @param application The grails application to use or null if none.
    -     */
    -    void setGrailsApplication(GrailsApplication application);
    -
    -    /**
    -     * The Spring bean name of the SessionFactory.
    -     * @param name the name
    -     */
    -    void setSessionFactoryBeanName(String name);
    -
    -    /**
    -     * The Spring bean name of the DataSource.
    -     * @param name the name
    -     */
    -    void setDataSourceName(String name);
    -}
    diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateMappingBuilder.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateMappingBuilder.groovy
    deleted file mode 100644
    index e2fe3f0c4..000000000
    --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateMappingBuilder.groovy
    +++ /dev/null
    @@ -1,607 +0,0 @@
    -/*
    - * Copyright 2003-2007 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.cfg
    -
    -import org.apache.commons.beanutils.BeanUtils
    -import org.hibernate.FetchMode
    -import org.hibernate.InvalidMappingException
    -import org.slf4j.Logger
    -import org.slf4j.LoggerFactory
    -import org.springframework.context.ApplicationContext
    -
    -/**
    - * Implements the ORM mapping DSL constructing a model that can be evaluated by the
    - * GrailsDomainBinder class which maps GORM classes onto the database.
    - *
    - * @author Graeme Rocher
    - * @since 1.0
    - */
    -class HibernateMappingBuilder {
    -
    -    static final Logger LOG = LoggerFactory.getLogger(this)
    -
    -    Mapping mapping
    -    String className
    -
    -    /**
    -     * Constructor for builder
    -     *
    -     * @param className The name of the class being mapped
    -     */
    -    HibernateMappingBuilder(String className) {
    -        this.className = className
    -    }
    -
    -    /**
    -     * Central entry point for the class. Passing a closure that defines a set of mappings will evaluate said mappings
    -     * and populate the "mapping" property of this class which can then be obtained with getMappings()
    -     *
    -     * @param mappingClosure The closure that defines the ORM DSL
    -     */
    -    Mapping evaluate(Closure mappingClosure, ApplicationContext applicationContext = null) {
    -        if (mapping == null) {
    -            mapping = new Mapping()
    -        }
    -        mappingClosure.resolveStrategy = Closure.DELEGATE_ONLY
    -        mappingClosure.delegate = this
    -        try {
    -            mappingClosure.call(applicationContext)
    -        }
    -        finally {
    -            mappingClosure.delegate = null
    -        }
    -        mapping
    -    }
    -
    -    /**
    -     * Include another config in this one
    -     */
    -    void includes(Closure callable) {
    -        if (!callable) {
    -            return
    -        }
    -
    -        callable.resolveStrategy = Closure.DELEGATE_ONLY
    -        callable.delegate = this
    -        try {
    -            callable.call()
    -        }
    -        finally {
    -            callable.delegate = null
    -        }
    -    }
    -
    -    void hibernateCustomUserType(Map args) {
    -        if (args.type && (args['class'] instanceof Class)) {
    -            mapping.userTypes[args['class']] = args.type
    -        }
    -    }
    -
    -    /**
    -     * 

    Configures the table name. Example: - * { table 'foo' } - * - * @param name The name of the table - */ - void table(String name) { - mapping.tableName = name - } - - /** - *

    Configures the discriminator name. Example: - * { discriminator 'foo' } - * - * @param name The name of the table - */ - void discriminator(String name) { - mapping.discriminator = name - } - - /** - *

    Configures the discriminator name. Example: - * { discriminator name:'foo', column:'type' } - * - * @param name The name of the table - */ - void discriminator(Map args) { - mapping.discriminator = args?.remove('value') - if (args.column instanceof String) { - mapping.discriminatorColumn = new ColumnConfig(name:args.column) - } - else if (args.column instanceof Map) { - ColumnConfig config = new ColumnConfig() - BeanUtils.populate config, args.column - mapping.discriminatorColumn = config - } - mapping.discriminatorMap.type = args?.remove('type') - mapping.discriminatorMap.insert = args?.remove('insert') - mapping.discriminatorMap.formula = args?.remove('formula') - } - - /** - *

    Configures whether to auto import packages domain classes in HQL queries. Default is true - * { autoImport false } - */ - void autoImport(boolean b) { - mapping.autoImport = b - } - - /** - *

    Configures the table name. Example: - * { table name:'foo', schema:'dbo', catalog:'CRM' } - */ - void table(Map tableDef) { - mapping.table.name = tableDef?.name?.toString() - mapping.table.schema = tableDef?.schema?.toString() - mapping.table.catalog = tableDef?.catalog?.toString() - } - - /** - *

    Configures the default sort column. Example: - * { sort 'foo' } - * - * @param name The name of the property to sort by - */ - void sort(String name) { - if (name) { - mapping.sort.name = name - } - } - - /** - * Whether to use dynamic update queries - */ - void dynamicUpdate(boolean b) { - mapping.dynamicUpdate = b - } - - /** - * Whether to use dynamic update queries - */ - void dynamicInsert(boolean b) { - mapping.dynamicInsert = b - } - - /** - *

    Configures the default sort column. Example: - * { sort foo:'desc' } - * - * @param namesAndDirections The names and directions of the property to sort by - */ - void sort(Map namesAndDirections) { - if (namesAndDirections) { - mapping.sort.namesAndDirections = namesAndDirections - } - } - - /** - * Configures the batch-size used for lazy loading - * @param num The batch size to use - */ - void batchSize(Integer num) { - if (num) { - mapping.batchSize = num - } - } - - /** - *

    Configures the default sort direction. Example: - * { order 'desc' } - * - * @param name The name of the property to sort by - */ - void order(String direction) { - if ("desc".equalsIgnoreCase(direction) || "asc".equalsIgnoreCase(direction)) { - mapping.sort.direction = direction - } - } - - /** - * Set whether auto time stamping should occur for last_updated and date_created columns - */ - void autoTimestamp(boolean b) { - mapping.autoTimestamp = b - } - - /** - *

    Configures whether to use versioning for optimistic locking - * { version false } - * - * @param isVersioned True if a version property should be configured - */ - void version(boolean isVersioned) { - mapping.versioned = isVersioned - } - - /** - *

    Configures the name of the version column - * { version 'foo' } - * - * @param isVersioned True if a version property should be configured - */ - void version(String versionColumn) { - PropertyConfig pc = mapping.getPropertyConfig("version") - if (!pc) { - pc = new PropertyConfig() - mapping.columns['version'] = pc - } - pc.columns << new ColumnConfig(name:versionColumn) - } - - /** - *

    Configures the second-level cache for the class - * { cache usage:'read-only', include:'all' } - * - * @param args Named arguments that contain the "usage" and/or "include" parameters - */ - void cache(Map args) { - mapping.cache = new CacheConfig(enabled:true) - if (args.usage) { - if (CacheConfig.USAGE_OPTIONS.contains(args.usage)) { - mapping.cache.usage = args.usage - } - else { - LOG.warn("ORM Mapping Invalid: Specified [usage] with value [$args.usage] of [cache] in class [$className] is not valid") - } - } - if (args.include) { - if (CacheConfig.INCLUDE_OPTIONS.contains(args.include)) { - mapping.cache.include = args.include - } - else { - LOG.warn("ORM Mapping Invalid: Specified [include] with value [$args.include] of [cache] in class [$className] is not valid") - } - } - } - - /** - *

    Configures the second-level cache for the class - * { cache 'read-only' } - * - * @param usage The usage type for the cache which is one of CacheConfig.USAGE_OPTIONS - */ - void cache(String usage) { - cache(usage:usage) - } - - /** - *

    Configures the second-level cache for the class - * { cache 'read-only', include:'all } - * - * @param usage The usage type for the cache which is one of CacheConfig.USAGE_OPTIONS - */ - void cache(String usage, Map args) { - args = args ? args : [:] - args.usage = usage - cache(args) - } - - /** - * If true the class and its sub classes will be mapped with table per hierarchy mapping - */ - void tablePerHierarchy(boolean isTablePerHierarchy) { - mapping.tablePerHierarchy = isTablePerHierarchy - } - - /** - * If true the class and its subclasses will be mapped with table per subclass mapping - */ - void tablePerSubclass(boolean isTablePerSubClass) { - mapping.tablePerHierarchy = !isTablePerSubClass - } - - /** - * If true the class and its subclasses will be mapped with table per subclass mapping - */ - void tablePerConcreteClass(boolean isTablePerConcreteClass) { - mapping.tablePerHierarchy = false - mapping.tablePerConcreteClass = true - } - - - /** - *

    Configures the second-level cache with the default usage of 'read-write' and the default include of 'all' if - * the passed argument is true - * - * { cache true } - * - * @param shouldCache True if the default cache configuration should be applied - */ - void cache(boolean shouldCache) { - mapping.cache = new CacheConfig(enabled:shouldCache) - } - - /** - *

    Configures the identity strategy for the mapping. Examples - * - * - * { id generator:'sequence' } - * { id composite: ['one', 'two'] } - * - * - * @param args The named arguments to the id method - */ - void id(Map args) { - if (args.composite) { - mapping.identity = new CompositeIdentity(propertyNames:args.composite as String[]) - if (args.compositeClass) { - mapping.identity.compositeClass = args.compositeClass - } - } - else { - if (args?.generator) { - mapping.identity.generator = args.remove('generator') - } - if (args?.name) { - mapping.identity.name = args.remove('name').toString() - } - if (args?.params) { - def params = args.remove('params') - for (entry in params) { - params[entry.key] = entry.value?.toString() - } - mapping.identity.params = params - } - if (args?.natural) { - def naturalArgs = args.remove('natural') - def propertyNames = naturalArgs instanceof Map ? naturalArgs.remove('properties') : naturalArgs - - if (propertyNames) { - def ni = new NaturalId() - ni.mutable = (naturalArgs instanceof Map) && naturalArgs.mutable ?: false - if (propertyNames instanceof List) { - ni.propertyNames = propertyNames - } - else { - ni.propertyNames = [propertyNames.toString()] - } - mapping.identity.natural = ni - } - } - // still more arguments? - if (args) { - handleMethodMissing("id", [args] as Object[]) - } - } - } - - /** - * A closure used by methodMissing to create column definitions - */ - private handleMethodMissing = { String name, args -> - if (args && ((args[0] instanceof Map) || (args[0] instanceof Closure))) { - def namedArgs = args[0] instanceof Map ? args[0] : [:] - PropertyConfig property = mapping.columns[name] ?: new PropertyConfig() - property.formula = namedArgs.formula - property.type = namedArgs.type ?: property.type - property.lazy = namedArgs.lazy != null ? namedArgs.lazy : property.lazy - property.insertable = namedArgs.insertable != null ? namedArgs.insertable : property.insertable - property.updateable = namedArgs.updateable != null ? namedArgs.updateable : property.updateable - property.cascade = namedArgs.cascade ?: property.cascade - property.sort = namedArgs.sort ?: property.sort - property.order = namedArgs.order ?: property.order - property.batchSize = namedArgs.batchSize instanceof Integer ? namedArgs.batchSize : property.batchSize - property.ignoreNotFound = namedArgs.ignoreNotFound != null ? namedArgs.ignoreNotFound : property.ignoreNotFound - property.typeParams = namedArgs.params ?: property.typeParams - if (namedArgs.fetch) { - switch(namedArgs.fetch) { - case ~/(join|JOIN)/: - property.fetch = FetchMode.JOIN; break - case ~/(select|SELECT)/: - property.fetch = FetchMode.SELECT; break - default: - property.fetch = FetchMode.DEFAULT - } - } - - // Deal with any column configuration for this property. - if (args[-1] instanceof Closure) { - // Multiple column definitions for this property. - Closure c = args[-1] - c.delegate = new PropertyDefinitionDelegate(property) - c.resolveStrategy = Closure.DELEGATE_ONLY - c.call() - } - else { - // There is no sub-closure containing multiple column - // definitions, so pick up any column settings from - // the argument map. - def cc - if (property.columns) { - cc = property.columns[0] - } - else { - cc = new ColumnConfig() - property.columns << cc - } - - if (namedArgs["column"]) cc.name = namedArgs["column"] - if (namedArgs["sqlType"]) cc.sqlType = namedArgs["sqlType"] - if (namedArgs["enumType"]) cc.enumType = namedArgs["enumType"] - if (namedArgs["index"]) cc.index = namedArgs["index"] - if (namedArgs["unique"]) cc.unique = namedArgs["unique"] - if (namedArgs.defaultValue) cc.defaultValue = namedArgs.defaultValue - if (namedArgs.comment) cc.comment = namedArgs.comment - cc.length = namedArgs["length"] ?: -1 - cc.precision = namedArgs["precision"] ?: -1 - cc.scale = namedArgs["scale"] ?: -1 - } - - if (namedArgs.cache instanceof String) { - CacheConfig cc = new CacheConfig() - if (CacheConfig.USAGE_OPTIONS.contains(namedArgs.cache)) { - cc.usage = namedArgs.cache - } - else { - LOG.warn("ORM Mapping Invalid: Specified [usage] of [cache] with value [$args.usage] for association [$name] in class [$className] is not valid") - } - property.cache = cc - } - else if (namedArgs.cache == true) { - property.cache = new CacheConfig() - } - else if (namedArgs.cache instanceof Map) { - def cacheArgs = namedArgs.cache - CacheConfig cc = new CacheConfig() - if (CacheConfig.USAGE_OPTIONS.contains(cacheArgs.usage)) { - cc.usage = cacheArgs.usage - } - else { - LOG.warn("ORM Mapping Invalid: Specified [usage] of [cache] with value [$args.usage] for association [$name] in class [$className] is not valid") - } - if (CacheConfig.INCLUDE_OPTIONS.contains(cacheArgs.include)) { - cc.include = cacheArgs.include - } - else { - LOG.warn("ORM Mapping Invalid: Specified [include] of [cache] with value [$args.include] for association [$name] in class [$className] is not valid") - } - property.cache = cc - } - - if (namedArgs.indexColumn) { - def pc = new PropertyConfig() - property.indexColumn = pc - def cc = new ColumnConfig() - pc.columns << cc - def indexColArg = namedArgs.indexColumn - if (indexColArg instanceof Map) { - if (indexColArg.type) { - pc.type = indexColArg.remove('type') - } - bindArgumentsToColumnConfig(indexColArg, cc) - } - else { - cc.name = indexColArg.toString() - } - } - if (namedArgs.joinTable) { - def join = new JoinTable() - def joinArgs = namedArgs.joinTable - if (joinArgs instanceof String) { - join.name = joinArgs - } - else if (joinArgs instanceof Map) { - if (joinArgs.schema) join.schema = joinArgs.remove('schema') - if (joinArgs.catalog) join.catalog = joinArgs.remove('catalog') - if (joinArgs.name) join.name = joinArgs.remove('name') - if (joinArgs.key) { - join.key = new ColumnConfig(name:joinArgs.remove('key')) - } - if (joinArgs.column) { - ColumnConfig cc = new ColumnConfig(name: joinArgs.column) - join.column = cc - bindArgumentsToColumnConfig(joinArgs, cc) - } - } - property.joinTable = join - } - else if (namedArgs.containsKey('joinTable') && namedArgs.joinTable == false) { - property.joinTable = null - } - - mapping.columns[name] = property - } - } - - private bindArgumentsToColumnConfig(argMap, ColumnConfig cc) { - argMap.each { k, v -> - if (cc.metaClass.hasProperty(cc, k)) { - try { - cc."$k" = v - } - catch (Exception e) { - LOG.warn("Parameter [$k] cannot be used with [joinTable] argument") - } - } - } - } - - /** - *

    Consumes the columns closure and populates the value into the Mapping objects columns property - * - * @param callable The closure containing the column definitions - */ - void columns(Closure callable) { - callable.resolveStrategy = Closure.DELEGATE_ONLY - callable.delegate = new Object() { - def invokeMethod(String methodName, args) { - handleMethodMissing(methodName, args) - } - } - callable.call() - } - - void datasource(String name) { - mapping.datasources = [name] - } - - void datasources(List names) { - mapping.datasources = names - } - - void comment(String comment) { - mapping.comment = comment - } - - void methodMissing(String name, args) { - if ('user-type' == name && args && (args[0] instanceof Map)) { - hibernateCustomUserType(args[0]) - } - else if (args && ((args[0] instanceof Map) || (args[0] instanceof Closure))) { - handleMethodMissing(name, args) - } - else { - LOG.error "ORM Mapping Invalid: Specified config option [$name] does not exist for class [$className]!" - } - } -} - -/** - * Builder delegate that handles multiple-column definitions for a - * single domain property, e.g. - *

    - *   amount type: MonetaryAmountUserType, {
    - *       column name: "value"
    - *       column name: "currency_code", sqlType: "text"
    - *   }
    - * 
    - */ -class PropertyDefinitionDelegate { - PropertyConfig config - - PropertyDefinitionDelegate(PropertyConfig config) { - this.config = config - } - - def column(Map args) { - // Check that this column has a name - if (!args["name"]) throw new InvalidMappingException("Column definition must have a name!") - - // Create a new column configuration based on the mapping for this column. - def column = new ColumnConfig() - column.name = args["name"] - column.sqlType = args["sqlType"] - column.enumType = args["enumType"] - column.index = args["index"] - column.unique = args["unique"] ?: false - column.length = args["length"] ?: -1 - column.precision = args["precision"] ?: -1 - column.scale = args["scale"] ?: -1 - - // Append the new column configuration to the property config. - config.columns << column - } -} 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 deleted file mode 100644 index 2bcddd378..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateNamedQueriesBuilder.groovy +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright 2003-2009 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.cfg - -import grails.util.GrailsNameUtils - -import java.lang.reflect.Modifier - -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.grails.datastore.gorm.finders.FinderMethod -import org.hibernate.criterion.CriteriaSpecification -import org.springframework.core.convert.ConversionService - -/** - * A builder that implements the ORM named queries DSL. - * - * @author Jeff Brown - */ -class HibernateNamedQueriesBuilder { - - protected final domainClass - protected final dynamicMethods - protected boolean initialized = false - protected final ConversionService conversionService - - /** - * @param domainClass the GrailsDomainClass defining the named queries - * @param finders dynamic finders - */ - HibernateNamedQueriesBuilder(domainClass, List finders, ConversionService conversionService) { - this.domainClass = domainClass - this.conversionService = conversionService - dynamicMethods = finders - } - - def evaluate(Closure namedQueriesClosure) { - def closure = namedQueriesClosure.clone() - closure.resolveStrategy = Closure.DELEGATE_ONLY - closure.delegate = this - closure.call() - initialized = true - } - - protected handleMethodMissing = {String name, args -> - def classesToAugment = [domainClass] - - def subClasses = domainClass.subClasses - if (subClasses) { - classesToAugment += subClasses - } - - def getterName = GrailsNameUtils.getGetterName(name) - classesToAugment.each { clz -> - clz.metaClass.static."${getterName}" = {-> - // creating a new proxy each time because the proxy class has - // some state that cannot be shared across requests (namedCriteriaParams) - new NamedCriteriaProxy(criteriaClosure: args[0], domainClass: clz, dynamicMethods: dynamicMethods, conversionService: conversionService) - } - } - } - - def methodMissing(String name, args) { - if (args && args[0] instanceof Closure && !initialized) { - return handleMethodMissing(name, args) - } - throw new MissingMethodException(name, HibernateNamedQueriesBuilder, args) - } -} - -class NamedCriteriaProxy { - - protected criteriaClosure - protected GrailsDomainClass domainClass - protected dynamicMethods - protected namedCriteriaParams - protected previousInChain - protected queryBuilder - protected inCountMethod = false - protected conversionService - protected Class HibernateUtils - - NamedCriteriaProxy() { - HibernateUtils = Class.forName("org.codehaus.groovy.grails.orm.hibernate.cfg.HibernateUtils", - true, Thread.currentThread().contextClassLoader) - } - - protected invokeCriteriaClosure(additionalCriteriaClosure = null) { - def crit = getPreparedCriteriaClosure(additionalCriteriaClosure) - crit() - } - - void propertyMissing(String propName, val) { - queryBuilder?."${propName}" = val - } - - protected listInternal(Object[] params, Closure additionalCriteriaClosure, Boolean isDistinct) { - def listClosure = { - queryBuilder = delegate - invokeCriteriaClosure(additionalCriteriaClosure) - if (isDistinct) { - resultTransformer = CriteriaSpecification.DISTINCT_ROOT_ENTITY - } - } - - def paramsMap - if (params && params[-1] instanceof Map) { - paramsMap = params[-1] - } - - if (paramsMap) { - domainClass.clazz.createCriteria().list(paramsMap, listClosure) - } else { - domainClass.clazz.withCriteria(listClosure) - } - } - - def list(Object[] params, Closure additionalCriteriaClosure = null) { - listInternal params, additionalCriteriaClosure, false - } - - def listDistinct(Object[] params, Closure additionalCriteriaClosure = null) { - listInternal params, additionalCriteriaClosure, true - } - - def call(Object[] params) { - if (params && params[-1] instanceof Closure) { - def additionalCriteriaClosure = params[-1] - params = params.length > 1 ? params[0..-2] : [:] - if (params) { - if (params[-1] instanceof Map) { - if (params.length > 1) { - namedCriteriaParams = params[0..-2] as Object[] - } - } else { - namedCriteriaParams = params - } - } - list(params, additionalCriteriaClosure) - } - else { - namedCriteriaParams = params - this - } - } - - T get() { - def getClosure = { - queryBuilder = delegate - invokeCriteriaClosure() - maxResults 1 - uniqueResult = true - } - domainClass.clazz.withCriteria(getClosure) - } - - T get(id) { - id = HibernateUtils.convertValueToIdentifierType(domainClass, id, conversionService) - def getClosure = { - queryBuilder = delegate - invokeCriteriaClosure() - eq 'id', id - uniqueResult = true - } - domainClass.clazz.withCriteria(getClosure) - } - - int count(Closure additionalCriteriaClosure = null) { - def countClosure = { - inCountMethod = true - queryBuilder = delegate - invokeCriteriaClosure(additionalCriteriaClosure) - uniqueResult = true - projections { - rowCount() - } - inCountMethod = false - } - domainClass.clazz.withCriteria(countClosure) - } - - def findWhere(params) { - findAllWhere(params, true) - } - - void order(String propName) { - if (!inCountMethod) { - queryBuilder?.order propName - } - } - - void order(String propName, String direction) { - if (!inCountMethod) { - queryBuilder?.order propName, direction - } - } - - def findAllWhere(Map params, Boolean uniq = false) { - def queryClosure = { - queryBuilder = delegate - invokeCriteriaClosure() - params.each {key, val -> - eq key, val - } - if (uniq) { - maxResults 1 - uniqueResult = true - } - } - domainClass.clazz.withCriteria(queryClosure) - } - - def propertyMissing(String propertyName) { - if (domainClass.metaClass.getMetaProperty(propertyName)) { - def nextInChain = domainClass.metaClass.getMetaProperty(propertyName).getProperty(domainClass) - nextInChain.previousInChain = this - return nextInChain - } - throw new MissingPropertyException(propertyName, NamedCriteriaProxy) - } - - def methodMissing(String methodName, args) { - - def method = dynamicMethods.find {it.isMethodMatch(methodName)} - - if (method) { - def preparedClosure = getPreparedCriteriaClosure() - def c = { - queryBuilder = delegate - preparedClosure() - } - return method.invoke(domainClass.clazz, methodName, c, args) - } - - if (!queryBuilder && domainClass.metaClass.getMetaProperty(methodName)) { - def nextInChain = domainClass.metaClass.getMetaProperty(methodName).getProperty(domainClass) - nextInChain.previousInChain = this - return nextInChain(args) - } - - def proxy = getNamedCriteriaProxy(domainClass, methodName) - if (proxy) { - def nestedCriteria = proxy.criteriaClosure.clone() - nestedCriteria.delegate = this - return nestedCriteria(*args) - } - try { - def returnValue = queryBuilder."${methodName}"(*args) - return returnValue - } catch (MissingMethodException mme) { - def targetType = queryBuilder?.targetClass - proxy = getNamedCriteriaProxy(targetType, methodName) - if (proxy) { - def nestedCriteria = proxy.criteriaClosure.clone() - nestedCriteria.delegate = this - return nestedCriteria(*args) - } - throw mme - } - } - - protected getNamedCriteriaProxy(targetClass, name) { - def proxy = null - def metaProperty = targetClass.metaClass.getMetaProperty(name) - if (metaProperty && Modifier.isStatic(metaProperty.modifiers)) { - def prop = metaProperty.getProperty(targetClass) - if (prop instanceof NamedCriteriaProxy) { - proxy = prop - } - } - proxy - } - - protected getPreparedCriteriaClosure(additionalCriteriaClosure = null) { - def closureClone = criteriaClosure.clone() - closureClone.resolveStrategy = Closure.DELEGATE_FIRST - if (namedCriteriaParams) { - closureClone = closureClone.curry(*namedCriteriaParams) - } - def c = { - closureClone.delegate = delegate - if (previousInChain) { - def previousClosure = previousInChain.getPreparedCriteriaClosure() - previousClosure.delegate = delegate - previousClosure() - } - closureClone() - if (additionalCriteriaClosure) { - additionalCriteriaClosure = additionalCriteriaClosure.clone() - additionalCriteriaClosure.delegate = delegate - additionalCriteriaClosure() - } - } - c - } -} 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 deleted file mode 100644 index 2f0933ec2..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtilities.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.codehaus.groovy.grails.orm.hibernate.cfg; - -import java.util.List; - -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.orm.hibernate.AbstractGrailsHibernateDomainClass; - -public class HibernateUtilities { - - public static boolean usesDatasource(GrailsDomainClass domainClass, String dataSourceName, AbstractGrailsDomainBinder binder) { - if (domainClass instanceof AbstractGrailsHibernateDomainClass) { - AbstractGrailsHibernateDomainClass hibernateDomainClass = (AbstractGrailsHibernateDomainClass)domainClass; - String sessionFactoryName = hibernateDomainClass.getSessionFactoryName(); - if (dataSourceName.equals(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE)) { - return "sessionFactory".equals(sessionFactoryName); - } - return sessionFactoryName.endsWith("_" + dataSourceName); - } - - List names = getDatasourceNames(domainClass, binder); - return names.contains(dataSourceName) || - names.contains(GrailsDomainClassProperty.ALL_DATA_SOURCES); - } - - public static List getDatasourceNames(GrailsDomainClass domainClass, AbstractGrailsDomainBinder binder) { - // Mappings won't have been built yet when this is called from - // HibernatePluginSupport.doWithSpring so do a temporary evaluation but don't cache it - Mapping mapping = isMappedWithHibernate(domainClass) ? binder.evaluateMapping(domainClass, null, false) : null; - if (mapping == null) { - mapping = new Mapping(); - } - return mapping.getDatasources(); - } - - public static boolean isMappedWithHibernate(GrailsDomainClass domainClass) { - return domainClass instanceof AbstractGrailsHibernateDomainClass || domainClass.getMappingStrategy().equals(GrailsDomainClass.GORM); - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/Identity.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/Identity.groovy deleted file mode 100644 index 5f644e4cf..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/Identity.groovy +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2003-2007 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.cfg - -/** - * Defines the identity generation strategy. In the case of a 'composite' identity the properties - * array defines the property names that formulate the composite id. - * - * @author Graeme Rocher - * @since 1.0 - */ -class Identity { - String generator = 'native' - String column = 'id' - String name - NaturalId natural - Class type = Long - Map params = [:] - - String toString() { "id[generator:$generator, column:$column, type:$type]" } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/InstanceProxy.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/InstanceProxy.groovy deleted file mode 100644 index 6b0e5aa4d..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/InstanceProxy.groovy +++ /dev/null @@ -1,68 +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.cfg - -import groovy.transform.CompileStatic - -import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateGormInstanceApi -import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateGormValidationApi - -@CompileStatic -class InstanceProxy { - protected instance - protected AbstractHibernateGormValidationApi validateApi - protected AbstractHibernateGormInstanceApi instanceApi - - protected final Set validateMethods - - InstanceProxy(instance, AbstractHibernateGormInstanceApi instanceApi, AbstractHibernateGormValidationApi validateApi) { - this.instance = instance - this.instanceApi = instanceApi - this.validateApi = validateApi - validateMethods = validateApi.methods*.name as Set - validateMethods.remove 'getValidator' - validateMethods.remove 'setValidator' - validateMethods.remove 'getBeforeValidateHelper' - validateMethods.remove 'setBeforeValidateHelper' - validateMethods.remove 'getValidateMethod' - validateMethods.remove 'setValidateMethod' - } - - def invokeMethod(String name, args) { - if (validateMethods.contains(name)) { - validateApi.invokeMethod(name, [instance, *args] as Object[]) - } - else { - instanceApi.invokeMethod(name, [instance, *args] as Object[]) - } - } - - void setProperty(String name, val) { - instanceApi.setProperty(name, val) - } - - def getProperty(String name) { - instanceApi.getProperty(name) - } - - void putAt(String name, val) { - instanceApi.setProperty(name, val) - } - - def getAt(String name) { - instanceApi.getProperty(name) - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/JoinTable.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/JoinTable.groovy deleted file mode 100644 index 831ea43fa..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/JoinTable.groovy +++ /dev/null @@ -1,31 +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.cfg - -/** - * Represents a Join table in Grails mapping. It has a name which represents the name of the table, a key - * for the primary key and a column which is the other side of the join. - * - * @author Graeme Rocher - * @since 1.0 - */ -class JoinTable { - String catalog - String schema - String name - ColumnConfig key - ColumnConfig column -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/Mapping.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/Mapping.groovy deleted file mode 100644 index a1e15c149..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/Mapping.groovy +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2003-2007 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.cfg - -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty - -/** - * Models the mapping from GORM classes to the db. - * - * @author Graeme Rocher - * @since 1.0 - */ -class Mapping { - - /** - * Custom hibernate user types - */ - Map userTypes = [:] - - /** - * Return a type name of the known custom user types - */ - String getTypeName(Class theClass) { - def type = userTypes[theClass] - if (type == null) { - return null - } - - return type instanceof Class ? type.name : type.toString() - } - - /** - * The table - */ - Table table = new Table() - - /** - * The table name - */ - String getTableName() { table?.name } - - /** - * Set the table name - */ - void setTableName(String name) { table?.name = name } - - /** - * Whether the class is versioned for optimistic locking - */ - boolean versioned = true - - /** - * Sets whether to use table-per-hierarchy or table-per-subclass mapping - */ - boolean tablePerHierarchy = true - - /** - * Sets whether to use table-per-concrete-class or table-per-subclass mapping - */ - boolean tablePerConcreteClass = false - - /** - * Sets whether automatic timestamping should occur for columns like last_updated and date_created - */ - boolean autoTimestamp = true - - /** - * Sets whether packaged domain classes should be auto-imported in HQL queries - */ - boolean autoImport = true - - Map columns = [:] - - /** - * The identity definition - */ - def identity = new Identity() - - /** - * Caching config - */ - CacheConfig cache - - /** - * Used to hold the names and directions of the default property to sort by - */ - SortConfig sort = new SortConfig() - - /** - * Value used to discriminate entities in table-per-hierarchy inheritance mapping - */ - String discriminator - - /** - * Used to hold the attributes for Discriminator, such as formula, type and insertable - */ - Map discriminatorMap = [:] - - /** - * Used to configure the disriminator column properties - */ - ColumnConfig discriminatorColumn - - /** - * Obtains a PropertyConfig object for the given name - */ - PropertyConfig getPropertyConfig(String name) { columns[name] } - - /** - * The name of the column used for the version number - */ - String versionColumn - - /** - * The batch size to use for lazy loading - */ - Integer batchSize - - /** - * Whether to use dynamically created update queries, at the cost of some performance - */ - boolean dynamicUpdate = false - - /** - * Whether to use dynamically created insert queries, at the cost of some performance - */ - boolean dynamicInsert = false - - /** - * Get the datasource names that this domain class works with. - * @return the datasource names - */ - List datasources = [GrailsDomainClassProperty.DEFAULT_DATA_SOURCE] - - /** - * DDL comment. - */ - String comment - - boolean isTablePerConcreteClass() { - return tablePerConcreteClass - } - - void setTablePerConcreteClass(boolean tablePerConcreteClass) { - this.tablePerHierarchy = !tablePerConcreteClass - this.tablePerConcreteClass = tablePerConcreteClass - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/NaturalId.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/NaturalId.groovy deleted file mode 100644 index dc33781d8..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/NaturalId.groovy +++ /dev/null @@ -1,25 +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.cfg - -/** - * @author Graeme Rocher - * @since 1.1 - */ -class NaturalId { - List propertyNames = [] - boolean mutable = false -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/PropertyConfig.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/PropertyConfig.groovy deleted file mode 100644 index 6a194159e..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/PropertyConfig.groovy +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2003-2007 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.cfg - -import org.hibernate.FetchMode - -/** - * Custom mapping for a single domain property. Note that a property - * can have multiple columns via a component or a user type. - * - * @since 1.0.4 - * @author pledbrook - */ -class PropertyConfig { - - /** - * The Hibernate type or user type of the property. This can be - * a string or a class. - */ - def type - - /** - * The parameters for the property that can be used to - * configure a Hibernate ParameterizedType implementation. - */ - Properties typeParams - - /** - * The default sort property name - */ - String sort - - String formula - - /** - * The default sort order - */ - String order - - /** - * The batch size used for lazy loading - */ - Integer batchSize - - /** - * Cascading strategy for this property. Only makes sense if the - * property is an association or collection. - */ - String cascade - /** - * The fetch strategy for this property. - */ - FetchMode fetch = FetchMode.DEFAULT - - /** - * Whether to ignore ObjectNotFoundException - */ - boolean ignoreNotFound = false - - /** - * Whether or not this is column is insertable by hibernate - */ - boolean insertable = true - - /** - * Whether or not this column is updateable by hibernate - */ - boolean updateable = true - - List columns = [] - - boolean lazy = true - CacheConfig cache - JoinTable joinTable = new JoinTable() - - /** - * The column used to produce the index for index based collections (lists and maps) - */ - PropertyConfig indexColumn - - /** - * Shortcut to get the column name for this property. - * @throws RuntimeException if this property maps to more than one - * column. - */ - String getColumn() { - checkHasSingleColumn() - return columns[0].name - } - - String getEnumType() { - checkHasSingleColumn() - return columns[0].enumType - } - - /** - * Shortcut to get the SQL type of the corresponding column. - * @throws RuntimeException if this property maps to more than one - * column. - */ - String getSqlType() { - checkHasSingleColumn() - return columns[0].sqlType - } - - /** - * Shortcut to get the index setting for this property's column. - * @throws RuntimeException if this property maps to more than one - * column. - */ - String getIndex() { - checkHasSingleColumn() - return columns[0].index?.toString() - } - - /** - * Shortcut to determine whether the property's column is configured - * to be unique. - * @throws RuntimeException if this property maps to more than one - * column. - */ - boolean isUnique() { - checkHasSingleColumn() - return columns[0].unique - } - - /** - * Shortcut to get the length of this property's column. - * @throws RuntimeException if this property maps to more than one - * column. - */ - int getLength() { - checkHasSingleColumn() - return columns[0].length - } - - /** - * Shortcut to get the precision of this property's column. - * @throws RuntimeException if this property maps to more than one - * column. - */ - int getPrecision() { - checkHasSingleColumn() - return columns[0].precision - } - - /** - * Shortcut to get the scale of this property's column. - * @throws RuntimeException if this property maps to more than one - * column. - */ - int getScale() { - checkHasSingleColumn() - return columns[0].scale - } - - String toString() { - "property[type:$type, lazy:$lazy, columns:$columns, insertable:${insertable}, updateable:${updateable}]" - } - - protected void checkHasSingleColumn() { - if (columns?.size() > 1) { - throw new RuntimeException("Cannot treat multi-column property as a single-column property") - } - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/SortConfig.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/SortConfig.groovy deleted file mode 100644 index e1c1931b0..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/SortConfig.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package org.codehaus.groovy.grails.orm.hibernate.cfg - -class SortConfig { - String name - String direction - Map namesAndDirections - - Map getNamesAndDirections() { - if (namesAndDirections) { - return namesAndDirections - } - if (name) { - return [(name): direction] - } - Collections.emptyMap() - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/Table.groovy b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/Table.groovy deleted file mode 100644 index d13ec60e0..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/Table.groovy +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2003-2007 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.cfg - -/** - * Represents a table definition in GORM. - * - * @author Graeme Rocher - * @since 1.1 - */ -class Table { - String name - String catalog - String schema -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/CouldNotDetermineHibernateDialectException.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/CouldNotDetermineHibernateDialectException.java deleted file mode 100644 index b26af4920..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/CouldNotDetermineHibernateDialectException.java +++ /dev/null @@ -1,42 +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.exceptions; - -/** - * Thrown when no Hibernate dialect could be found for a database name. - * - * @author Steven Devijver - */ -public class CouldNotDetermineHibernateDialectException extends GrailsHibernateException { - - private static final long serialVersionUID = -3385252525996110909L; - - public CouldNotDetermineHibernateDialectException() { - super(); - } - - public CouldNotDetermineHibernateDialectException(String message) { - super(message); - } - - public CouldNotDetermineHibernateDialectException(String message, Throwable cause) { - super(message, cause); - } - - public CouldNotDetermineHibernateDialectException(Throwable cause) { - super(cause); - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsHibernateConfigurationException.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsHibernateConfigurationException.java deleted file mode 100644 index 5e4453599..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsHibernateConfigurationException.java +++ /dev/null @@ -1,42 +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.exceptions; - -/** - * Thrown when configuration Hibernate for GORM features. - * - * @author Graeme Rocher - * @since 1.1 - */ -public class GrailsHibernateConfigurationException extends GrailsHibernateException{ - - private static final long serialVersionUID = 5212907914995954558L; - - public GrailsHibernateConfigurationException() { - super(); - } - - public GrailsHibernateConfigurationException(String message) { - super(message); - } - - public GrailsHibernateConfigurationException(String message, Throwable cause) { - super(message, cause); - } - - public GrailsHibernateConfigurationException(Throwable cause) { - super(cause); - } -} 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 deleted file mode 100644 index 545d273c2..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsHibernateException.java +++ /dev/null @@ -1,44 +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.exceptions; - -import org.codehaus.groovy.grails.exceptions.GrailsException; - -/** - * Base exception class for errors related to Hibernate configuration in Grails. - * - * @author Steven Devijver - */ -public abstract class GrailsHibernateException extends GrailsException { - - private static final long serialVersionUID = -6019220941440364736L; - - public GrailsHibernateException() { - super(); - } - - public GrailsHibernateException(String message) { - super(message); - } - - public GrailsHibernateException(String message, Throwable cause) { - super(message, cause); - } - - public GrailsHibernateException(Throwable cause) { - super(cause); - } -} 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 deleted file mode 100644 index e66724fa4..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/exceptions/GrailsQueryException.java +++ /dev/null @@ -1,44 +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.exceptions; - -import org.codehaus.groovy.grails.exceptions.GrailsException; - -/** - * Base exception class for errors related to Domain class queries in Grails. - * - * @author Graeme Rocher - */ -public class GrailsQueryException extends GrailsException { - - private static final long serialVersionUID = 775603608315415077L; - - public GrailsQueryException() { - super(); - } - - public GrailsQueryException(String message, Throwable cause) { - super(message, cause); - } - - public GrailsQueryException(String message) { - super(message); - } - - public GrailsQueryException(Throwable cause) { - super(cause); - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/AbstractHibernateCriterionAdapter.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/AbstractHibernateCriterionAdapter.java deleted file mode 100644 index 4f8101f5f..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/AbstractHibernateCriterionAdapter.java +++ /dev/null @@ -1,309 +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.codehaus.groovy.grails.orm.hibernate.query; - -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang.ArrayUtils; -import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; -import org.grails.datastore.mapping.model.PersistentEntity; -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.criterion.Criterion; -import org.hibernate.criterion.DetachedCriteria; -import org.hibernate.criterion.Junction; -import org.hibernate.criterion.Property; -import org.hibernate.criterion.Restrictions; -import org.springframework.util.Assert; -import org.springframework.util.ReflectionUtils; - -/** - * @author Graeme Rocher - * @since 2.0 - */ -public abstract class AbstractHibernateCriterionAdapter { - protected static final Map, CriterionAdaptor> criterionAdaptors = new HashMap, CriterionAdaptor>(); - protected String alias; - protected static boolean initialized; - - protected Query.Criterion criterion; - - protected AbstractHibernateCriterionAdapter(Query.Criterion criterion) { - this(null, criterion, null); - } - - protected AbstractHibernateCriterionAdapter(PersistentEntity entity, Query.Criterion criterion, String alias) { - this.criterion = criterion; - this.alias = alias; - initialize(); - } - - protected synchronized void initialize() { - if (initialized) { - return; - } - - //add simple property criterions - addPropertyCriterionAdaptor(Query.Equals.class, "eq"); - addPropertyCriterionAdaptor(Query.NotEquals.class, "ne"); - addPropertyCriterionAdaptor(Query.GreaterThan.class, "gt"); - addPropertyCriterionAdaptor(Query.GreaterThanEquals.class, "ge"); - addPropertyCriterionAdaptor(Query.LessThan.class, "lt"); - addPropertyCriterionAdaptor(Query.LessThanEquals.class, "le"); - - //add simple size criterions - addPropertySizeCriterionAdaptor(Query.SizeEquals.class, "sizeEq"); - addPropertySizeCriterionAdaptor(Query.SizeGreaterThan.class, "sizeGt"); - addPropertySizeCriterionAdaptor(Query.SizeGreaterThanEquals.class, "sizeGe"); - addPropertySizeCriterionAdaptor(Query.SizeLessThan.class, "sizeLt"); - addPropertySizeCriterionAdaptor(Query.SizeLessThanEquals.class, "sizeLe"); - - //add simple criterions - addPropertyNameCriterionAdaptor(Query.IsNull.class, "isNull"); - addPropertyNameCriterionAdaptor(Query.IsNotNull.class, "isNotNull"); - addPropertyNameCriterionAdaptor(Query.IsEmpty.class, "isEmpty"); - addPropertyNameCriterionAdaptor(Query.IsNotEmpty.class, "isNotEmpty"); - - //add simple property comparison criterions - addPropertyComparisonCriterionAdaptor(Query.EqualsProperty.class, "eqProperty"); - addPropertyComparisonCriterionAdaptor(Query.GreaterThanProperty.class, "gtProperty"); - addPropertyComparisonCriterionAdaptor(Query.GreaterThanEqualsProperty.class, "geProperty"); - addPropertyComparisonCriterionAdaptor(Query.LessThanProperty.class, "ltProperty"); - addPropertyComparisonCriterionAdaptor(Query.LessThanEqualsProperty.class, "leProperty"); - addPropertyComparisonCriterionAdaptor(Query.NotEqualsProperty.class, "neProperty"); - - addJunctionCriterionAdaptor(Query.Conjunction.class, "conjunction"); - addJunctionCriterionAdaptor(Query.Disjunction.class, "disjunction"); - - addPropertyLikeCriterionAdaptor(Query.Like.class, "like"); - addPropertyLikeCriterionAdaptor(Query.ILike.class, "ilike"); - - criterionAdaptors.put(DetachedAssociationCriteria.class, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - DetachedAssociationCriteria existing = (DetachedAssociationCriteria) criterion; - String newAlias = hibernateQuery.handleAssociationQuery(existing.getAssociation(), existing.getCriteria()); - if (alias == null) { - alias = newAlias; - } - else { - alias = alias + '.' + newAlias; - } - Junction conjunction = Restrictions.conjunction(); - applySubCriteriaToJunction(existing.getAssociation().getAssociatedEntity(), hibernateQuery, existing.getCriteria(), conjunction, alias); - return conjunction; - } - }); - criterionAdaptors.put(AssociationQuery.class, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - AssociationQuery existing = (AssociationQuery) criterion; - Junction conjunction = Restrictions.conjunction(); - String newAlias = hibernateQuery.handleAssociationQuery(existing.getAssociation(), existing.getCriteria().getCriteria()); - if (alias == null) { - alias = newAlias; - } - else { - alias += '.' + newAlias; - } - applySubCriteriaToJunction(existing.getAssociation().getAssociatedEntity(), hibernateQuery, existing.getCriteria().getCriteria(), conjunction, alias); - return conjunction; - } - }); - criterionAdaptors.put(Query.Negation.class, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - return Restrictions.not(criterionAdaptors.get(Query.Disjunction.class).toHibernateCriterion(hibernateQuery, criterion, alias)); - } - }); - criterionAdaptors.put(Query.Between.class, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - Query.Between btwCriterion = (Query.Between) criterion; - return Restrictions.between(calculatePropertyName(calculatePropertyName(btwCriterion.getProperty(), alias), alias), btwCriterion.getFrom(), btwCriterion.getTo()); - } - }); - criterionAdaptors.put(Query.IdEquals.class, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - return Restrictions.idEq(((Query.IdEquals) criterion).getValue()); - } - }); - criterionAdaptors.put(Query.RLike.class, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - return createRlikeExpression(getPropertyName(criterion, alias), ((Query.RLike) criterion).getPattern()); - } - }); - criterionAdaptors.put(Query.In.class, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - return Restrictions.in(getPropertyName(criterion, alias), ((Query.In) criterion).getValues()); - } - }); - - initialized = true; - } - - /** utility methods to group and clean up the initialization of the Criterion Adapters**/ - - //used for PropertyCriterions with a specified value ( which can be a subquery) - protected void addPropertyCriterionAdaptor(final Class clazz, final String constraintName) { - addCriterionAdaptor(clazz, constraintName, Object.class); - } - - protected abstract Criterion createRlikeExpression(String propertyName, String pattern); - - //used for collection size PropertyCriterions - protected void addPropertySizeCriterionAdaptor(final Class clazz, final String constraintName) { - addCriterionAdaptor(clazz, constraintName, int.class); - } - - protected void addCriterionAdaptor(final Class clazz, final String constraintName, final Class valueClass) { - criterionAdaptors.put(clazz, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - Query.PropertyCriterion propertyCriterion = (Query.PropertyCriterion) criterion; - Object value = propertyCriterion.getValue(); - String propertyName = getPropertyName(criterion, alias); - if (value instanceof DetachedCriteria) { - Method propertyMethod = ReflectionUtils.findMethod(Property.class, constraintName, new Class[]{DetachedCriteria.class}); - if (propertyMethod != null) { // if supports subqueries - return (Criterion) ReflectionUtils.invokeMethod(propertyMethod, Property.forName(propertyName), new Object[]{value}); - } - } - return callRestrictionsMethod(constraintName, new Class[]{String.class, valueClass}, new Object[]{propertyName, value}); - } - }); - } - - // use for criterions without a value - protected void addPropertyNameCriterionAdaptor(final Class clazz, final String constraintName) { - criterionAdaptors.put(clazz, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - return callRestrictionsMethod(constraintName, new Class[]{String.class}, new Object[]{getPropertyName(criterion, alias)}); - } - }); - } - - // use for criterions used to compare 2 properties - protected void addPropertyComparisonCriterionAdaptor(final Class clazz, final String constraintName) { - criterionAdaptors.put(clazz, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - return callRestrictionsMethod(constraintName, new Class[]{String.class, String.class}, new Object[]{getPropertyName(criterion, alias), ((Query.PropertyComparisonCriterion) criterion).getOtherProperty()}); - } - }); - } - - // use for regular expression criterions - protected void addPropertyLikeCriterionAdaptor(final Class clazz, final String constraintName) { - criterionAdaptors.put(clazz, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - return callRestrictionsMethod(constraintName, new Class[]{String.class, Object.class}, new Object[]{getPropertyName(criterion, alias), convertStringValue(((Query.Like) criterion).getValue())}); - } - }); - } - - // used for junctions - protected void addJunctionCriterionAdaptor(final Class clazz, final String constraintName) { - criterionAdaptors.put(clazz, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - Junction junction = (Junction) callRestrictionsMethod(constraintName, new Class[0], new Object[0]); - applySubCriteriaToJunction(hibernateQuery.getEntity(), hibernateQuery, ((Query.Junction) criterion).getCriteria(), junction, alias); - return junction; - } - }); - } - - /** - * utility method that generically returns a criterion using methods in Restrictions - * - * @param constraintName - the criteria - */ - protected Criterion callRestrictionsMethod(String constraintName, Class[] paramTypes, Object[] params) { - final Method restrictionsMethod = ReflectionUtils.findMethod(Restrictions.class, constraintName, paramTypes); - Assert.notNull(restrictionsMethod, "Could not find method: " + constraintName + " in class Restrictions for parameters: " + ArrayUtils.toString(params) + " with types: " + ArrayUtils.toString(paramTypes)); - return (Criterion) ReflectionUtils.invokeMethod(restrictionsMethod, null, params); - } - - protected String getPropertyName(Query.Criterion criterion, String alias) { - return calculatePropertyName(((Query.PropertyNameCriterion) criterion).getProperty(), alias); - } - - protected String calculatePropertyName(String property, String alias) { - if (alias != null) { - return alias + '.' + property; - } - return property; - } - - protected void applySubCriteriaToJunction(PersistentEntity entity, AbstractHibernateQuery hibernateCriteria, List existing, - Junction conjunction, String alias) { - - for (Query.Criterion subCriterion : existing) { - if (subCriterion instanceof Query.PropertyCriterion) { - Query.PropertyCriterion pc = (Query.PropertyCriterion) subCriterion; - if (pc.getValue() instanceof QueryableCriteria) { - pc.setValue(getHibernateDetachedCriteria((QueryableCriteria) pc.getValue())); - } - else { - AbstractHibernateQuery.doTypeConversionIfNeccessary(entity, pc); - } - } - CriterionAdaptor criterionAdaptor = criterionAdaptors.get(subCriterion.getClass()); - if (criterionAdaptor != null) { - Criterion c = criterionAdaptor.toHibernateCriterion(hibernateCriteria, subCriterion, alias); - if (c != null) - conjunction.add(c); - } - else if (subCriterion instanceof FunctionCallingCriterion) { - Criterion sqlRestriction = hibernateCriteria.getRestrictionForFunctionCall((FunctionCallingCriterion) subCriterion, entity); - if (sqlRestriction != null) { - conjunction.add(sqlRestriction); - } - } - } - } - - protected abstract Object getHibernateDetachedCriteria(QueryableCriteria value); - - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery) { - final CriterionAdaptor criterionAdaptor = criterionAdaptors.get(criterion.getClass()); - if (criterionAdaptor != null) { - return criterionAdaptor.toHibernateCriterion(hibernateQuery, criterion, alias); - } - return null; - } - - public static abstract class CriterionAdaptor { - public abstract org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias); - - protected Object convertStringValue(Object o) { - if ((!(o instanceof String)) && (o instanceof CharSequence)) { - o = o.toString(); - } - return o; - } - } -} 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 deleted file mode 100644 index 1c77409ef..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ /dev/null @@ -1,847 +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.codehaus.groovy.grails.orm.hibernate.query; - -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import javax.persistence.FetchType; - -import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateSession; -import org.codehaus.groovy.grails.orm.hibernate.IHibernateTemplate; -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.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.criterion.CriteriaSpecification; -import org.hibernate.criterion.Projections; -import org.hibernate.criterion.Restrictions; -import org.hibernate.criterion.SimpleExpression; -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.function.SQLFunction; -import org.hibernate.persister.entity.PropertyMapping; -import org.hibernate.type.BasicType; -import org.hibernate.type.TypeResolver; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.dao.InvalidDataAccessResourceUsageException; -import org.springframework.util.ReflectionUtils; - -/** - * Bridges the Query API with the Hibernate Criteria API - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractHibernateQuery extends Query { - - public static final String SIZE_CONSTRAINT_PREFIX = "Size"; - - protected static final String ALIAS = "_alias"; - protected static ConversionService conversionService = new DefaultConversionService(); - protected static Field opField = ReflectionUtils.findField(SimpleExpression.class, "op"); - static { - ReflectionUtils.makeAccessible(opField); - } - - protected Criteria criteria; - protected AbstractHibernateQuery.HibernateProjectionList hibernateProjectionList; - protected String alias; - protected int aliasCount; - protected Map createdAssociationPaths = new HashMap(); - protected LinkedList aliasStack = new LinkedList(); - protected LinkedList entityStack = new LinkedList(); - protected LinkedList associationStack = new LinkedList(); - protected LinkedList aliasInstanceStack = new LinkedList(); - - protected AbstractHibernateQuery(Criteria criteria, AbstractHibernateSession session, PersistentEntity entity) { - super(session, entity); - this.criteria = criteria; - } - - protected AbstractHibernateQuery(Criteria subCriteria, AbstractHibernateSession session, PersistentEntity associatedEntity, String newAlias) { - this(subCriteria, session, associatedEntity); - alias = newAlias; - } - - @Override - public Query isEmpty(String property) { - org.hibernate.criterion.Criterion criterion = Restrictions.isEmpty(calculatePropertyName(property)); - addToCriteria(criterion); - return this; - } - - @Override - public Query isNotEmpty(String property) { - addToCriteria(Restrictions.isNotEmpty(calculatePropertyName(property))); - return this; - } - - @Override - public Query isNull(String property) { - addToCriteria(Restrictions.isNull(calculatePropertyName(property))); - return this; - } - - @Override - public Query isNotNull(String property) { - addToCriteria(Restrictions.isNotNull(calculatePropertyName(property))); - return this; - } - - @Override - public void add(Criterion criterion) { - if (criterion instanceof FunctionCallingCriterion) { - org.hibernate.criterion.Criterion sqlRestriction = getRestrictionForFunctionCall((FunctionCallingCriterion) criterion, getEntity()); - if (sqlRestriction != null) { - addToCriteria(sqlRestriction); - } - } - else if (criterion instanceof PropertyCriterion) { - PropertyCriterion pc = (PropertyCriterion) criterion; - Object value = pc.getValue(); - if (value instanceof QueryableCriteria) { - setDetachedCriteriaValue((QueryableCriteria) value, pc); - } - // ignore Size related constraints - else { - doTypeConversionIfNeccessary(getEntity(), pc); - } - } - if (criterion instanceof DetachedAssociationCriteria) { - DetachedAssociationCriteria associationCriteria = (DetachedAssociationCriteria) criterion; - - Association association = associationCriteria.getAssociation(); - - CriteriaAndAlias criteriaAndAlias = getCriteriaAndAlias(association); - - aliasInstanceStack.add(criteriaAndAlias.criteria); - aliasStack.add(criteriaAndAlias.alias); - associationStack.add(association); - entityStack.add(association.getAssociatedEntity()); - - try { - @SuppressWarnings("unchecked") - List associationCriteriaList = associationCriteria.getCriteria(); - for (Criterion c : associationCriteriaList) { - add(c); - } - } - finally { - aliasInstanceStack.removeLast(); - aliasStack.removeLast(); - entityStack.removeLast(); - associationStack.removeLast(); - } - } - else { - - final org.hibernate.criterion.Criterion hibernateCriterion = createHibernateCriterionAdapter( - getEntity(), criterion, getCurrentAlias()).toHibernateCriterion(this); - if (hibernateCriterion != null) { - addToCriteria(hibernateCriterion); - } - } - } - - @Override - public PersistentEntity getEntity() { - if (!entityStack.isEmpty()) { - return entityStack.getLast(); - } - return super.getEntity(); - } - - protected String getAssociationPath(String propertyName) { - StringBuilder fullPath = new StringBuilder(); - for (Iterator iterator = associationStack.iterator(); iterator.hasNext(); ) { - Association association = iterator.next(); - fullPath.append(association.getName()); - fullPath.append('.'); - } - fullPath.append(propertyName); - return fullPath.toString(); - } - - protected String getCurrentAlias() { - if (alias != null) { - return alias; - } - - if (aliasStack.isEmpty()) { - return null; - } - - return aliasStack.getLast(); - } - - @SuppressWarnings("unchecked") - static void doTypeConversionIfNeccessary(PersistentEntity entity, PropertyCriterion pc) { - if (pc.getClass().getSimpleName().startsWith(SIZE_CONSTRAINT_PREFIX)) { - return; - } - - String property = pc.getProperty(); - Object value = pc.getValue(); - PersistentProperty p = entity.getPropertyByName(property); - if (p != null && !p.getType().isInstance(value)) { - pc.setValue(conversionService.convert(value, p.getType())); - } - } - - org.hibernate.criterion.Criterion getRestrictionForFunctionCall(FunctionCallingCriterion criterion, PersistentEntity entity) { - org.hibernate.criterion.Criterion sqlRestriction; - - SessionFactory sessionFactory = ((IHibernateTemplate)session.getNativeInterface()).getSessionFactory(); - String property = criterion.getProperty(); - Criterion datastoreCriterion = criterion.getPropertyCriterion(); - PersistentProperty pp = entity.getPropertyByName(property); - - if (pp == null) throw new InvalidDataAccessResourceUsageException( - "Cannot execute function defined in query [" + criterion.getFunctionName() + - "] on non-existent property [" + property + "] of [" + entity.getJavaClass() + "]"); - - String functionName = criterion.getFunctionName(); - - Dialect dialect = getDialect(sessionFactory); - SQLFunction sqlFunction = dialect.getFunctions().get(functionName); - if (sqlFunction != null) { - TypeResolver typeResolver = getTypeResolver(sessionFactory); - BasicType basic = typeResolver.basic(pp.getType().getName()); - if (basic != null && datastoreCriterion instanceof PropertyCriterion) { - - PropertyCriterion pc = (PropertyCriterion) datastoreCriterion; - final org.hibernate.criterion.Criterion hibernateCriterion = createHibernateCriterionAdapter( - getEntity(),datastoreCriterion, alias).toHibernateCriterion(this); - if (hibernateCriterion instanceof SimpleExpression) { - SimpleExpression expr = (SimpleExpression) hibernateCriterion; - Object op = ReflectionUtils.getField(opField, expr); - PropertyMapping mapping = getEntityPersister(entity.getJavaClass().getName(), sessionFactory); - String[] columns; - if (alias != null) { - columns = mapping.toColumns(alias, property); - } - else { - columns = mapping.toColumns(property); - } - String root = render(basic, Arrays.asList(columns), sessionFactory, sqlFunction); - Object value = pc.getValue(); - if (value != null) { - sqlRestriction = Restrictions.sqlRestriction(root + op + "?", value, typeResolver.basic(value.getClass().getName())); - } - else { - sqlRestriction = Restrictions.sqlRestriction(root + op + "?", value, basic); - } - } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function ["+functionName+"] defined in query for property ["+property+"] with type ["+pp.getType()+"]"); - } - } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function ["+functionName+"] defined in query for property ["+property+"] with type ["+pp.getType()+"]"); - } - } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function defined in query ["+functionName+"]"); - } - return sqlRestriction; - } - - protected abstract String render(BasicType basic, List asList, SessionFactory sessionFactory, SQLFunction sqlFunction); - - protected abstract PropertyMapping getEntityPersister(String name, SessionFactory sessionFactory); - - protected abstract TypeResolver getTypeResolver(SessionFactory sessionFactory); - - protected abstract Dialect getDialect(SessionFactory sessionFactory); - - @Override - public Junction disjunction() { - final org.hibernate.criterion.Disjunction disjunction = Restrictions.disjunction(); - addToCriteria(disjunction); - return new HibernateJunction(disjunction, alias); - } - - @Override - public Junction negation() { - final org.hibernate.criterion.Disjunction disjunction = Restrictions.disjunction(); - addToCriteria(Restrictions.not(disjunction)); - return new HibernateJunction(disjunction, alias); - } - - @Override - public Query eq(String property, Object value) { - addToCriteria(Restrictions.eq(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query idEq(Object value) { - addToCriteria(Restrictions.idEq(value)); - return this; - } - - @Override - public Query gt(String property, Object value) { - addToCriteria(Restrictions.gt(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query and(Criterion a, Criterion b) { - AbstractHibernateCriterionAdapter aa = createHibernateCriterionAdapter(getEntity(), a, alias); - AbstractHibernateCriterionAdapter ab = createHibernateCriterionAdapter(getEntity(), a, alias); - addToCriteria(Restrictions.and(aa.toHibernateCriterion(this), ab.toHibernateCriterion(this))); - return this; - } - - @Override - public Query or(Criterion a, Criterion b) { - AbstractHibernateCriterionAdapter aa = createHibernateCriterionAdapter(getEntity(), a, alias); - AbstractHibernateCriterionAdapter ab = createHibernateCriterionAdapter(getEntity(), a, alias); - addToCriteria(Restrictions.or(aa.toHibernateCriterion(this), ab.toHibernateCriterion(this))); - return this; - } - - @Override - public Query allEq(Map values) { - addToCriteria(Restrictions.allEq(values)); - return this; - } - - @Override - public Query ge(String property, Object value) { - addToCriteria(Restrictions.ge(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query le(String property, Object value) { - addToCriteria(Restrictions.le(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query gte(String property, Object value) { - addToCriteria(Restrictions.ge(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query lte(String property, Object value) { - addToCriteria(Restrictions.le(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query lt(String property, Object value) { - addToCriteria(Restrictions.lt(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query in(String property, List values) { - addToCriteria(Restrictions.in(calculatePropertyName(property), values)); - return this; - } - - @Override - public Query between(String property, Object start, Object end) { - addToCriteria(Restrictions.between(calculatePropertyName(property), start, end)); - return this; - } - - @Override - public Query like(String property, String expr) { - addToCriteria(Restrictions.like(calculatePropertyName(property), calculatePropertyName(expr))); - return this; - } - - @Override - public Query ilike(String property, String expr) { - addToCriteria(Restrictions.ilike(calculatePropertyName(property), calculatePropertyName(expr))); - return this; - } - - @Override - public Query rlike(String property, String expr) { - addToCriteria(createRlikeExpression(calculatePropertyName(property), calculatePropertyName(expr))); - return this; - } - - @Override - public AssociationQuery createQuery(String associationName) { - final PersistentProperty property = entity.getPropertyByName(calculatePropertyName(associationName)); - if (property != null && (property instanceof Association)) { - String alias = generateAlias(associationName); - CriteriaAndAlias subCriteria = getOrCreateAlias(associationName, alias); - - Association association = (Association) property; - return new HibernateAssociationQuery(subCriteria.criteria, (AbstractHibernateSession) getSession(), association.getAssociatedEntity(), association, alias); - } - throw new InvalidDataAccessApiUsageException("Cannot query association [" + calculatePropertyName(associationName) + "] of entity [" + entity + "]. Property is not an association!"); - } - - protected CriteriaAndAlias getOrCreateAlias(String associationName, String alias) { - CriteriaAndAlias subCriteria; - String associationPath = getAssociationPath(associationName); - if (createdAssociationPaths.containsKey(associationName)) { - subCriteria = createdAssociationPaths.get(associationPath); - } - else { - Criteria sc = criteria.createAlias(associationPath, alias); - subCriteria = new CriteriaAndAlias(sc, alias); - createdAssociationPaths.put(associationPath,subCriteria); - } - return subCriteria; - } - - @Override - public ProjectionList projections() { - if (hibernateProjectionList == null) { - hibernateProjectionList = new HibernateProjectionList(); - } - return hibernateProjectionList; - } - - @Override - public Query max(int max) { - criteria.setMaxResults(max); - return this; - } - - @Override - public Query maxResults(int max) { - criteria.setMaxResults(max); - return this; - } - - @Override - public Query offset(int offset) { - criteria.setFirstResult(offset); - return this; - } - - @Override - public Query firstResult(int offset) { - offset(offset); - return this; - } - - @Override - public Query order(Order order) { - super.order(order); - criteria.addOrder(order.getDirection() == Order.Direction.ASC ? - org.hibernate.criterion.Order.asc(calculatePropertyName(order.getProperty())) : - org.hibernate.criterion.Order.desc(calculatePropertyName(order.getProperty()))); - return this; - } - - @Override - public List list() { - int projectionLength = 0; - if (hibernateProjectionList != null) { - org.hibernate.criterion.ProjectionList projectionList = hibernateProjectionList.getHibernateProjectionList(); - projectionLength = projectionList.getLength(); - criteria.setProjection(projectionList); - } - - if (projectionLength < 2) { - criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); - } - - applyFetchStrategies(); - return criteria.list(); - } - - protected void applyFetchStrategies() { - for (Map.Entry entry : fetchStrategies.entrySet()) { - switch(entry.getValue()) { - case EAGER: - criteria.setFetchMode(entry.getKey(), FetchMode.JOIN); - break; - case LAZY: - criteria.setFetchMode(entry.getKey(), FetchMode.SELECT); - break; - } - } - } - - @Override - protected void flushBeforeQuery() { - // do nothing - } - - @Override - public Object singleResult() { - if (hibernateProjectionList != null) { - criteria.setProjection(hibernateProjectionList.getHibernateProjectionList()); - } - criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); - applyFetchStrategies(); - return criteria.uniqueResult(); - } - - @Override - protected List executeQuery(PersistentEntity entity, Junction criteria) { - return list(); - } - - String handleAssociationQuery(Association association, List criteriaList) { - return getCriteriaAndAlias(association).alias; - } - - protected CriteriaAndAlias getCriteriaAndAlias(Association association) { - String associationName = calculatePropertyName(association.getName()); - String newAlias = generateAlias(associationName); - return getOrCreateAlias(associationName, newAlias); - } - - protected void addToCriteria(org.hibernate.criterion.Criterion criterion) { - if (criterion == null) { - return; - } - - if (aliasInstanceStack.isEmpty()) { - criteria.add(criterion); - } - else { - aliasInstanceStack.getLast().add(criterion); - } - } - - protected String calculatePropertyName(String property) { - if (alias == null) { - return property; - } - return alias + '.' + property; - } - - protected String generateAlias(String associationName) { - return calculatePropertyName(associationName) + calculatePropertyName(ALIAS) + aliasCount++; - } - - protected abstract void setDetachedCriteriaValue(QueryableCriteria value, PropertyCriterion pc); - - protected abstract AbstractHibernateCriterionAdapter createHibernateCriterionAdapter(PersistentEntity entity, Criterion c, String alias); - - protected abstract org.hibernate.criterion.Criterion createRlikeExpression(String propertyName, String value); - - protected class HibernateJunction extends Junction { - - protected org.hibernate.criterion.Junction hibernateJunction; - protected String alias; - - public HibernateJunction(org.hibernate.criterion.Junction junction, String alias) { - hibernateJunction = junction; - this.alias = alias; - } - - @Override - public Junction add(Criterion c) { - if (c != null) { - if (c instanceof FunctionCallingCriterion) { - org.hibernate.criterion.Criterion sqlRestriction = getRestrictionForFunctionCall((FunctionCallingCriterion) c, entity); - if (sqlRestriction != null) { - hibernateJunction.add(sqlRestriction); - } - } - else { - AbstractHibernateCriterionAdapter adapter = createHibernateCriterionAdapter(getEntity(),c, alias); - org.hibernate.criterion.Criterion criterion = adapter.toHibernateCriterion(AbstractHibernateQuery.this); - if (criterion != null) { - hibernateJunction.add(criterion); - } - } - } - return this; - } - } - - protected class HibernateProjectionList extends ProjectionList { - - org.hibernate.criterion.ProjectionList projectionList = Projections.projectionList(); - - public org.hibernate.criterion.ProjectionList getHibernateProjectionList() { - return projectionList; - } - - @Override - public ProjectionList add(Projection p) { - projectionList.add(new HibernateProjectionAdapter(p).toHibernateProjection()); - return this; - } - - @Override - public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(String property) { - projectionList.add(Projections.countDistinct(calculatePropertyName(property))); - return this; - } - - @Override - public org.grails.datastore.mapping.query.api.ProjectionList distinct(String property) { - projectionList.add(Projections.distinct(Projections.property(calculatePropertyName(property)))); - return this; - } - - @Override - public org.grails.datastore.mapping.query.api.ProjectionList rowCount() { - projectionList.add(Projections.rowCount()); - return this; - } - - @Override - public ProjectionList id() { - projectionList.add(Projections.id()); - return this; - } - - @Override - public ProjectionList count() { - projectionList.add(Projections.rowCount()); - return this; - } - - @Override - public ProjectionList property(String name) { - projectionList.add(Projections.property(calculatePropertyName(name))); - return this; - } - - @Override - public ProjectionList sum(String name) { - projectionList.add(Projections.sum(calculatePropertyName(name))); - return this; - } - - @Override - public ProjectionList min(String name) { - projectionList.add(Projections.min(calculatePropertyName(name))); - return this; - } - - @Override - public ProjectionList max(String name) { - projectionList.add(Projections.max(calculatePropertyName(name))); - return this; - } - - @Override - public ProjectionList avg(String name) { - projectionList.add(Projections.avg(calculatePropertyName(name))); - return this; - } - - @Override - public ProjectionList distinct() { - criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - return this; - } - } - - protected class HibernateAssociationQuery extends AssociationQuery { - - protected String alias; - protected org.hibernate.criterion.Junction hibernateJunction; - protected Criteria assocationCriteria; - - public HibernateAssociationQuery(Criteria criteria, AbstractHibernateSession session, PersistentEntity associatedEntity, Association association, String alias) { - super(session, associatedEntity, association); - this.alias = alias; - assocationCriteria = criteria; - } - - @Override - public Query isEmpty(String property) { - org.hibernate.criterion.Criterion criterion = Restrictions.isEmpty(calculatePropertyName(property)); - addToCriteria(criterion); - return this; - } - - protected void addToCriteria(org.hibernate.criterion.Criterion criterion) { - if (hibernateJunction != null) { - hibernateJunction.add(criterion); - } - else { - assocationCriteria.add(criterion); - } - } - - @Override - public Query isNotEmpty(String property) { - addToCriteria(Restrictions.isNotEmpty(calculatePropertyName(property))); - return this; - } - - @Override - public Query isNull(String property) { - addToCriteria(Restrictions.isNull(calculatePropertyName(property))); - return this; - } - - @Override - public Query isNotNull(String property) { - addToCriteria(Restrictions.isNotNull(calculatePropertyName(property))); - return this; - } - - @Override - public void add(Criterion criterion) { - final org.hibernate.criterion.Criterion hibernateCriterion = createHibernateCriterionAdapter( - getEntity(), criterion, alias).toHibernateCriterion(AbstractHibernateQuery.this); - if (hibernateCriterion != null) { - addToCriteria(hibernateCriterion); - } - } - - @Override - public Junction disjunction() { - final org.hibernate.criterion.Disjunction disjunction = Restrictions.disjunction(); - addToCriteria(disjunction); - return new HibernateJunction(disjunction, alias); - } - - @Override - public Junction negation() { - final org.hibernate.criterion.Disjunction disjunction = Restrictions.disjunction(); - addToCriteria(Restrictions.not(disjunction)); - return new HibernateJunction(disjunction, alias); - } - - @Override - public Query eq(String property, Object value) { - addToCriteria(Restrictions.eq(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query idEq(Object value) { - addToCriteria(Restrictions.idEq(value)); - return this; - } - - @Override - public Query gt(String property, Object value) { - addToCriteria(Restrictions.gt(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query and(Criterion a, Criterion b) { - AbstractHibernateCriterionAdapter aa = createHibernateCriterionAdapter(getEntity(),a, alias); - AbstractHibernateCriterionAdapter ab = createHibernateCriterionAdapter(getEntity(),a, alias); - addToCriteria(Restrictions.and(aa.toHibernateCriterion(AbstractHibernateQuery.this), ab.toHibernateCriterion(AbstractHibernateQuery.this))); - return this; - } - - @Override - public Query or(Criterion a, Criterion b) { - AbstractHibernateCriterionAdapter aa = createHibernateCriterionAdapter(getEntity(),a, alias); - AbstractHibernateCriterionAdapter ab = createHibernateCriterionAdapter(getEntity(),a, alias); - addToCriteria(Restrictions.or(aa.toHibernateCriterion(AbstractHibernateQuery.this), ab.toHibernateCriterion(AbstractHibernateQuery.this))); - return this; - } - - @Override - public Query allEq(Map values) { - addToCriteria(Restrictions.allEq(values)); - return this; - } - - @Override - public Query ge(String property, Object value) { - addToCriteria(Restrictions.ge(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query le(String property, Object value) { - addToCriteria(Restrictions.le(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query gte(String property, Object value) { - addToCriteria(Restrictions.ge(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query lte(String property, Object value) { - addToCriteria(Restrictions.le(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query lt(String property, Object value) { - addToCriteria(Restrictions.lt(calculatePropertyName(property), value)); - return this; - } - - @Override - public Query in(String property, List values) { - addToCriteria(Restrictions.in(calculatePropertyName(property), values)); - return this; - } - - @Override - public Query between(String property, Object start, Object end) { - addToCriteria(Restrictions.between(calculatePropertyName(property), start, end)); - return this; - } - - @Override - public Query like(String property, String expr) { - addToCriteria(Restrictions.like(calculatePropertyName(property), calculatePropertyName(expr))); - return this; - } - - @Override - public Query ilike(String property, String expr) { - addToCriteria(Restrictions.ilike(calculatePropertyName(property), calculatePropertyName(expr))); - return this; - } - - @Override - public Query rlike(String property, String expr) { - addToCriteria(createRlikeExpression(calculatePropertyName(property), calculatePropertyName(expr))); - return this; - } - } - - protected class CriteriaAndAlias { - protected Criteria criteria; - protected String alias; - - public CriteriaAndAlias(Criteria subCriteria, String alias) { - criteria = subCriteria; - this.alias = alias; - } - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateProjectionAdapter.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateProjectionAdapter.java deleted file mode 100644 index 4d26d4c5b..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateProjectionAdapter.java +++ /dev/null @@ -1,91 +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.codehaus.groovy.grails.orm.hibernate.query; - -import java.util.HashMap; -import java.util.Map; - -import org.grails.datastore.mapping.query.Query; -import org.hibernate.criterion.Projection; -import org.hibernate.criterion.Projections; - -/** - * Adapts Grails datastore API to Hibernate projections. - * - * @author Graeme Rocher - * @since 2.0 - */ -public class HibernateProjectionAdapter { - private Query.Projection projection; - private static Map, ProjectionAdapter> adapterMap = new HashMap, ProjectionAdapter>(); - - static { - adapterMap.put(Query.AvgProjection.class, new ProjectionAdapter() { - public Projection toHibernateProjection(Query.Projection gormProjection) { - Query.AvgProjection avg = (Query.AvgProjection) gormProjection; - return Projections.avg(avg.getPropertyName()); - } - }); - adapterMap.put(Query.SumProjection.class, new ProjectionAdapter() { - public Projection toHibernateProjection(Query.Projection gormProjection) { - Query.SumProjection avg = (Query.SumProjection) gormProjection; - return Projections.sum(avg.getPropertyName()); - } - }); - adapterMap.put(Query.DistinctPropertyProjection.class, new ProjectionAdapter() { - public Projection toHibernateProjection(Query.Projection gormProjection) { - Query.DistinctPropertyProjection avg = (Query.DistinctPropertyProjection) gormProjection; - return Projections.distinct(Projections.property(avg.getPropertyName())); - } - }); - adapterMap.put(Query.PropertyProjection.class, new ProjectionAdapter() { - public Projection toHibernateProjection(Query.Projection gormProjection) { - Query.PropertyProjection avg = (Query.PropertyProjection) gormProjection; - return Projections.property(avg.getPropertyName()); - } - }); - adapterMap.put(Query.CountDistinctProjection.class, new ProjectionAdapter() { - public Projection toHibernateProjection(Query.Projection gormProjection) { - Query.CountDistinctProjection cd = (Query.CountDistinctProjection) gormProjection; - return Projections.countDistinct(cd.getPropertyName()); - } - }); - adapterMap.put(Query.MaxProjection.class, new ProjectionAdapter() { - public Projection toHibernateProjection(Query.Projection gormProjection) { - Query.MaxProjection cd = (Query.MaxProjection) gormProjection; - return Projections.max(cd.getPropertyName()); - } - }); - adapterMap.put(Query.MinProjection.class, new ProjectionAdapter() { - public Projection toHibernateProjection(Query.Projection gormProjection) { - Query.MinProjection cd = (Query.MinProjection) gormProjection; - return Projections.min(cd.getPropertyName()); - } - }); - } - - public HibernateProjectionAdapter(Query.Projection projection) { - this.projection = projection; - } - - public Projection toHibernateProjection() { - ProjectionAdapter projectionAdapter = adapterMap.get(projection.getClass()); - return projectionAdapter.toHibernateProjection(projection); - } - - private static interface ProjectionAdapter { - Projection toHibernateProjection(Query.Projection gormProjection); - } -} 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 deleted file mode 100644 index b09dc212a..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AbstractAggregatePersistenceContextInterceptor.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 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.codehaus.groovy.grails.orm.hibernate.support; - -import java.util.ArrayList; -import java.util.List; - -import org.codehaus.groovy.grails.support.PersistenceContextInterceptor; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; - -/** - * @author Burt Beckwith - */ -public abstract class AbstractAggregatePersistenceContextInterceptor implements PersistenceContextInterceptor, InitializingBean, ApplicationContextAware { - - protected List interceptors = new ArrayList(); - protected List dataSourceNames = new ArrayList(); - protected ApplicationContext applicationContext; - - public boolean isOpen() { - for (PersistenceContextInterceptor interceptor : interceptors) { - if (interceptor.isOpen()) { - // true at least one is true - return true; - } - } - return false; - } - - public void reconnect() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.reconnect(); - } - } - - public void destroy() { - for (PersistenceContextInterceptor interceptor : interceptors) { - if (interceptor.isOpen()) { - interceptor.destroy(); - } - } - } - - public void clear() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.clear(); - } - } - - public void disconnect() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.disconnect(); - } - } - - public void flush() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.flush(); - } - } - - public void init() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.init(); - } - } - - public void setReadOnly() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.setReadOnly(); - } - } - - public void setReadWrite() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.setReadWrite(); - } - } - - /** - * Dependency injection for the datasource names. - * @param names the names - */ - public void setDataSourceNames(List names) { - dataSourceNames = names; - } - - public void setApplicationContext(ApplicationContext ctx) { - applicationContext = ctx; - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateBeanWrapper.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateBeanWrapper.java deleted file mode 100644 index a6ad517b2..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateBeanWrapper.java +++ /dev/null @@ -1,77 +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.support; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; - -import org.hibernate.Hibernate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.BeansException; - -/** - * BeanWrapper implementaion that will not lazy initialize entity properties. - */ -public class HibernateBeanWrapper extends BeanWrapperImpl { - - private static final Logger log = LoggerFactory.getLogger(HibernateBeanWrapper.class); - - public HibernateBeanWrapper() { - // default - } - - public HibernateBeanWrapper(boolean b) { - super(b); - } - - public HibernateBeanWrapper(Object o) { - super(o); - } - - public HibernateBeanWrapper(Class aClass) { - super(aClass); - } - - public HibernateBeanWrapper(Object o, String s, Object o1) { - super(o, s, o1); - } - - /** - * Checks Hibernate.isInitialized before calling super method. - * - * @param name target property - * @return null if false or super'name value if true - * @throws BeansException - */ - @Override - public Object getPropertyValue(String name) throws BeansException { - PropertyDescriptor desc = getPropertyDescriptor(name); - Method method = desc.getReadMethod(); - Object owner = getWrappedInstance(); - try { - if (Hibernate.isInitialized(method.invoke(owner))) { - return super.getPropertyValue(name); - } - } - catch (Exception e) { - log.error("Error checking Hibernate initialization on method " + - method.getName() + " for class " + owner.getClass().getName(), e); - } - return null; - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/SoftKey.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/SoftKey.java deleted file mode 100644 index fd073b18f..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/SoftKey.java +++ /dev/null @@ -1,66 +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.support; - -import java.lang.ref.SoftReference; - -/** - * SoftReference key to be used with ConcurrentHashMap. - * - * @author Lari Hotari - */ -public class SoftKey extends SoftReference { - final int hash; - - public SoftKey(T referent) { - super(referent); - hash = referent.hashCode(); - } - - @Override - public int hashCode() { - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - @SuppressWarnings("unchecked") - SoftKey other = (SoftKey)obj; - if (hash != other.hash) { - return false; - } - T referent = get(); - T otherReferent = other.get(); - if (referent == null) { - if (otherReferent != null) { - return false; - } - } - else if (!referent.equals(otherReferent)) { - return false; - } - return true; - } -} diff --git a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/SpringLobHandlerDetectorFactoryBean.java b/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/SpringLobHandlerDetectorFactoryBean.java deleted file mode 100644 index 2f43a5e7f..000000000 --- a/grails-datastore-gorm-hibernate-core/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/SpringLobHandlerDetectorFactoryBean.java +++ /dev/null @@ -1,84 +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.support; - -import javax.sql.DataSource; - -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.jdbc.support.JdbcUtils; -import org.springframework.jdbc.support.MetaDataAccessException; -import org.springframework.jdbc.support.lob.DefaultLobHandler; -import org.springframework.jdbc.support.lob.LobHandler; -import org.springframework.jdbc.support.lob.OracleLobHandler; -import org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor; -import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor; -import org.springframework.util.Assert; - -/** - * Attempts to auto-detect the LobHandler to use from the db meta data. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class SpringLobHandlerDetectorFactoryBean implements FactoryBean, InitializingBean { - - private static final String ORACLE_DB_NAME = "Oracle"; - private DataSource dataSource; - private LobHandler lobHandler; - private boolean pooledConnection; - private NativeJdbcExtractor nativeJdbcExtractor = new CommonsDbcpNativeJdbcExtractor(); - - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - } - - public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) { - this.nativeJdbcExtractor = nativeJdbcExtractor; - } - - public void setPooledConnection(boolean pooledConnection) { - this.pooledConnection = pooledConnection; - } - - public LobHandler getObject() { - return lobHandler; - } - - public Class getObjectType() { - return LobHandler.class; - } - - public boolean isSingleton() { - return true; - } - - public void afterPropertiesSet() throws MetaDataAccessException { - Assert.notNull(dataSource, "Data source is not set!"); - - String dbName = (String)JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName"); - if (SpringLobHandlerDetectorFactoryBean.ORACLE_DB_NAME.equals(dbName)) { - final OracleLobHandler oracleLobHandler = new OracleLobHandler(); - lobHandler = oracleLobHandler; - if (pooledConnection) { - oracleLobHandler.setNativeJdbcExtractor(nativeJdbcExtractor); - } - } - else { - lobHandler = new DefaultLobHandler(); - } - } -} diff --git a/grails-datastore-gorm-hibernate/build.gradle b/grails-datastore-gorm-hibernate/build.gradle deleted file mode 100644 index 29e8e23d2..000000000 --- a/grails-datastore-gorm-hibernate/build.gradle +++ /dev/null @@ -1,142 +0,0 @@ -configurations { - provided -} - -dependencies { - - compile("org.grails:grails-core:$grailsVersion") { - exclude group:'commons-logging',module:'commons-logging' - } - compile("org.grails:grails-bootstrap:$grailsVersion") - compile("org.grails:grails-plugin-domain-class:$grailsVersion") { - exclude group: 'org.grails', module:'grails-plugin-testing' - exclude group: 'org.grails', module:'grails-datastore-core' - exclude group: 'org.grails', module:'grails-datastore-gorm' - exclude group: 'org.grails', module:'grails-datastore-simple' - } - compile("org.grails:grails-web:$grailsVersion") - provided 'javax.servlet:servlet-api:2.5' - - compile(project(":grails-datastore-gorm")) { - exclude group: 'org.grails', module:'grails-bootstrap' - exclude group: 'org.grails', module:'grails-core' - exclude group: 'org.grails', module:'grails-async' - exclude group: 'org.grails', module:'grails-plugin-testing' - exclude group: 'org.slf4j', module:'jcl-over-slf4j' - exclude group: 'org.slf4j', module:'jul-to-slf4j' - exclude group: 'org.slf4j', module:'slf4j-api' - exclude group: 'org.slf4j', module:'slf4j-simple' - } - compile(project(":grails-datastore-gorm-plugin-support")) { - exclude group: 'org.grails', module:'grails-bootstrap' - exclude group: 'org.grails', module:'grails-core' - exclude group: 'org.grails', module:'grails-plugin-testing' - } - compile(project(":grails-datastore-core")) { - exclude group: 'org.grails', module:'grails-plugin-testing' - } - compile(project(":grails-datastore-gorm-hibernate-core")) - - compile "org.springframework:spring-jdbc:$springVersion" - compile "org.springframework:spring-orm:$springVersion" - compile "org.springframework:spring-tx:$springVersion" - compile "org.springframework:spring-web:$springVersion" - compile 'org.hibernate:hibernate-entitymanager:3.6.10.Final', { - exclude group: 'javassist', module: 'javassist' - } - - // Specs - compile 'javax.transaction:jta:1.1' - - compile('org.hibernate:hibernate-core:3.6.10.Final') { - exclude group:'commons-logging', module:'commons-logging' - exclude group:'commons-collections', module:'commons-collections' - exclude group:'org.slf4j', module:'slf4j-api' - exclude group:'xml-apis', module:'xml-apis' - exclude group:'dom4j', module:'dom4j' - exclude group:'antlr', module: 'antlr' - } - compile 'org.javassist:javassist:3.17.1-GA' - compile 'javax.transaction:jta:1.1' - runtime('dom4j:dom4j:1.6.1') { - exclude group: 'xml-apis', module:'xml-apis' - } - - compile('org.hibernate:hibernate-commons-annotations:3.2.0.Final'){ - exclude group: 'org.slf4j', module:'slf4j-api' - exclude group: 'commons-logging', module:'commons-logging' - } - runtime ("net.sf.ehcache:ehcache-core:2.4.6") { - exclude group: 'commons-logging', module:'commons-logging' - } - compile('org.hibernate:hibernate-validator:4.1.0.Final') { - exclude group:'commons-logging', module:'commons-logging' - exclude group:'commons-collections', module:'commons-collections' - exclude group:'org.slf4j', module:'slf4j-api' - } - runtime('org.hibernate:hibernate-ehcache:3.6.10.Final') { - exclude group:'commons-logging', module:'commons-logging' - exclude group:'commons-collections', module:'commons-collections' - exclude group:'org.slf4j', module:'slf4j-api' - exclude group:'xml-apis', module:'xml-apis' - exclude group:'dom4j', module:'dom4j' - exclude group:'org.hibernate', module:'hibernate-core' - exclude group:'net.sf.ehcache', module:'ehcache' - exclude group:'net.sf.ehcache', module:'ehcache-core' - } - runtime ('antlr:antlr:2.7.7') { - exclude group: 'commons-logging', module:'commons-logging' - } - runtime 'javax.validation:validation-api:1.0.0.GA' - - runtime "commons-lang:commons-lang:2.4" - compile("commons-beanutils:commons-beanutils:1.8.0") { - exclude group: 'commons-logging', module:'commons-logging' - } - - testCompile project(":grails-datastore-gorm-test") - testCompile project(":grails-datastore-gorm-tck") - testCompile "com.h2database:h2:1.3.164" - - testCompile("org.grails:grails-core:$grailsVersion") - testCompile("org.grails:grails-bootstrap:$grailsVersion") - testCompile("org.grails:grails-plugin-domain-class:$grailsVersion") { - transitive = false - exclude group: 'org.grails', module:'grails-plugin-testing' - exclude group: 'org.grails', module:'grails-datastore-core' - exclude group: 'org.grails', module:'grails-datastore-gorm' - exclude group: 'org.grails', module:'grails-datastore-simple' - } - testCompile("org.grails:grails-web:$grailsVersion") - testCompile("org.grails:grails-plugin-controllers:$grailsVersion") { - transitive = false - exclude group: 'org.grails', module:'grails-plugin-domain-class' - exclude group: 'org.grails', module:'grails-web' - } - testCompile("org.grails:grails-plugin-validation:$grailsVersion") { - exclude group: 'org.grails', module:'grails-plugin-domain-class' - } - - testRuntime "javax.servlet:servlet-api:2.5" -} - -sourceSets { - main { - compileClasspath += configurations.provided - } - javadoc { - classpath = configurations.compile + configurations.provided - } -} -idea { - module { - scopes.PROVIDED.plus += configurations.provided - } -} - -/* -test { - jvmArgs '-Xmx1024m', '-Xdebug', '-Xnoagent', '-Dgrails.full.stacktrace=true', '-Djava.compiler=NONE', - '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005' -} -*/ diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java deleted file mode 100644 index f586c8cf6..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java +++ /dev/null @@ -1,1991 +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 grails.orm; - -import grails.gorm.DetachedCriteria; -import grails.util.CollectionUtils; -import groovy.lang.Closure; -import groovy.lang.GroovyObjectSupport; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; -import groovy.lang.MetaMethod; -import groovy.lang.MissingMethodException; - -import java.beans.PropertyDescriptor; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -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.query.HibernateCriterionAdapter; -import org.codehaus.groovy.grails.orm.hibernate.query.HibernateProjectionAdapter; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.hibernate.Criteria; -import org.hibernate.EntityMode; -import org.hibernate.FetchMode; -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.TypeHelper; -import org.hibernate.criterion.AggregateProjection; -import org.hibernate.criterion.CountProjection; -import org.hibernate.criterion.CriteriaSpecification; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.IdentifierProjection; -import org.hibernate.criterion.Junction; -import org.hibernate.criterion.Order; -import org.hibernate.criterion.Projection; -import org.hibernate.criterion.ProjectionList; -import org.hibernate.criterion.Projections; -import org.hibernate.criterion.Property; -import org.hibernate.criterion.PropertyProjection; -import org.hibernate.criterion.Restrictions; -import org.hibernate.criterion.SimpleExpression; -import org.hibernate.engine.SessionFactoryImplementor; -import org.hibernate.metadata.ClassMetadata; -import org.hibernate.transform.ResultTransformer; -import org.hibernate.type.AssociationType; -import org.hibernate.type.EmbeddedComponentType; -import org.hibernate.type.StandardBasicTypes; -import org.hibernate.type.Type; -import org.springframework.beans.BeanUtils; -import org.springframework.core.convert.ConversionService; -import org.springframework.orm.hibernate3.SessionHolder; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -/** - *

    Wraps the Hibernate Criteria API in a builder. The builder can be retrieved through the "createCriteria()" dynamic static - * method of Grails domain classes (Example in Groovy): - * - *

    - *         def c = Account.createCriteria()
    - *         def results = c {
    - *             projections {
    - *                 groupProperty("branch")
    - *             }
    - *             like("holderFirstName", "Fred%")
    - *             and {
    - *                 between("balance", 500, 1000)
    - *                 eq("branch", "London")
    - *             }
    - *             maxResults(10)
    - *             order("holderLastName", "desc")
    - *         }
    - * 
    - * - *

    The builder can also be instantiated standalone with a SessionFactory and persistent Class instance: - * - *

    - *      new HibernateCriteriaBuilder(clazz, sessionFactory).list {
    - *         eq("firstName", "Fred")
    - *      }
    - * 
    - * - * @author Graeme Rocher - */ -public class HibernateCriteriaBuilder extends GroovyObjectSupport implements org.grails.datastore.mapping.query.api.Criteria, org.grails.datastore.mapping.query.api.ProjectionList { - - public static final String AND = "and"; // builder - public static final String IS_NULL = "isNull"; // builder - public static final String IS_NOT_NULL = "isNotNull"; // builder - public static final String NOT = "not";// builder - public static final String OR = "or"; // builder - public static final String ID_EQUALS = "idEq"; // builder - public static final String IS_EMPTY = "isEmpty"; //builder - public static final String IS_NOT_EMPTY = "isNotEmpty"; //builder - public static final String RLIKE = "rlike";//method - public static final String BETWEEN = "between";//method - public static final String EQUALS = "eq";//method - public static final String EQUALS_PROPERTY = "eqProperty";//method - public static final String GREATER_THAN = "gt";//method - public static final String GREATER_THAN_PROPERTY = "gtProperty";//method - public static final String GREATER_THAN_OR_EQUAL = "ge";//method - public static final String GREATER_THAN_OR_EQUAL_PROPERTY = "geProperty";//method - public static final String ILIKE = "ilike";//method - public static final String IN = "in";//method - public static final String LESS_THAN = "lt"; //method - public static final String LESS_THAN_PROPERTY = "ltProperty";//method - public static final String LESS_THAN_OR_EQUAL = "le";//method - public static final String LESS_THAN_OR_EQUAL_PROPERTY = "leProperty";//method - public static final String LIKE = "like";//method - public static final String NOT_EQUAL = "ne";//method - public static final String NOT_EQUAL_PROPERTY = "neProperty";//method - public static final String SIZE_EQUALS = "sizeEq"; //method - public static final String ORDER_DESCENDING = "desc"; - public static final String ORDER_ASCENDING = "asc"; - private static final String ROOT_DO_CALL = "doCall"; - private static final String ROOT_CALL = "call"; - private static final String LIST_CALL = "list"; - private static final String LIST_DISTINCT_CALL = "listDistinct"; - private static final String COUNT_CALL = "count"; - private static final String GET_CALL = "get"; - private static final String SCROLL_CALL = "scroll"; - private static final String SET_RESULT_TRANSFORMER_CALL = "setResultTransformer"; - private static final String PROJECTIONS = "projections"; - - private SessionFactory sessionFactory; - private Session hibernateSession; - private Class targetClass; - private Criteria criteria; - private MetaClass criteriaMetaClass; - - private boolean uniqueResult = false; - private List logicalExpressionStack = new ArrayList(); - private List associationStack = new ArrayList(); - private boolean participate; - private boolean scroll; - private boolean count; - private ProjectionList projectionList = Projections.projectionList(); - private List aliasStack = new ArrayList(); - private List aliasInstanceStack = new ArrayList(); - private Map aliasMap = new HashMap(); - private static final String ALIAS = "_alias"; - private ResultTransformer resultTransformer; - private int aliasCount; - - private boolean paginationEnabledList = false; - private List orderEntries; - private GrailsApplication grailsApplication; - private ConversionService conversionService; - - @SuppressWarnings("rawtypes") - public HibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory) { - this.targetClass = targetClass; - this.sessionFactory = sessionFactory; - } - - @SuppressWarnings("rawtypes") - public HibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory, boolean uniqueResult) { - this.targetClass = targetClass; - this.sessionFactory = sessionFactory; - this.uniqueResult = uniqueResult; - } - - public void setGrailsApplication(GrailsApplication grailsApplication) { - this.grailsApplication = grailsApplication; - } - - public void setConversionService(ConversionService conversionService) { - this.conversionService = conversionService; - } - - /** - * Returns the criteria instance - * @return The criteria instance - */ - public Criteria getInstance() { - return criteria; - } - - /** - * Set whether a unique result should be returned - * @param uniqueResult True if a unique result should be returned - */ - public void setUniqueResult(boolean uniqueResult) { - this.uniqueResult = uniqueResult; - } - - /** - * A projection that selects a property name - * @param propertyName The name of the property - */ - public org.grails.datastore.mapping.query.api.ProjectionList property(String propertyName) { - return property(propertyName, null); - } - - /** - * A projection that selects a property name - * @param propertyName The name of the property - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList property(String propertyName, String alias) { - final PropertyProjection propertyProjection = Projections.property(calculatePropertyName(propertyName)); - addProjectionToList(propertyProjection, alias); - return this; - } - - /** - * Adds a projection to the projectList for the given alias - * - * @param propertyProjection The projection - * @param alias The alias - */ - protected void addProjectionToList(Projection propertyProjection, String alias) { - if (alias != null) { - projectionList.add(propertyProjection,alias); - } - else { - projectionList.add(propertyProjection); - } - } - - /** - * Adds a sql projection to the criteria - * - * @param sql SQL projecting a single value - * @param columnAlias column alias for the projected value - * @param type the type of the projected value - */ - protected void sqlProjection(String sql, String columnAlias, Type type) { - sqlProjection(sql, CollectionUtils.newList(columnAlias), CollectionUtils.newList(type)); - } - - /** - * Adds a sql projection to the criteria - * - * @param sql SQL projecting - * @param columnAliases List of column aliases for the projected values - * @param types List of types for the projected values - */ - protected void sqlProjection(String sql, List columnAliases, List types) { - projectionList.add(Projections.sqlProjection(sql, columnAliases.toArray(new String[columnAliases.size()]), types.toArray(new Type[types.size()]))); - } - - /** - * Adds a sql projection to the criteria - * - * @param sql SQL projecting - * @param groupBy group by clause - * @param columnAliases List of column aliases for the projected values - * @param types List of types for the projected values - */ - protected void sqlGroupProjection(String sql, String groupBy, List columnAliases, List types) { - projectionList.add(Projections.sqlGroupProjection(sql, groupBy, columnAliases.toArray(new String[columnAliases.size()]), types.toArray(new Type[types.size()]))); - } - - /** - * A projection that selects a distince property name - * @param propertyName The property name - */ - public org.grails.datastore.mapping.query.api.ProjectionList distinct(String propertyName) { - distinct(propertyName, null); - return this; - } - - /** - * A projection that selects a distince property name - * @param propertyName The property name - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList distinct(String propertyName, String alias) { - final Projection proj = Projections.distinct(Projections.property(calculatePropertyName(propertyName))); - addProjectionToList(proj,alias); - return this; - } - - /** - * A distinct projection that takes a list - * - * @param propertyNames The list of distince property names - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.ProjectionList distinct(Collection propertyNames) { - return distinct(propertyNames, null); - } - - /** - * A distinct projection that takes a list - * - * @param propertyNames The list of distince property names - * @param alias The alias to use - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.ProjectionList distinct(Collection propertyNames, String alias) { - ProjectionList list = Projections.projectionList(); - for (Object o : propertyNames) { - list.add(Projections.property(calculatePropertyName(o.toString()))); - } - final Projection proj = Projections.distinct(list); - addProjectionToList(proj, alias); - return this; - } - - /** - * Adds a projection that allows the criteria to return the property average value - * - * @param propertyName The name of the property - */ - public org.grails.datastore.mapping.query.api.ProjectionList avg(String propertyName) { - return avg(propertyName, null); - } - - /** - * Adds a projection that allows the criteria to return the property average value - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList avg(String propertyName, String alias) { - final AggregateProjection aggregateProjection = Projections.avg(calculatePropertyName(propertyName)); - addProjectionToList(aggregateProjection, alias); - return this; - } - - /** - * Use a join query - * - * @param associationPath The path of the association - */ - public void join(String associationPath) { - criteria.setFetchMode(calculatePropertyName(associationPath), FetchMode.JOIN); - } - - /** - * Whether a pessimistic lock should be obtained. - * - * @param shouldLock True if it should - */ - public void lock(boolean shouldLock) { - String lastAlias = getLastAlias(); - - if (shouldLock) { - if (lastAlias != null) { - criteria.setLockMode(lastAlias, LockMode.PESSIMISTIC_WRITE); - } - else { - criteria.setLockMode(LockMode.PESSIMISTIC_WRITE); - } - } - else { - if (lastAlias != null) { - criteria.setLockMode(lastAlias, LockMode.NONE); - } - else { - criteria.setLockMode(LockMode.NONE); - } - } - } - - /** - * Use a select query - * - * @param associationPath The path of the association - */ - public void select(String associationPath) { - criteria.setFetchMode(calculatePropertyName(associationPath), FetchMode.SELECT); - } - - /** - * Whether to use the query cache - * @param shouldCache True if the query should be cached - */ - public void cache(boolean shouldCache) { - criteria.setCacheable(shouldCache); - } - - /** - * Calculates the property name including any alias paths - * - * @param propertyName The property name - * @return The calculated property name - */ - private String calculatePropertyName(String propertyName) { - String lastAlias = getLastAlias(); - if (lastAlias != null) { - return lastAlias +'.'+propertyName; - } - - return propertyName; - } - - private String getLastAlias() { - if (aliasStack.size() > 0) { - return aliasStack.get(aliasStack.size() - 1).toString(); - } - return null; - } - - public Class getTargetClass() { - return targetClass; - } - - /** - * Calculates the property value, converting GStrings if necessary - * - * @param propertyValue The property value - * @return The calculated property value - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - private Object calculatePropertyValue(Object propertyValue) { - if (propertyValue instanceof CharSequence) { - return propertyValue.toString(); - } - if (propertyValue instanceof QueryableCriteria) { - propertyValue = getHibernateDetachedCriteria((QueryableCriteria)propertyValue); - } - else if (propertyValue instanceof Closure) { - propertyValue = getHibernateDetachedCriteria( - new DetachedCriteria(targetClass).build((Closure)propertyValue)); - } - return propertyValue; - } - - public static org.hibernate.criterion.DetachedCriteria getHibernateDetachedCriteria(QueryableCriteria queryableCriteria) { - org.hibernate.criterion.DetachedCriteria detachedCriteria = org.hibernate.criterion.DetachedCriteria.forClass( - queryableCriteria.getPersistentEntity().getJavaClass()); - populateHibernateDetachedCriteria(detachedCriteria, queryableCriteria); - return detachedCriteria; - } - - private static void populateHibernateDetachedCriteria(org.hibernate.criterion.DetachedCriteria detachedCriteria, QueryableCriteria queryableCriteria) { - List criteriaList = queryableCriteria.getCriteria(); - for (Query.Criterion criterion : criteriaList) { - Criterion hibernateCriterion = new HibernateCriterionAdapter(criterion).toHibernateCriterion(null); - if (hibernateCriterion != null) { - detachedCriteria.add(hibernateCriterion); - } - } - - List projections = queryableCriteria.getProjections(); - ProjectionList projectionList = Projections.projectionList(); - for (Query.Projection projection : projections) { - Projection hibernateProjection = new HibernateProjectionAdapter(projection).toHibernateProjection(); - if (hibernateProjection != null) { - projectionList.add(hibernateProjection); - } - } - detachedCriteria.setProjection(projectionList); - } - - /** - * Adds a projection that allows the criteria to return the property count - * - * @param propertyName The name of the property - */ - public void count(String propertyName) { - count(propertyName, null); - } - - /** - * Adds a projection that allows the criteria to return the property count - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public void count(String propertyName, String alias) { - final CountProjection proj = Projections.count(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); - } - - public org.grails.datastore.mapping.query.api.ProjectionList id() { - final IdentifierProjection proj = Projections.id(); - addProjectionToList(proj, null); - return this; - } - - public org.grails.datastore.mapping.query.api.ProjectionList count() { - return rowCount(); - } - - /** - * Adds a projection that allows the criteria to return the distinct property count - * - * @param propertyName The name of the property - */ - public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(String propertyName) { - return countDistinct(propertyName, null); - } - - public org.grails.datastore.mapping.query.api.ProjectionList distinct() { - return this; - } - - /** - * Adds a projection that allows the criteria to return the distinct property count - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(String propertyName, String alias) { - final CountProjection proj = Projections.countDistinct(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); - return this; - } - - /** - * Adds a projection that allows the criteria's result to be grouped by a property - * - * @param propertyName The name of the property - */ - public void groupProperty(String propertyName) { - groupProperty(propertyName, null); - } - - /** - * Adds a projection that allows the criteria's result to be grouped by a property - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public void groupProperty(String propertyName, String alias) { - final PropertyProjection proj = Projections.groupProperty(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); - } - - /** - * Adds a projection that allows the criteria to retrieve a maximum property value - * - * @param propertyName The name of the property - */ - public org.grails.datastore.mapping.query.api.ProjectionList max(String propertyName) { - return max(propertyName, null); - } - - /** - * Adds a projection that allows the criteria to retrieve a maximum property value - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList max(String propertyName, String alias) { - final AggregateProjection proj = Projections.max(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); - return this; - } - - /** - * Adds a projection that allows the criteria to retrieve a minimum property value - * - * @param propertyName The name of the property - */ - public org.grails.datastore.mapping.query.api.ProjectionList min(String propertyName) { - return min(propertyName, null); - } - - /** - * Adds a projection that allows the criteria to retrieve a minimum property value - * - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList min(String propertyName, String alias) { - final AggregateProjection aggregateProjection = Projections.min(calculatePropertyName(propertyName)); - addProjectionToList(aggregateProjection, alias); - return this; - } - - /** - * Adds a projection that allows the criteria to return the row count - * - */ - public org.grails.datastore.mapping.query.api.ProjectionList rowCount() { - return rowCount(null); - } - - /** - * Adds a projection that allows the criteria to return the row count - * - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList rowCount(String alias) { - final Projection proj = Projections.rowCount(); - addProjectionToList(proj, alias); - return this; - } - - /** - * Adds a projection that allows the criteria to retrieve the sum of the results of a property - * - * @param propertyName The name of the property - */ - public org.grails.datastore.mapping.query.api.ProjectionList sum(String propertyName) { - return sum(propertyName, null); - } - - /** - * Adds a projection that allows the criteria to retrieve the sum of the results of a property - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList sum(String propertyName, String alias) { - final AggregateProjection proj = Projections.sum(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); - return this; - } - - /** - * Sets the fetch mode of an associated path - * - * @param associationPath The name of the associated path - * @param fetchMode The fetch mode to set - */ - public void fetchMode(String associationPath, FetchMode fetchMode) { - if (criteria != null) { - criteria.setFetchMode(associationPath, fetchMode); - } - } - - /** - * Sets the resultTransformer. - * @param transformer The result transformer to use. - */ - public void resultTransformer(ResultTransformer transformer) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("Call to [resultTransformer] not supported here")); - } - resultTransformer = transformer; - } - - /** - * Join an association, assigning an alias to the joined association. - *

    - * Functionally equivalent to createAlias(String, String, int) using - * CriteriaSpecificationINNER_JOIN for the joinType. - * - * @param associationPath A dot-seperated property path - * @param alias The alias to assign to the joined association (for later reference). - * - * @return this (for method chaining) - * #see {@link #createAlias(String, String, int)} - * @throws HibernateException Indicates a problem creating the sub criteria - */ - public Criteria createAlias(String associationPath, String alias) { - return criteria.createAlias(associationPath, alias); - } - - /** - * Join an association using the specified join-type, assigning an alias - * to the joined association. - *

    - * The joinType is expected to be one of CriteriaSpecification.INNER_JOIN (the default), - * CriteriaSpecificationFULL_JOIN, or CriteriaSpecificationLEFT_JOIN. - * - * @param associationPath A dot-seperated property path - * @param alias The alias to assign to the joined association (for later reference). - * @param joinType The type of join to use. - * - * @return this (for method chaining) - * @see #createAlias(String, String) - * @throws HibernateException Indicates a problem creating the sub criteria - */ - public Criteria createAlias(String associationPath, String alias, int joinType) { - return criteria.createAlias(associationPath, alias, joinType); - } - - /** - * Creates a Criterion that compares to class properties for equality - * @param propertyName The first property name - * @param otherPropertyName The second property name - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria eqProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [eqProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.eqProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Creates a Criterion that compares to class properties for !equality - * @param propertyName The first property name - * @param otherPropertyName The second property name - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria neProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [neProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.neProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Creates a Criterion that tests if the first property is greater than the second property - * @param propertyName The first property name - * @param otherPropertyName The second property name - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria gtProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [gtProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.gtProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Creates a Criterion that tests if the first property is greater than or equal to the second property - * @param propertyName The first property name - * @param otherPropertyName The second property name - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria geProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [geProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.geProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Creates a Criterion that tests if the first property is less than the second property - * @param propertyName The first property name - * @param otherPropertyName The second property name - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria ltProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [ltProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.ltProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Creates a Criterion that tests if the first property is less than or equal to the second property - * @param propertyName The first property name - * @param otherPropertyName The second property name - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria leProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [leProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.leProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Creates a subquery criterion that ensures the given property is equal to all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria eqAll(String propertyName, Closure propertyValue) { - return eqAll(propertyName, new DetachedCriteria(targetClass).build(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria gtAll(String propertyName, Closure propertyValue) { - return gtAll(propertyName, new DetachedCriteria(targetClass).build(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria ltAll(String propertyName, Closure propertyValue) { - return ltAll(propertyName, new DetachedCriteria(targetClass).build(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria geAll(String propertyName, Closure propertyValue) { - return geAll(propertyName, new DetachedCriteria(targetClass).build(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria leAll(String propertyName, Closure propertyValue) { - return leAll(propertyName, new DetachedCriteria(targetClass).build(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is equal to all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria eqAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).eqAll(getHibernateDetachedCriteria(propertyValue))); - return this; - } - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria gtAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).gtAll(getHibernateDetachedCriteria(propertyValue))); - return this; - } - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria ltAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).ltAll(getHibernateDetachedCriteria(propertyValue))); - return this; - - } - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria geAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).geAll(getHibernateDetachedCriteria(propertyValue))); - return this; - - } - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria leAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).leAll(getHibernateDetachedCriteria(propertyValue))); - return this; - - } - - /** - * Creates a "greater than" Criterion based on the specified property name and value - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria gt(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [gt] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - - Criterion gt; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - gt = Property.forName(propertyName).gt((org.hibernate.criterion.DetachedCriteria)propertyValue); - } - else { - gt = Restrictions.gt(propertyName, propertyValue); - } - addToCriteria(gt); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria lte(String s, Object o) { - return le(s,o); - } - - /** - * Creates a "greater than or equal to" Criterion based on the specified property name and value - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria ge(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [ge] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - - Criterion ge; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - ge = Property.forName(propertyName).ge((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - ge = Restrictions.ge(propertyName, propertyValue); - } - addToCriteria(ge); - return this; - } - - /** - * Creates a "less than" Criterion based on the specified property name and value - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria lt(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [lt] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - Criterion lt; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - lt = Property.forName(propertyName).lt((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - lt = Restrictions.lt(propertyName, propertyValue); - } - addToCriteria(lt); - return this; - } - - /** - * Creates a "less than or equal to" Criterion based on the specified property name and value - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria le(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [le] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - Criterion le; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - le = Property.forName(propertyName).le((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - le = Restrictions.le(propertyName, propertyValue); - } - addToCriteria(le); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria idEquals(Object o) { - return idEq(o); - } - - public org.grails.datastore.mapping.query.api.Criteria isEmpty(String property) { - String propertyName = calculatePropertyName(property); - addToCriteria(Restrictions.isEmpty(propertyName)); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria isNotEmpty(String property) { - String propertyName = calculatePropertyName(property); - addToCriteria(Restrictions.isNotEmpty(propertyName)); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria isNull(String property) { - String propertyName = calculatePropertyName(property); - addToCriteria(Restrictions.isNull(propertyName)); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria isNotNull(String property) { - String propertyName = calculatePropertyName(property); - addToCriteria(Restrictions.isNotNull(propertyName)); - return this; - } - - /** - * Creates an "equals" Criterion based on the specified property name and value. Case-sensitive. - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria eq(String propertyName, Object propertyValue) { - return eq(propertyName, propertyValue, Collections.emptyMap()); - } - - public org.grails.datastore.mapping.query.api.Criteria idEq(Object o) { - return eq("id", o); - } - - /** - * Groovy moves the map to the first parameter if using the idiomatic form, e.g. - * eq 'firstName', 'Fred', ignoreCase: true. - * @param params optional map with customization parameters; currently only 'ignoreCase' is supported. - * @param propertyName - * @param propertyValue - * @return A Criterion instance - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.Criteria eq(Map params, String propertyName, Object propertyValue) { - return eq(propertyName, propertyValue, params); - } - - /** - * Creates an "equals" Criterion based on the specified property name and value. - * Supports case-insensitive search if the params map contains true - * under the 'ignoreCase' key. - * @param propertyName The property name - * @param propertyValue The property value - * @param params optional map with customization parameters; currently only 'ignoreCase' is supported. - * - * @return A Criterion instance - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.Criteria eq(String propertyName, Object propertyValue, Map params) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [eq] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - Criterion eq; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - eq = Property.forName(propertyName).eq((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - eq = Restrictions.eq(propertyName, propertyValue); - } - if (params != null && (eq instanceof SimpleExpression)) { - Object ignoreCase = params.get("ignoreCase"); - if (ignoreCase instanceof Boolean && (Boolean)ignoreCase) { - eq = ((SimpleExpression)eq).ignoreCase(); - } - } - addToCriteria(eq); - return this; - } - - /** - * Applies a sql restriction to the results to allow something like: -

    -       def results = Person.withCriteria {
    -           sqlRestriction "char_length(first_name) <= 4"
    -       }
    -      
    - * - * @param sqlRestriction the sql restriction - * @return a Criteria instance - */ - public org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sqlRestriction) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sqlRestriction] with value [" + - sqlRestriction + "] not allowed here.")); - } - return sqlRestriction(sqlRestriction, Collections.EMPTY_LIST); - } - - /** - * Applies a sql restriction to the results to allow something like: -
    -       def results = Person.withCriteria {
    -           sqlRestriction "char_length(first_name) < ? AND char_length(first_name) > ?", [4, 9]
    -       }
    -      
    - * - * @param sqlRestriction the sql restriction - * @param values jdbc parameters - * @return a Criteria instance - */ - public org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sqlRestriction, List values) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sqlRestriction] with value [" + - sqlRestriction + "] not allowed here.")); - } - final int numberOfParameters = values.size(); - - final Type[] typesArray = new Type[numberOfParameters]; - final Object[] valuesArray = new Object[numberOfParameters]; - - if (numberOfParameters > 0) { - final TypeHelper typeHelper = sessionFactory.getTypeHelper(); - for (int i = 0; i < typesArray.length; i++) { - final Object value = values.get(i); - typesArray[i] = typeHelper.basic(value.getClass()); - valuesArray[i] = value; - } - } - addToCriteria(Restrictions.sqlRestriction(sqlRestriction, valuesArray, typesArray)); - return this; - } - - /** - * Creates a Criterion with from the specified property name and "like" expression - * @param propertyName The property name - * @param propertyValue The like value - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria like(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [like] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - addToCriteria(Restrictions.like(propertyName, propertyValue)); - return this; - } - - /** - * Creates a Criterion with from the specified property name and "rlike" (a regular expression version of "like") expression - * @param propertyName The property name - * @param propertyValue The ilike value - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria rlike(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [rlike] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - addToCriteria(new RlikeExpression(propertyName, propertyValue)); - return this; - } - - /** - * Creates a Criterion with from the specified property name and "ilike" (a case sensitive version of "like") expression - * @param propertyName The property name - * @param propertyValue The ilike value - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria ilike(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [ilike] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - addToCriteria(Restrictions.ilike(propertyName, propertyValue)); - return this; - } - - /** - * Applys a "in" contrain on the specified property - * @param propertyName The property name - * @param values A collection of values - * - * @return A Criterion instance - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.Criteria in(String propertyName, Collection values) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [in] with propertyName [" + - propertyName + "] and values [" + values + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.in(propertyName, values == null ? Collections.EMPTY_LIST : values)); - return this; - } - - /** - * Delegates to in as in is a Groovy keyword - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.Criteria inList(String propertyName, Collection values) { - return in(propertyName, values); - } - - /** - * Delegates to in as in is a Groovy keyword - */ - public org.grails.datastore.mapping.query.api.Criteria inList(String propertyName, Object[] values) { - return in(propertyName, values); - } - - /** - * Applys a "in" contrain on the specified property - * @param propertyName The property name - * @param values A collection of values - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria in(String propertyName, Object[] values) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [in] with propertyName [" + - propertyName + "] and values [" + values + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.in(propertyName, values)); - return this; - } - - /** - * Orders by the specified property name (defaults to ascending) - * - * @param propertyName The property name to order by - * @return A Order instance - */ - public org.grails.datastore.mapping.query.api.Criteria order(String propertyName) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("Call to [order] with propertyName [" + - propertyName + "]not allowed here.")); - } - propertyName = calculatePropertyName(propertyName); - Order o = Order.asc(propertyName); - if (paginationEnabledList) { - orderEntries.add(o); - } - else { - criteria.addOrder(o); - } - return this; - } - - /** - * Orders by the specified property name (defaults to ascending) - * - * @param o The property name to order by - * @return A Order instance - */ - public org.grails.datastore.mapping.query.api.Criteria order(Order o) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("Call to [order] not allowed here.")); - } - if (paginationEnabledList) { - orderEntries.add(o); - } - else { - criteria.addOrder(o); - } - return this; - } - - /** - * Orders by the specified property name and direction - * - * @param propertyName The property name to order by - * @param direction Either "asc" for ascending or "desc" for descending - * - * @return A Order instance - */ - public org.grails.datastore.mapping.query.api.Criteria order(String propertyName, String direction) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("Call to [order] with propertyName [" + - propertyName + "]not allowed here.")); - } - propertyName = calculatePropertyName(propertyName); - Order o; - if (direction.equalsIgnoreCase(ORDER_DESCENDING)) { - o = Order.desc(propertyName); - } - else { - o = Order.asc(propertyName); - } - if (paginationEnabledList) { - orderEntries.add(o); - } - else { - criteria.addOrder(o); - } - return this; - } - - /** - * Creates a Criterion that contrains a collection property by size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria sizeEq(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeEq] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeEq(propertyName, size)); - return this; - } - - /** - * Creates a Criterion that contrains a collection property to be greater than the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria sizeGt(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeGt] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeGt(propertyName, size)); - return this; - } - - /** - * Creates a Criterion that contrains a collection property to be greater than or equal to the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria sizeGe(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeGe] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeGe(propertyName, size)); - return this; - } - - /** - * Creates a Criterion that contrains a collection property to be less than or equal to the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria sizeLe(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeLe] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeLe(propertyName, size)); - return this; - } - - /** - * Creates a Criterion that contrains a collection property to be less than to the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria sizeLt(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeLt] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeLt(propertyName, size)); - return this; - } - - /** - * Creates a Criterion that contrains a collection property to be not equal to the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria sizeNe(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeNe] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeNe(propertyName, size)); - return this; - } - - /** - * Creates a "not equal" Criterion based on the specified property name and value - * @param propertyName The property name - * @param propertyValue The property value - * @return The criterion object - */ - public org.grails.datastore.mapping.query.api.Criteria ne(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [ne] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - addToCriteria(Restrictions.ne(propertyName, propertyValue)); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria notEqual(String propertyName, Object propertyValue) { - return ne(propertyName, propertyValue); - } - - /** - * Creates a "between" Criterion based on the property name and specified lo and hi values - * @param propertyName The property name - * @param lo The low value - * @param hi The high value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria between(String propertyName, Object lo, Object hi) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [between] with propertyName [" + - propertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.between(propertyName, lo, hi)); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria gte(String s, Object o) { - return ge(s, o); - } - - private boolean validateSimpleExpression() { - return criteria != null; - } - - @SuppressWarnings("rawtypes") - @Override - public Object invokeMethod(String name, Object obj) { - Object[] args = obj.getClass().isArray() ? (Object[])obj : new Object[]{obj}; - - if (paginationEnabledList && SET_RESULT_TRANSFORMER_CALL.equals(name) && args.length == 1 && - args[0] instanceof ResultTransformer) { - resultTransformer = (ResultTransformer) args[0]; - return null; - } - - if (isCriteriaConstructionMethod(name, args)) { - if (criteria != null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - - if (name.equals(GET_CALL)) { - uniqueResult = true; - } - else if (name.equals(SCROLL_CALL)) { - scroll = true; - } - else if (name.equals(COUNT_CALL)) { - count = true; - } - else if (name.equals(LIST_DISTINCT_CALL)) { - resultTransformer = CriteriaSpecification.DISTINCT_ROOT_ENTITY; - } - - createCriteriaInstance(); - - // Check for pagination params - if (name.equals(LIST_CALL) && args.length == 2) { - paginationEnabledList = true; - orderEntries = new ArrayList(); - invokeClosureNode(args[1]); - } - else { - invokeClosureNode(args[0]); - } - - if (resultTransformer != null) { - criteria.setResultTransformer(resultTransformer); - } - Object result; - if (!uniqueResult) { - if (scroll) { - result = criteria.scroll(); - } - else if (count) { - criteria.setProjection(Projections.rowCount()); - result = criteria.uniqueResult(); - } - else if (paginationEnabledList) { - // Calculate how many results there are in total. This has been - // moved to before the 'list()' invocation to avoid any "ORDER - // BY" clause added by 'populateArgumentsForCriteria()', otherwise - // an exception is thrown for non-string sort fields (GRAILS-2690). - criteria.setFirstResult(0); - criteria.setMaxResults(Integer.MAX_VALUE); - - // Restore the previous projection, add settings for the pagination parameters, - // and then execute the query. - if (projectionList != null && projectionList.getLength() > 0) { - criteria.setProjection(projectionList); - } else { - criteria.setProjection(null); - } - for (Order orderEntry : orderEntries) { - criteria.addOrder(orderEntry); - } - if (resultTransformer == null) { - criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY); - } - else if (paginationEnabledList) { - // relevant to GRAILS-5692 - criteria.setResultTransformer(resultTransformer); - } - // GRAILS-7324 look if we already have association to sort by - Map argMap = (Map)args[0]; - final String sort = (String) argMap.get(GrailsHibernateUtil.ARGUMENT_SORT); - if (sort != null) { - boolean ignoreCase = true; - Object caseArg = argMap.get(GrailsHibernateUtil.ARGUMENT_IGNORE_CASE); - if (caseArg instanceof Boolean) { - ignoreCase = (Boolean) caseArg; - } - final String orderParam = (String) argMap.get(GrailsHibernateUtil.ARGUMENT_ORDER); - final String order = GrailsHibernateUtil.ORDER_DESC.equalsIgnoreCase(orderParam) ? - GrailsHibernateUtil.ORDER_DESC : GrailsHibernateUtil.ORDER_ASC; - int lastPropertyPos = sort.lastIndexOf('.'); - String associationForOrdering = lastPropertyPos >= 0 ? sort.substring(0, lastPropertyPos) : null; - if (associationForOrdering != null && aliasMap.containsKey(associationForOrdering)) { - addOrder(criteria, aliasMap.get(associationForOrdering) + "." + sort.substring(lastPropertyPos + 1), - order, ignoreCase); - // remove sort from arguments map to exclude from default processing. - @SuppressWarnings("unchecked") Map argMap2 = new HashMap(argMap); - argMap2.remove(GrailsHibernateUtil.ARGUMENT_SORT); - argMap = argMap2; - } - } - GrailsHibernateUtil.populateArgumentsForCriteria(grailsApplication, targetClass, criteria, argMap, conversionService); - GrailsHibernateTemplate ght = new GrailsHibernateTemplate(sessionFactory, grailsApplication); - PagedResultList pagedRes = new PagedResultList(ght, criteria); - result = pagedRes; - } - else { - result = criteria.list(); - } - } - else { - result = GrailsHibernateUtil.unwrapIfProxy(criteria.uniqueResult()); - } - if (!participate) { - hibernateSession.close(); - } - return result; - } - - if (criteria == null) createCriteriaInstance(); - - MetaMethod metaMethod = getMetaClass().getMetaMethod(name, args); - if (metaMethod != null) { - return metaMethod.invoke(this, args); - } - - metaMethod = criteriaMetaClass.getMetaMethod(name, args); - if (metaMethod != null) { - return metaMethod.invoke(criteria, args); - } - metaMethod = criteriaMetaClass.getMetaMethod(GrailsClassUtils.getSetterName(name), args); - if (metaMethod != null) { - return metaMethod.invoke(criteria, args); - } - - if (isAssociationQueryMethod(args) || isAssociationQueryWithJoinSpecificationMethod(args)) { - final boolean hasMoreThanOneArg = args.length > 1; - Object callable = hasMoreThanOneArg ? args[1] : args[0]; - int joinType = hasMoreThanOneArg ? (Integer)args[0] : CriteriaSpecification.INNER_JOIN; - - if (name.equals(AND) || name.equals(OR) || name.equals(NOT)) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - - logicalExpressionStack.add(new LogicalExpression(name)); - invokeClosureNode(callable); - - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - addToCriteria(logicalExpression.toCriterion()); - - return name; - } - - if (name.equals(PROJECTIONS) && args.length == 1 && (args[0] instanceof Closure)) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - - projectionList = Projections.projectionList(); - invokeClosureNode(callable); - - if (projectionList != null && projectionList.getLength() > 0) { - criteria.setProjection(projectionList); - } - - return name; - } - - final PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(targetClass, name); - if (pd != null && pd.getReadMethod() != null) { - ClassMetadata meta = sessionFactory.getClassMetadata(targetClass); - Type type = meta.getPropertyType(name); - if (type.isAssociationType()) { - String otherSideEntityName = - ((AssociationType) type).getAssociatedEntityName((SessionFactoryImplementor) sessionFactory); - Class oldTargetClass = targetClass; - targetClass = sessionFactory.getClassMetadata(otherSideEntityName).getMappedClass(EntityMode.POJO); - if (targetClass.equals(oldTargetClass) && !hasMoreThanOneArg) { - joinType = CriteriaSpecification.LEFT_JOIN; // default to left join if joining on the same table - } - associationStack.add(name); - final String associationPath = getAssociationPath(); - createAliasIfNeccessary(name, associationPath,joinType); - // the criteria within an association node are grouped with an implicit AND - logicalExpressionStack.add(new LogicalExpression(AND)); - invokeClosureNode(callable); - aliasStack.remove(aliasStack.size() - 1); - if (!aliasInstanceStack.isEmpty()) { - aliasInstanceStack.remove(aliasInstanceStack.size() - 1); - } - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - if (!logicalExpression.args.isEmpty()) { - addToCriteria(logicalExpression.toCriterion()); - } - associationStack.remove(associationStack.size()-1); - targetClass = oldTargetClass; - - return name; - } - if (type instanceof EmbeddedComponentType) { - associationStack.add(name); - logicalExpressionStack.add(new LogicalExpression(AND)); - Class oldTargetClass = targetClass; - targetClass = pd.getPropertyType(); - invokeClosureNode(callable); - targetClass = oldTargetClass; - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - if (!logicalExpression.args.isEmpty()) { - addToCriteria(logicalExpression.toCriterion()); - } - associationStack.remove(associationStack.size()-1); - return name; - } - } - } - else if (args.length == 1 && args[0] != null) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - - Object value = args[0]; - Criterion c = null; - if (name.equals(ID_EQUALS)) { - return eq("id", value); - } - - if (name.equals(IS_NULL) || - name.equals(IS_NOT_NULL) || - name.equals(IS_EMPTY) || - name.equals(IS_NOT_EMPTY)) { - if (!(value instanceof String)) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] with value [" + - value + "] requires a String value.")); - } - String propertyName = calculatePropertyName((String)value); - if (name.equals(IS_NULL)) { - c = Restrictions.isNull(propertyName); - } - else if (name.equals(IS_NOT_NULL)) { - c = Restrictions.isNotNull(propertyName); - } - else if (name.equals(IS_EMPTY)) { - c = Restrictions.isEmpty(propertyName); - } - else if (name.equals(IS_NOT_EMPTY)) { - c = Restrictions.isNotEmpty(propertyName); - } - } - - if (c != null) { - return addToCriteria(c); - } - } - - throw new MissingMethodException(name, getClass(), args); - } - - private boolean isAssociationQueryMethod(Object[] args) { - return args.length == 1 && args[0] instanceof Closure; - } - - private boolean isAssociationQueryWithJoinSpecificationMethod(Object[] args) { - return args.length == 2 && (args[0] instanceof Number) && (args[1] instanceof Closure); - } - - @SuppressWarnings("unused") - private void addToCurrentOrAliasedCriteria(Criterion criterion) { - if (!aliasInstanceStack.isEmpty()) { - Criteria c = aliasInstanceStack.get(aliasInstanceStack.size()-1); - c.add(criterion); - } - else { - criteria.add(criterion); - } - } - - private void createAliasIfNeccessary(String associationName, String associationPath, int joinType) { - String newAlias; - if (aliasMap.containsKey(associationPath)) { - newAlias = aliasMap.get(associationPath); - } - else { - aliasCount++; - newAlias = associationName + ALIAS + aliasCount; - aliasMap.put(associationPath, newAlias); - aliasInstanceStack.add(criteria.createAlias(associationPath, newAlias, joinType)); - } - aliasStack.add(newAlias); - } - - private String getAssociationPath() { - StringBuilder fullPath = new StringBuilder(); - for (Object anAssociationStack : associationStack) { - String propertyName = (String) anAssociationStack; - if (fullPath.length() > 0) fullPath.append("."); - fullPath.append(propertyName); - } - return fullPath.toString(); - } - - private boolean isCriteriaConstructionMethod(String name, Object[] args) { - return (name.equals(LIST_CALL) && args.length == 2 && args[0] instanceof Map && args[1] instanceof Closure) || - (name.equals(ROOT_CALL) || - name.equals(ROOT_DO_CALL) || - name.equals(LIST_CALL) || - name.equals(LIST_DISTINCT_CALL) || - name.equals(GET_CALL) || - name.equals(COUNT_CALL) || - name.equals(SCROLL_CALL) && args.length == 1 && args[0] instanceof Closure); - } - - public Criteria buildCriteria(Closure criteriaClosure) { - createCriteriaInstance(); - criteriaClosure.setDelegate(this); - criteriaClosure.call(); - return criteria; - } - - private void createCriteriaInstance() { - if (TransactionSynchronizationManager.hasResource(sessionFactory)) { - participate = true; - hibernateSession = ((SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory)).getSession(); - } - else { - hibernateSession = sessionFactory.openSession(); - } - - criteria = hibernateSession.createCriteria(targetClass); - GrailsHibernateUtil.cacheCriteriaByMapping(grailsApplication, targetClass, criteria); - criteriaMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(criteria.getClass()); - } - - private void invokeClosureNode(Object args) { - Closure callable = (Closure)args; - callable.setDelegate(this); - callable.setResolveStrategy(Closure.DELEGATE_FIRST); - callable.call(); - } - - /** - * Throws a runtime exception where necessary to ensure the session gets closed - */ - private void throwRuntimeException(RuntimeException t) { - closeSessionFollowingException(); - throw t; - } - - private void closeSessionFollowingException() { - if (hibernateSession != null && hibernateSession.isOpen() && !participate) { - hibernateSession.close(); - } - criteria = null; - } - - /** - * adds and returns the given criterion to the currently active criteria set. - * this might be either the root criteria or a currently open - * LogicalExpression. - */ - private Criterion addToCriteria(Criterion c) { - if (!logicalExpressionStack.isEmpty()) { - logicalExpressionStack.get(logicalExpressionStack.size() - 1).args.add(c); - } - else { - criteria.add(c); - } - return c; - } - - /** - * instances of this class are pushed onto the logicalExpressionStack - * to represent all the unfinished "and", "or", and "not" expressions. - */ - private class LogicalExpression { - final Object name; - final List args = new ArrayList(); - - LogicalExpression(Object name) { - this.name = name; - } - - Criterion toCriterion() { - if (name.equals(NOT)) { - switch (args.size()) { - case 0: - throwRuntimeException(new IllegalArgumentException("Logical expression [not] must contain at least 1 expression")); - return null; - - case 1: - return Restrictions.not(args.get(0)); - - default: - // treat multiple sub-criteria as an implicit "OR" - return Restrictions.not(buildJunction(Restrictions.disjunction(), args)); - } - } - - if (name.equals(AND)) { - return buildJunction(Restrictions.conjunction(), args); - } - - if (name.equals(OR)) { - return buildJunction(Restrictions.disjunction(), args); - } - - throwRuntimeException(new IllegalStateException("Logical expression [" + name + "] not handled!")); - return null; - } - - // add the Criterion objects in the given list to the given junction. - Junction buildJunction(Junction junction, List criterions) { - for (Criterion c : criterions) { - junction.add(c); - } - - return junction; - } - } - - /** - * Add order directly to criteria. - */ - private static void addOrder(Criteria c, String sort, String order, boolean ignoreCase) { - if (GrailsHibernateUtil.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) ); - } - } - - /* - * Define constants which may be used inside of criteria queries - * to refer to standard Hibernate Type instances. - */ - public static final Type BOOLEAN = StandardBasicTypes.BOOLEAN; - public static final Type YES_NO = StandardBasicTypes.YES_NO; - public static final Type BYTE = StandardBasicTypes.BYTE; - public static final Type CHARACTER = StandardBasicTypes.CHARACTER; - public static final Type SHORT = StandardBasicTypes.SHORT; - public static final Type INTEGER = StandardBasicTypes.INTEGER; - public static final Type LONG = StandardBasicTypes.LONG; - public static final Type FLOAT = StandardBasicTypes.FLOAT; - public static final Type DOUBLE = StandardBasicTypes.DOUBLE; - public static final Type BIG_DECIMAL = StandardBasicTypes.BIG_DECIMAL; - public static final Type BIG_INTEGER = StandardBasicTypes.BIG_INTEGER; - public static final Type STRING = StandardBasicTypes.STRING; - public static final Type NUMERIC_BOOLEAN = StandardBasicTypes.NUMERIC_BOOLEAN; - public static final Type TRUE_FALSE = StandardBasicTypes.TRUE_FALSE; - public static final Type URL = StandardBasicTypes.URL; - public static final Type TIME = StandardBasicTypes.TIME; - public static final Type DATE = StandardBasicTypes.DATE; - public static final Type TIMESTAMP = StandardBasicTypes.TIMESTAMP; - public static final Type CALENDAR = StandardBasicTypes.CALENDAR; - public static final Type CALENDAR_DATE = StandardBasicTypes.CALENDAR_DATE; - public static final Type CLASS = StandardBasicTypes.CLASS; - public static final Type LOCALE = StandardBasicTypes.LOCALE; - public static final Type CURRENCY = StandardBasicTypes.CURRENCY; - public static final Type TIMEZONE = StandardBasicTypes.TIMEZONE; - public static final Type UUID_BINARY = StandardBasicTypes.UUID_BINARY; - public static final Type UUID_CHAR = StandardBasicTypes.UUID_CHAR; - public static final Type BINARY = StandardBasicTypes.BINARY; - public static final Type WRAPPER_BINARY = StandardBasicTypes.WRAPPER_BINARY; - public static final Type IMAGE = StandardBasicTypes.IMAGE; - public static final Type BLOB = StandardBasicTypes.BLOB; - public static final Type MATERIALIZED_BLOB = StandardBasicTypes.MATERIALIZED_BLOB; - public static final Type WRAPPER_MATERIALIZED_BLOB = StandardBasicTypes.WRAPPER_MATERIALIZED_BLOB; - public static final Type CHAR_ARRAY = StandardBasicTypes.CHAR_ARRAY; - public static final Type CHARACTER_ARRAY = StandardBasicTypes.CHARACTER_ARRAY; - public static final Type TEXT = StandardBasicTypes.TEXT; - public static final Type CLOB = StandardBasicTypes.CLOB; - public static final Type MATERIALIZED_CLOB = StandardBasicTypes.MATERIALIZED_CLOB; - public static final Type WRAPPER_CHARACTERS_CLOB = StandardBasicTypes.WRAPPER_CHARACTERS_CLOB; - public static final Type CHARACTERS_CLOB = StandardBasicTypes.CHARACTERS_CLOB; - public static final Type SERIALIZABLE = StandardBasicTypes.SERIALIZABLE; -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/PagedResultList.java b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/PagedResultList.java deleted file mode 100644 index b8f2e304c..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/PagedResultList.java +++ /dev/null @@ -1,201 +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 grails.orm; - -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.sql.SQLException; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.criterion.Projections; -import org.hibernate.impl.CriteriaImpl; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * A result list for Criteria list calls, which is aware of the totalCount for - * the paged result. - * - * @author Siegfried Puchbauer - * @since 1.0 - */ -@SuppressWarnings({"unchecked","rawtypes"}) -public class PagedResultList implements List, Serializable { - - private static final long serialVersionUID = -5820655628956173929L; - - protected List list; - - protected int totalCount = Integer.MIN_VALUE; - - private transient GrailsHibernateTemplate hibernateTemplate; - private final Criteria criteria; - - public PagedResultList(GrailsHibernateTemplate template, Criteria crit) { - list = crit.list(); - criteria = crit; - hibernateTemplate = template; - } - - public int size() { - return list.size(); - } - - public boolean isEmpty() { - return list.isEmpty(); - } - - public boolean contains(Object o) { - return list.contains(o); - } - - public Iterator iterator() { - return list.iterator(); - } - - public Object[] toArray() { - return list.toArray(); - } - - public Object[] toArray(Object[] objects) { - return list.toArray(objects); - } - - public boolean add(Object o) { - return list.add(o); - } - - public boolean remove(Object o) { - return list.remove(o); - } - - public boolean containsAll(Collection collection) { - return list.containsAll(collection); - } - - public boolean addAll(Collection collection) { - return list.addAll(collection); - } - - public boolean addAll(int i, Collection collection) { - return list.addAll(i, collection); - } - - public boolean removeAll(Collection collection) { - return list.removeAll(collection); - } - - public boolean retainAll(Collection collection) { - return list.retainAll(collection); - } - - public void clear() { - list.clear(); - } - - @Override - public boolean equals(Object o) { - return list.equals(o); - } - - @Override - public int hashCode() { - return list.hashCode(); - } - - public Object get(int i) { - return list.get(i); - } - - public Object set(int i, Object o) { - return list.set(i, o); - } - - public void add(int i, Object o) { - list.add(i, o); - } - - public Object remove(int i) { - return list.remove(i); - } - - public int indexOf(Object o) { - return list.indexOf(o); - } - - public int lastIndexOf(Object o) { - return list.lastIndexOf(o); - } - - public ListIterator listIterator() { - return list.listIterator(); - } - - public ListIterator listIterator(int i) { - return list.listIterator(i); - } - - public List subList(int i, int i1) { - return list.subList(i, i1); - } - - public int getTotalCount() { - if (totalCount == Integer.MIN_VALUE) { - totalCount = (Integer)hibernateTemplate.execute(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException, SQLException { - CriteriaImpl impl = (CriteriaImpl) criteria; - Criteria totalCriteria = session.createCriteria(impl.getEntityOrClassName()); - hibernateTemplate.applySettings(totalCriteria); - - Iterator iterator = impl.iterateExpressionEntries(); - while (iterator.hasNext()) { - CriteriaImpl.CriterionEntry entry = (CriteriaImpl.CriterionEntry) iterator.next(); - totalCriteria.add(entry.getCriterion()); - } - Iterator subcriteriaIterator = impl.iterateSubcriteria(); - while (subcriteriaIterator.hasNext()) { - CriteriaImpl.Subcriteria sub = (CriteriaImpl.Subcriteria) subcriteriaIterator.next(); - totalCriteria.createAlias(sub.getPath(), sub.getAlias(), sub.getJoinType(), sub.getWithClause()); - } - totalCriteria.setProjection(impl.getProjection()); - totalCriteria.setProjection(Projections.rowCount()); - return ((Number)totalCriteria.uniqueResult()).intValue(); - } - }); - } - return totalCount; - } - - public void setTotalCount(int totalCount) { - this.totalCount = totalCount; - } - - private void writeObject(ObjectOutputStream out) throws IOException { - - // find the total count if it hasn't been done yet so when this is deserialized - // the null GrailsHibernateTemplate won't be an issue - getTotalCount(); - - out.defaultWriteObject(); - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/RlikeExpression.java b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/RlikeExpression.java deleted file mode 100644 index 852aec154..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/RlikeExpression.java +++ /dev/null @@ -1,79 +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 grails.orm; - -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.criterion.CriteriaQuery; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.MatchMode; -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.MySQLDialect; -import org.hibernate.dialect.Oracle8iDialect; -import org.hibernate.engine.TypedValue; - -/** - * Adds support for rlike to Hibernate in supported dialects. - * - * @author Graeme Rocher - * @since 1.1.1 - */ -public class RlikeExpression implements Criterion { - - private static final long serialVersionUID = -214329918050957956L; - - private final String propertyName; - private final Object value; - - public RlikeExpression(String propertyName, Object value) { - this.propertyName = propertyName; - this.value = value; - } - - public RlikeExpression(String propertyName, String value, MatchMode matchMode) { - this(propertyName, matchMode.toMatchString(value)); - } - - public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { - Dialect dialect = criteriaQuery.getFactory().getDialect(); - String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName); - if (columns.length != 1) { - throw new HibernateException("ilike may only be used with single-column properties"); - } - - if (dialect instanceof MySQLDialect) { - return columns[0] + " rlike ?"; - } - - if (isOracleDialect(dialect)) { - return " REGEXP_LIKE (" + columns[0] + ", ?)"; - } - - return columns[0] + " like ?"; - } - - private boolean isOracleDialect(Dialect dialect) { - return (dialect instanceof Oracle8iDialect); - } - - public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { - return new TypedValue[] { criteriaQuery.getTypedValue(criteria, propertyName, value.toString().toLowerCase()) }; - } - - @Override - public String toString() { - return propertyName + " rlike " + value; - } -} 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 deleted file mode 100644 index 7012c9c55..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/ConfigurableLocalSessionFactoryBean.java +++ /dev/null @@ -1,367 +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; - -import groovy.lang.GroovySystem; -import groovy.lang.MetaClassRegistry; - -import java.lang.reflect.Array; -import java.lang.reflect.InvocationTargetException; -import java.util.Map; - -import javax.naming.NameNotFoundException; - -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; -import org.hibernate.EntityMode; -import org.hibernate.HibernateException; -import org.hibernate.SessionFactory; -import org.hibernate.cache.CacheException; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.event.AutoFlushEventListener; -import org.hibernate.event.DeleteEventListener; -import org.hibernate.event.DirtyCheckEventListener; -import org.hibernate.event.EventListeners; -import org.hibernate.event.EvictEventListener; -import org.hibernate.event.FlushEntityEventListener; -import org.hibernate.event.FlushEventListener; -import org.hibernate.event.InitializeCollectionEventListener; -import org.hibernate.event.LoadEventListener; -import org.hibernate.event.LockEventListener; -import org.hibernate.event.MergeEventListener; -import org.hibernate.event.PersistEventListener; -import org.hibernate.event.PostCollectionRecreateEventListener; -import org.hibernate.event.PostCollectionRemoveEventListener; -import org.hibernate.event.PostCollectionUpdateEventListener; -import org.hibernate.event.PostDeleteEventListener; -import org.hibernate.event.PostInsertEventListener; -import org.hibernate.event.PostLoadEventListener; -import org.hibernate.event.PostUpdateEventListener; -import org.hibernate.event.PreCollectionRecreateEventListener; -import org.hibernate.event.PreCollectionRemoveEventListener; -import org.hibernate.event.PreCollectionUpdateEventListener; -import org.hibernate.event.PreDeleteEventListener; -import org.hibernate.event.PreInsertEventListener; -import org.hibernate.event.PreLoadEventListener; -import org.hibernate.event.PreUpdateEventListener; -import org.hibernate.event.RefreshEventListener; -import org.hibernate.event.ReplicateEventListener; -import org.hibernate.event.SaveOrUpdateEventListener; -import org.hibernate.metadata.ClassMetadata; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.orm.hibernate3.LocalSessionFactoryBean; - -/** - * A SessionFactory bean that allows the configuration class to - * be changed and customise for usage within Grails. - * - * @author Graeme Rocher - * @since 07-Jul-2005 - */ -public class ConfigurableLocalSessionFactoryBean extends - LocalSessionFactoryBean implements ApplicationContextAware { - - protected static final Logger LOG = LoggerFactory.getLogger(ConfigurableLocalSessionFactoryBean.class); - protected ClassLoader classLoader; - protected GrailsApplication grailsApplication; - protected Class configClass; - protected Class currentSessionContextClass; - protected HibernateEventListeners hibernateEventListeners; - protected ApplicationContext applicationContext; - protected boolean proxyIfReloadEnabled = true; - protected String sessionFactoryBeanName = "sessionFactory"; - protected String dataSourceName = GrailsDomainClassProperty.DEFAULT_DATA_SOURCE; - - /** - * @param proxyIfReloadEnabled Sets whether a proxy should be created if reload is enabled - */ - public void setProxyIfReloadEnabled(boolean proxyIfReloadEnabled) { - this.proxyIfReloadEnabled = proxyIfReloadEnabled; - } - - /** - * Sets class to be used for the Hibernate CurrentSessionContext. - * - * @param currentSessionContextClass An implementation of the CurrentSessionContext interface - */ - public void setCurrentSessionContextClass(Class currentSessionContextClass) { - this.currentSessionContextClass = currentSessionContextClass; - } - - /** - * Sets the class to be used for Hibernate Configuration. - * @param configClass A subclass of the Hibernate Configuration class - */ - public void setConfigClass(Class configClass) { - this.configClass = configClass; - } - - /** - * @return Returns the grailsApplication. - */ - public GrailsApplication getGrailsApplication() { - return grailsApplication; - } - - /** - * @param grailsApplication The grailsApplication to set. - */ - public void setGrailsApplication(GrailsApplication grailsApplication) { - this.grailsApplication = grailsApplication; - } - - /** - * Overrides default behaviour to allow for a configurable configuration class. - */ - @Override - protected Configuration newConfiguration() { - ClassLoader cl = classLoader != null ? classLoader : Thread.currentThread().getContextClassLoader(); - if (configClass == null) { - try { - configClass = cl.loadClass("org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration"); - } - catch (Throwable e) { - // probably not Java 5 or missing some annotation jars, use default - configClass = DefaultGrailsDomainConfiguration.class; - } - } - Object config = BeanUtils.instantiateClass(configClass); - if (config instanceof GrailsDomainConfiguration) { - GrailsDomainConfiguration grailsConfig = (GrailsDomainConfiguration)config; - grailsConfig.setGrailsApplication(grailsApplication); - grailsConfig.setSessionFactoryBeanName(sessionFactoryBeanName); - grailsConfig.setDataSourceName(dataSourceName); - } - if (currentSessionContextClass != null) { - ((Configuration)config).setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS, currentSessionContextClass.getName()); - // don't allow Spring's LocaalSessionFactoryBean to override setting - setExposeTransactionAwareSessionFactory(false); - } - return (Configuration)config; - } - - @Override - public void setBeanClassLoader(ClassLoader beanClassLoader) { - classLoader = beanClassLoader; - super.setBeanClassLoader(beanClassLoader); - } - - @Override - public void afterPropertiesSet() throws Exception { - Thread thread = Thread.currentThread(); - ClassLoader cl = thread.getContextClassLoader(); - try { - thread.setContextClassLoader(classLoader); - super.afterPropertiesSet(); - } finally { - thread.setContextClassLoader(cl); - } - } - - @Override - protected SessionFactory newSessionFactory(Configuration configuration) throws HibernateException { - try { - - SessionFactory sf = super.newSessionFactory(configuration); - - if (!grails.util.Environment.getCurrent().isReloadEnabled() || !proxyIfReloadEnabled) { - return sf; - } - - // if reloading is enabled in this environment then we need to use a SessionFactoryProxy instance - SessionFactoryProxy sfp = new SessionFactoryProxy(); - String suffix = dataSourceName.equals(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE) ? "" : '_' + dataSourceName; - SessionFactoryHolder sessionFactoryHolder = applicationContext.getBean( - SessionFactoryHolder.BEAN_ID + suffix, SessionFactoryHolder.class); - sessionFactoryHolder.setSessionFactory(sf); - sfp.setApplicationContext(applicationContext); - sfp.setCurrentSessionContextClass(currentSessionContextClass); - sfp.setTargetBean(SessionFactoryHolder.BEAN_ID + suffix); - sfp.afterPropertiesSet(); - return sfp; - } - catch (HibernateException e) { - Throwable cause = e.getCause(); - if (isCacheConfigurationError(cause)) { - LOG.error("There was an error configuring the Hibernate second level cache: " + getCauseMessage(e)); - LOG.error("This is normally due to one of two reasons. Either you have incorrectly specified the cache provider class name in [DataSource.groovy] or you do not have the cache provider on your classpath (eg. runtime (\"net.sf.ehcache:ehcache:1.6.1\"))"); - if (grails.util.Environment.isDevelopmentMode()) { - System.exit(1); - } - } - throw e; - } - } - - protected String getCauseMessage(HibernateException e) { - Throwable cause = e.getCause(); - if (cause instanceof InvocationTargetException) { - cause = ((InvocationTargetException)cause).getTargetException(); - } - return cause.getMessage(); - } - - protected boolean isCacheConfigurationError(Throwable cause) { - if (cause instanceof InvocationTargetException) { - cause = ((InvocationTargetException)cause).getTargetException(); - } - return cause != null && (cause instanceof CacheException); - } - - @Override - public void destroy() throws HibernateException { - if (grailsApplication.isWarDeployed()) { - MetaClassRegistry registry = GroovySystem.getMetaClassRegistry(); - Map classMetaData = getSessionFactory().getAllClassMetadata(); - for (Object o : classMetaData.values()) { - ClassMetadata classMetadata = (ClassMetadata) o; - Class mappedClass = classMetadata.getMappedClass(EntityMode.POJO); - registry.removeMetaClass(mappedClass); - } - } - - try { - super.destroy(); - } catch (HibernateException e) { - if (e.getCause() instanceof NameNotFoundException) { - LOG.debug(e.getCause().getMessage(), e); - } - else { - throw e; - } - } - } - - @Override - protected void postProcessConfiguration(Configuration config) throws HibernateException { - EventListeners listeners = config.getEventListeners(); - if (hibernateEventListeners != null && hibernateEventListeners.getListenerMap() != null) { - Map listenerMap = hibernateEventListeners.getListenerMap(); - addNewListenerToConfiguration(config, "auto-flush", AutoFlushEventListener.class, - listeners.getAutoFlushEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "merge", MergeEventListener.class, - listeners.getMergeEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "create", PersistEventListener.class, - listeners.getPersistEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "create-onflush", PersistEventListener.class, - listeners.getPersistOnFlushEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "delete", DeleteEventListener.class, - listeners.getDeleteEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "dirty-check", DirtyCheckEventListener.class, - listeners.getDirtyCheckEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "evict", EvictEventListener.class, - listeners.getEvictEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "flush", FlushEventListener.class, - listeners.getFlushEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "flush-entity", FlushEntityEventListener.class, - listeners.getFlushEntityEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "load", LoadEventListener.class, - listeners.getLoadEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "load-collection", InitializeCollectionEventListener.class, - listeners.getInitializeCollectionEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "lock", LockEventListener.class, - listeners.getLockEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "refresh", RefreshEventListener.class, - listeners.getRefreshEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "replicate", ReplicateEventListener.class, - listeners.getReplicateEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "save-update", SaveOrUpdateEventListener.class, - listeners.getSaveOrUpdateEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "save", SaveOrUpdateEventListener.class, - listeners.getSaveEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "update", SaveOrUpdateEventListener.class, - listeners.getUpdateEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "pre-load", PreLoadEventListener.class, - listeners.getPreLoadEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "pre-update", PreUpdateEventListener.class, - listeners.getPreUpdateEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "pre-delete", PreDeleteEventListener.class, - listeners.getPreDeleteEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "pre-insert", PreInsertEventListener.class, - listeners.getPreInsertEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "pre-collection-recreate", PreCollectionRecreateEventListener.class, - listeners.getPreCollectionRecreateEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "pre-collection-remove", PreCollectionRemoveEventListener.class, - listeners.getPreCollectionRemoveEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "pre-collection-update", PreCollectionUpdateEventListener.class, - listeners.getPreCollectionUpdateEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "post-load", PostLoadEventListener.class, - listeners.getPostLoadEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "post-update", PostUpdateEventListener.class, - listeners.getPostUpdateEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "post-delete", PostDeleteEventListener.class, - listeners.getPostDeleteEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "post-insert", PostInsertEventListener.class, - listeners.getPostInsertEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "post-commit-update", PostUpdateEventListener.class, - listeners.getPostCommitUpdateEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "post-commit-delete", PostDeleteEventListener.class, - listeners.getPostCommitDeleteEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "post-commit-insert", PostInsertEventListener.class, - listeners.getPostCommitInsertEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "post-collection-recreate", PostCollectionRecreateEventListener.class, - listeners.getPostCollectionRecreateEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "post-collection-remove", PostCollectionRemoveEventListener.class, - listeners.getPostCollectionRemoveEventListeners(), listenerMap); - addNewListenerToConfiguration(config, "post-collection-update", PostCollectionUpdateEventListener.class, - listeners.getPostCollectionUpdateEventListeners(), listenerMap); - } - // register workaround for GRAILS-8988 (do nullability checks for inserts in last PreInsertEventListener) - ClosureEventTriggeringInterceptor.addNullabilityCheckerPreInsertEventListener(listeners); - } - - @SuppressWarnings("unchecked") - protected void addNewListenerToConfiguration(final Configuration config, final String listenerType, - final Class klass, final T[] currentListeners, final Map newlistenerMap) { - - Object newListener = newlistenerMap.get(listenerType); - if (newListener == null) return; - - if (currentListeners != null && currentListeners.length > 0) { - T[] newListeners = (T[])Array.newInstance(klass, currentListeners.length + 1); - System.arraycopy(currentListeners, 0, newListeners, 0, currentListeners.length); - newListeners[currentListeners.length] = (T)newListener; - config.setListeners(listenerType, newListeners); - } - else { - config.setListener(listenerType, newListener); - } - } - - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - public void setHibernateEventListeners(final HibernateEventListeners listeners) { - hibernateEventListeners = listeners; - } - - public void setSessionFactoryBeanName(String name) { - sessionFactoryBeanName = name; - } - - public void setDataSourceName(String name) { - dataSourceName = name; - } -} 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 deleted file mode 100644 index 6765c1e8e..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventTriggeringInterceptor.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 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.codehaus.groovy.grails.orm.hibernate; - -import groovy.lang.GroovySystem; -import groovy.util.ConfigObject; - -import java.util.List; -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.datastore.mapping.engine.event.AbstractPersistenceEvent; -import org.grails.datastore.mapping.engine.event.ValidationEvent; -import org.hibernate.HibernateException; -import org.hibernate.event.PostDeleteEvent; -import org.hibernate.event.PostInsertEvent; -import org.hibernate.event.PostLoadEvent; -import org.hibernate.event.PostUpdateEvent; -import org.hibernate.event.PreDeleteEvent; -import org.hibernate.event.PreInsertEvent; -import org.hibernate.event.PreLoadEvent; -import org.hibernate.event.PreUpdateEvent; -import org.hibernate.event.SaveOrUpdateEvent; -import org.springframework.context.ApplicationEvent; - -/** - *

    Invokes closure events on domain entities such as beforeInsert, beforeUpdate and beforeDelete. - * - * @author Graeme Rocher - * @author Lari Hotari - * @author Burt Beckwith - * @since 2.0 - */ -public class EventTriggeringInterceptor extends AbstractEventTriggeringInterceptor { - - protected transient ConcurrentMap>, ClosureEventListener> eventListeners = - new ConcurrentHashMap>, ClosureEventListener>(); - - protected final GrailsDomainBinder domainBinder = new GrailsDomainBinder(); - - public EventTriggeringInterceptor(HibernateDatastore datastore, ConfigObject co) { - super(datastore); - - Object failOnErrorConfig = co.flatten().get("grails.gorm.failOnError"); - if (failOnErrorConfig instanceof List) { - failOnError = true; - failOnErrorPackages = (List)failOnErrorConfig; - } - else { - failOnError = DefaultTypeTransformation.castToBoolean(failOnErrorConfig); - } - } - - @Override - protected void onPersistenceEvent(final AbstractPersistenceEvent event) { - switch (event.getEventType()) { - case PreInsert: - if (onPreInsert((PreInsertEvent)event.getNativeEvent())) { - event.cancel(); - } - break; - case PostInsert: - onPostInsert((PostInsertEvent)event.getNativeEvent()); - break; - case PreUpdate: - if (onPreUpdate((PreUpdateEvent)event.getNativeEvent())) { - event.cancel(); - } - break; - case PostUpdate: - onPostUpdate((PostUpdateEvent)event.getNativeEvent()); - break; - case PreDelete: - if (onPreDelete((PreDeleteEvent)event.getNativeEvent())) { - event.cancel(); - } - break; - case PostDelete: - onPostDelete((PostDeleteEvent)event.getNativeEvent()); - break; - case PreLoad: - onPreLoad((PreLoadEvent)event.getNativeEvent()); - break; - case PostLoad: - onPostLoad((PostLoadEvent)event.getNativeEvent()); - break; - case SaveOrUpdate: - onSaveOrUpdate((SaveOrUpdateEvent)event.getNativeEvent()); - break; - case Validation: - onValidate((ValidationEvent)event); - break; - default: - throw new IllegalStateException("Unexpected EventType: " + event.getEventType()); - } - } - - public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException { - ClosureEventListener eventListener = findEventListener(event.getObject()); - if (eventListener != null) { - eventListener.onSaveOrUpdate(event); - } - } - - public void onPreLoad(PreLoadEvent event) { - Object entity = event.getEntity(); - GrailsHibernateUtil.ensureCorrectGroovyMetaClass(entity, entity.getClass()); - ClosureEventListener eventListener = findEventListener(entity); - if (eventListener != null) { - eventListener.onPreLoad(event); - } - } - - public void onPostLoad(PostLoadEvent event) { - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - eventListener.onPostLoad(event); - } - } - - public void onPostInsert(PostInsertEvent event) { - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - eventListener.onPostInsert(event); - } - } - - public boolean onPreInsert(PreInsertEvent event) { - boolean evict = false; - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - evict = eventListener.onPreInsert(event); - } - return evict; - } - - public boolean onPreUpdate(PreUpdateEvent event) { - boolean evict = false; - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - evict = eventListener.onPreUpdate(event); - } - return evict; - } - - public void onPostUpdate(PostUpdateEvent event) { - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - eventListener.onPostUpdate(event); - } - } - - public boolean onPreDelete(PreDeleteEvent event) { - boolean evict = false; - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - evict = eventListener.onPreDelete(event); - } - return evict; - } - - public void onPostDelete(PostDeleteEvent event) { - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - eventListener.onPostDelete(event); - } - } - - public void onValidate(ValidationEvent event) { - ClosureEventListener eventListener = findEventListener(event.getEntityObject()); - if (eventListener != null) { - eventListener.onValidate(event); - } - } - - protected ClosureEventListener findEventListener(Object entity) { - if (entity == null) return null; - Class clazz = entity.getClass(); - - SoftKey> key = new SoftKey>(clazz); - ClosureEventListener eventListener = eventListeners.get(key); - if (eventListener != null) { - return eventListener; - } - - Boolean shouldTrigger = cachedShouldTrigger.get(key); - if (shouldTrigger == null || shouldTrigger) { - synchronized(clazz) { - eventListener = eventListeners.get(key); - if (eventListener == null) { - shouldTrigger = (GroovySystem.getMetaClassRegistry().getMetaClass(entity.getClass()) != null && - (DomainClassArtefactHandler.isDomainClass(clazz) || AnnotationDomainClassArtefactHandler.isJPADomainClass(clazz)) && - isDefinedByCurrentDataStore(entity, domainBinder)); - if (shouldTrigger) { - eventListener = new ClosureEventListener(clazz, failOnError, failOnErrorPackages); - ClosureEventListener previous = eventListeners.putIfAbsent(key, eventListener); - if (previous != null) { - eventListener = previous; - } - } - cachedShouldTrigger.put(key, shouldTrigger); - } - } - } - return eventListener; - } - - /** - * {@inheritDoc} - * @see org.springframework.context.event.SmartApplicationListener#supportsEventType(java.lang.Class) - */ - public boolean supportsEventType(Class eventType) { - return AbstractPersistenceEvent.class.isAssignableFrom(eventType); - } - - protected List getDatasourceNames(GrailsDomainClass dc) { - return GrailsHibernateUtil.getDatasourceNames(dc); - } -} 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 deleted file mode 100644 index b26623870..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java +++ /dev/null @@ -1,68 +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; - -import java.util.Collection; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.hibernate.EntityMode; -import org.hibernate.MappingException; -import org.hibernate.SessionFactory; -import org.hibernate.engine.SessionFactoryImplementor; -import org.hibernate.metadata.ClassMetadata; -import org.hibernate.type.AssociationType; -import org.hibernate.type.Type; - -/** - * An implementation of the GrailsDomainClass interface that allows Classes - * mapped in Hibernate to integrate with Grails' validation, dynamic methods - * etc. seamlessly. - * - * @author Graeme Rocher - * @since 0.1 - */ -@SuppressWarnings("unchecked") -public class GrailsHibernateDomainClass extends AbstractGrailsHibernateDomainClass { - - /** - * Contructor to be used by all child classes to create a new instance - * and get the name right. - * - * @param clazz the Grails class - * @param sessionFactory The Hibernate SessionFactory instance - * @param sessionFactoryName - * @param application - * @param metaData The ClassMetaData for this class retrieved from the SF - */ - public GrailsHibernateDomainClass(Class clazz, SessionFactory sessionFactory, String sessionFactoryName, - GrailsApplication application, ClassMetadata metaData) { - super(clazz, sessionFactory, sessionFactoryName, application, metaData); - } - - protected void setRelatedClassType(GrailsHibernateDomainClassProperty prop, AssociationType assType, Type hibernateType) { - try { - String associatedEntity = assType.getAssociatedEntityName((SessionFactoryImplementor) getSessionFactory()); - ClassMetadata associatedMetaData = getSessionFactory().getClassMetadata(associatedEntity); - prop.setRelatedClassType(associatedMetaData.getMappedClass(EntityMode.POJO)); - } - catch (MappingException me) { - // other side must be a value object - if (hibernateType.isCollectionType()) { - prop.setRelatedClassType(Collection.class); - } - } - } -} 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 deleted file mode 100644 index 59db74fb6..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTemplate.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 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.codehaus.groovy.grails.orm.hibernate; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.Criteria; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.orm.hibernate3.HibernateTemplate; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -public class GrailsHibernateTemplate extends HibernateTemplate implements IHibernateTemplate { - private boolean osivReadOnly; - - public GrailsHibernateTemplate() { - initialize(null); - } - - public GrailsHibernateTemplate(SessionFactory sessionFactory, boolean allowCreate) { - super(sessionFactory, allowCreate); - initialize(null); - } - - public GrailsHibernateTemplate(SessionFactory sessionFactory) { - super(sessionFactory); - initialize(null); - } - - public GrailsHibernateTemplate(SessionFactory sessionFactory, GrailsApplication application) { - super(sessionFactory); - initialize(application); - } - - private void initialize(GrailsApplication application) { - setExposeNativeSession(true); - if (application != null) { - setCacheQueries(GrailsHibernateUtil.isCacheQueriesByDefault(application)); - this.osivReadOnly = GrailsHibernateUtil.isOsivReadonly(application); - } - } - - @Override - protected void prepareQuery(Query queryObject) { - super.prepareQuery(queryObject); - if(isCurrentTransactionReadOnly()) { - queryObject.setReadOnly(true); - } - } - - public void applySettings(Query queryObject) { - if (isExposeNativeSession()) { - prepareQuery(queryObject); - } - } - - @Override - protected void prepareCriteria(Criteria criteria) { - super.prepareCriteria(criteria); - if(isCurrentTransactionReadOnly()) { - criteria.setReadOnly(true); - } - } - - protected boolean isCurrentTransactionReadOnly() { - if(TransactionSynchronizationManager.hasResource(getSessionFactory())) { - if(TransactionSynchronizationManager.isActualTransactionActive()) { - return TransactionSynchronizationManager.isCurrentTransactionReadOnly(); - } else { - return osivReadOnly; - } - } else { - return false; - } - } - - public void applySettings(Criteria criteria) { - if (isExposeNativeSession()) { - prepareCriteria(criteria); - } - } - - @Override - protected void enableFilters(Session session) { - if(isCurrentTransactionReadOnly()) { - session.setDefaultReadOnly(true); - } - super.enableFilters(session); - } - - public boolean isOsivReadOnly() { - return osivReadOnly; - } - - public void setOsivReadOnly(boolean osivReadOnly) { - this.osivReadOnly = osivReadOnly; - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy deleted file mode 100644 index ab1831068..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2004-2010 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 - -import org.hibernate.FlushMode -import org.springframework.orm.hibernate3.HibernateTransactionManager -import org.springframework.orm.hibernate3.HibernateTransactionManager.HibernateTransactionObject -import org.springframework.transaction.TransactionDefinition - -/** - * Extends the standard class to always set the flush mode to manual when in a read-only transaction. - * - * @author Burt Beckwith - */ -class GrailsHibernateTransactionManager extends HibernateTransactionManager { - - @Override - protected void doBegin(Object transaction, TransactionDefinition definition) { - super.doBegin transaction, definition - - if (definition.isReadOnly()) { - // transaction is HibernateTransactionManager.HibernateTransactionObject private class instance - transaction.sessionHolder?.session?.with { - // always set to manual; the base class doesn't because the OSIVI has already registered a session - flushMode = FlushMode.MANUAL - // set session to load entities in read-only mode - defaultReadOnly = true - } - } - } -} 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 deleted file mode 100644 index f25d4f4c8..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateDatastore.java +++ /dev/null @@ -1,58 +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.codehaus.groovy.grails.orm.hibernate; - -import groovy.util.ConfigObject; - -import java.util.Map; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.model.MappingContext; -import org.hibernate.SessionFactory; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ConfigurableApplicationContext; - -/** - * Datastore implementation that uses a Hibernate SessionFactory underneath. - * - * @author Graeme Rocher - * @since 2.0 - */ -public class HibernateDatastore extends AbstractHibernateDatastore { - - public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config) { - super(mappingContext, sessionFactory, config); - } - - public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config, ApplicationContext applicationContext) { - super(mappingContext, sessionFactory, config, applicationContext); - } - - @Override - protected Session createSession(Map connectionDetails) { - return new HibernateSession(this, sessionFactory); - } - - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - super.setApplicationContext(applicationContext); - - if (applicationContext != null) { - // support for callbacks in domain classes - eventTriggeringInterceptor = new EventTriggeringInterceptor(this, config); - ((ConfigurableApplicationContext)applicationContext).addApplicationListener(eventTriggeringInterceptor); - } - } -} 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 deleted file mode 100644 index a79f98d27..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormEnhancer.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.codehaus.groovy.grails.orm.hibernate - -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 - -/** - * Extended GORM Enhancer that fills out the remaining GORM for Hibernate methods - * and implements string-based query support via HQL. - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class HibernateGormEnhancer extends AbstractHibernateGormEnhancer { - - HibernateGormEnhancer(HibernateDatastore datastore, PlatformTransactionManager transactionManager, GrailsApplication grailsApplication) { - super(datastore, transactionManager, grailsApplication) - } - - protected List 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 GormValidationApi getValidationApi(Class cls) { - new HibernateGormValidationApi(cls, (HibernateDatastore)datastore, classLoader) - } - - @Override - protected GormStaticApi getStaticApi(Class cls) { - new HibernateGormStaticApi(cls, (HibernateDatastore)datastore, getFinders(), classLoader, transactionManager) - } - - @Override - protected GormInstanceApi getInstanceApi(Class cls) { - new HibernateGormInstanceApi(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 deleted file mode 100644 index f73d6165e..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormInstanceApi.groovy +++ /dev/null @@ -1,277 +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 - -import groovy.transform.CompileStatic - -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.domain.GrailsDomainClassMappingContext -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.hibernate.SessionFactory -import org.hibernate.engine.EntityEntry -import org.hibernate.engine.SessionImplementor -import org.hibernate.proxy.HibernateProxy -import org.springframework.dao.DataAccessException - -/** - * The implementation of the GORM instance API contract for Hibernate. - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class HibernateGormInstanceApi extends AbstractHibernateGormInstanceApi { - - protected SavePersistentMethod saveMethod - protected MergePersistentMethod mergeMethod - protected GrailsHibernateTemplate hibernateTemplate - protected InstanceApiHelper instanceApiHelper - - HibernateGormInstanceApi(Class persistentClass, HibernateDatastore datastore, ClassLoader classLoader) { - super(persistentClass, datastore, classLoader) - - def mappingContext = datastore.mappingContext - if (mappingContext instanceof GrailsDomainClassMappingContext) { - GrailsDomainClassMappingContext domainClassMappingContext = (GrailsDomainClassMappingContext)mappingContext - def grailsApplication = domainClassMappingContext.getGrailsApplication() - 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) - cacheQueriesByDefault = GrailsHibernateUtil.isCacheQueriesByDefault(grailsApplication) - } - else { - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory) - } - instanceApiHelper = new InstanceApiHelper(hibernateTemplate) - } - - /** - * Checks whether a field is dirty - * - * @param instance The instance - * @param fieldName The name of the field - * - * @return true if the field is dirty - */ - boolean isDirty(D instance, String fieldName) { - SessionImplementor session = (SessionImplementor)sessionFactory.currentSession - def entry = findEntityEntry(instance, session) - if (!entry || !entry.loadedState) { - return false - } - - Object[] values = entry.persister.getPropertyValues(instance, session.entityMode) - int[] dirtyProperties = entry.persister.findDirty(values, entry.loadedState, instance, session) - if(!dirtyProperties) return false - int fieldIndex = entry.persister.propertyNames.findIndexOf { fieldName == it } - return fieldIndex in dirtyProperties - } - - /** - * Checks whether an entity is dirty - * - * @param instance The instance - * @return true if it is dirty - */ - boolean isDirty(D instance) { - SessionImplementor session = (SessionImplementor)sessionFactory.currentSession - def entry = findEntityEntry(instance, session) - if (!entry || !entry.loadedState) { - return false - } - - Object[] values = entry.persister.getPropertyValues(instance, session.entityMode) - def dirtyProperties = entry.persister.findDirty(values, entry.loadedState, instance, session) - return dirtyProperties != null - } - - /** - * Obtains a list of property names that are dirty - * - * @param instance The instance - * @return A list of property names that are dirty - */ - List getDirtyPropertyNames(D instance) { - SessionImplementor session = (SessionImplementor)sessionFactory.currentSession - def entry = findEntityEntry(instance, session) - if (!entry || !entry.loadedState) { - return [] - } - - Object[] values = entry.persister.getPropertyValues(instance, session.entityMode) - int[] dirtyProperties = entry.persister.findDirty(values, entry.loadedState, instance, session) - def names = [] - for (index in dirtyProperties) { - names << entry.persister.propertyNames[index] - } - names - } - - /** - * Gets the original persisted value of a field. - * - * @param fieldName The field name - * @return The original persisted value - */ - Object getPersistentValue(D instance, String fieldName) { - SessionImplementor session = (SessionImplementor)sessionFactory.currentSession - def entry = findEntityEntry(instance, session, false) - if (!entry || !entry.loadedState) { - return null - } - - int fieldIndex = entry.persister.propertyNames.findIndexOf { fieldName == it } - return fieldIndex == -1 ? null : entry.loadedState[fieldIndex] - } - - @Override - D lock(D instance) { - hibernateTemplate.lock(instance, LockMode.UPGRADE) - } - - @Override - D refresh(D instance) { - hibernateTemplate.refresh(instance) - return instance - } - - @Override - D save(D instance) { - if (saveMethod) { - return saveMethod.invoke(instance, "save", EMPTY_ARRAY) - } - return super.save(instance) - } - - D save(D instance, boolean validate) { - if (saveMethod) { - return saveMethod.invoke(instance, "save", [validate] as Object[]) - } - return super.save(instance, validate) - } - - @Override - D merge(D instance) { - if (mergeMethod) { - mergeMethod.invoke(instance, "merge", EMPTY_ARRAY) - } - else { - return super.merge(instance) - } - } - - @Override - D merge(D instance, Map params) { - if (mergeMethod) { - mergeMethod.invoke(instance, "merge", [params] as Object[]) - } - else { - return super.merge(instance, params) - } - } - - @Override - D save(D instance, Map params) { - if (saveMethod) { - return 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) { - def entry = session.persistenceContext.getEntry(instance) - if (!entry) { - return null - } - - if (forDirtyCheck && !entry.requiresDirtyCheck(instance) && entry.loadedState) { - return null - } - - 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 deleted file mode 100644 index 3481f9a78..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormStaticApi.groovy +++ /dev/null @@ -1,608 +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 - -import grails.orm.HibernateCriteriaBuilder -import groovy.transform.CompileStatic - -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.domain.GrailsDomainClassMappingContext -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.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.query.api.Criteria 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 -import org.springframework.orm.hibernate3.SessionFactoryUtils -import org.springframework.orm.hibernate3.SessionHolder -import org.springframework.transaction.PlatformTransactionManager -import org.springframework.transaction.support.TransactionSynchronizationManager - -/** - * The implementation of the GORM static method contract for Hibernate - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class HibernateGormStaticApi extends GormStaticApi { - protected static final EMPTY_ARRAY = [] as Object[] - - 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 boolean cacheQueriesByDefault = false - protected GrailsDomainBinder grailsDomainBinder = new GrailsDomainBinder() - - HibernateGormStaticApi(Class persistentClass, HibernateDatastore datastore, List finders, - ClassLoader classLoader, PlatformTransactionManager transactionManager) { - super(persistentClass, datastore, finders) - - super.transactionManager = transactionManager - this.classLoader = classLoader - sessionFactory = datastore.getSessionFactory() - conversionService = datastore.mappingContext.conversionService - - identityType = persistentEntity.identity?.type - - def mappingContext = datastore.mappingContext - if (mappingContext instanceof GrailsDomainClassMappingContext) { - GrailsDomainClassMappingContext domainClassMappingContext = (GrailsDomainClassMappingContext)mappingContext - grailsApplication = domainClassMappingContext.getGrailsApplication() - - 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) - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, grailsApplication) - hibernateTemplate.setCacheQueries(cacheQueriesByDefault) - } else { - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory) - } - - executeQueryMethod = new ExecuteQueryPersistentMethod(sessionFactory, classLoader, grailsApplication, conversionService) - executeUpdateMethod = new ExecuteUpdatePersistentMethod(sessionFactory, classLoader, grailsApplication) - findMethod = new FindPersistentMethod(sessionFactory, classLoader, grailsApplication, conversionService) - findAllMethod = new FindAllPersistentMethod(sessionFactory, classLoader, grailsApplication, conversionService) - } - - @Override - D get(Serializable id) { - if (id || (id instanceof Number)) { - id = convertIdentifier(id) - D result = (D)hibernateTemplate.get((Class)persistentClass, id) - return GrailsHibernateUtil.unwrapIfProxy(result) - } - } - - 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 getAll() { - (List)hibernateTemplate.execute({ Session session -> - Criteria criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) - criteria.list() - } as HibernateCallback) - } - - List getAll(List ids) { - getAllInternal(ids) - } - - List getAll(Long... ids) { - getAllInternal(ids as List) - } - - @Override - List 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) - } - - @Override - GrailsCriteria createCriteria() { - def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory) - builder.grailsApplication = grailsApplication - builder.conversionService = conversionService - builder - } - - @Override - D lock(Serializable id) { - id = convertIdentifier(id) - (D)hibernateTemplate.get((Class)persistentClass, id, LockMode.UPGRADE) - } - - @Override - D merge(o) { - 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 list(Map params) { - (List)listMethod.invoke(persistentClass, "list", [params] as Object[]) - } - - @Override - List list() { - (List)listMethod.invoke(persistentClass, "list", EMPTY_ARRAY) - } - - @Override - List findAll(example, Map args) { - (List)findAllMethod.invoke(persistentClass, "findAll", [example, args] as Object[]) - } - - @Override - D find(example, Map args) { - 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) { - 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) { - 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) { - 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) { - 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 findAll(String query, Map args, Integer max) { - (List)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 findAll(String query, Map args, Integer max, Integer offset) { - (List)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 findAll(String query, Integer max) { - (List)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 findAll(String query, Integer max, Integer offset) { - (List)findAllMethod.invoke(persistentClass, "findAll", [query, max, offset] as Object[]) - } - - @Override - List findAllWhere(Map queryMap, Map args) { - if (!queryMap) return null - (List)hibernateTemplate.execute({Session session -> - Map queryArgs = filterQueryArgumentMap(queryMap) - List 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 queryArgs = filterQueryArgumentMap(queryMap) - List 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 removeNullNames(Map query) { - List nullNames = [] - Set allNames = new HashSet(query.keySet()) - for (String name in allNames) { - if (query[name] == null) { - query.remove name - nullNames << name - } - } - nullNames - } - - @Override - Object withSession(Closure callable) { - HibernateTemplate template = new GrailsHibernateTemplate(sessionFactory, grailsApplication) - template.setExposeNativeSession(false) - template.execute({ session -> - callable(session) - } as HibernateCallback) - } - - @Override - def withNewSession(Closure callable) { - HibernateTemplate template = new GrailsHibernateTemplate(sessionFactory, grailsApplication) - template.setExposeNativeSession(false) - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory) - Session previousSession = sessionHolder?.session - Session newSession - boolean newBind = false - try { - template.allowCreate = true - newSession = sessionFactory.openSession() - if (sessionHolder == null) { - sessionHolder = new SessionHolder(newSession) - TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder) - newBind = true - } - else { - sessionHolder.addSession(newSession) - } - template.execute({ Session session -> - return callable(session) - } as HibernateCallback) - } - finally { - if (newSession) { - SessionFactoryUtils.closeSession(newSession) - sessionHolder?.removeSession(newSession) - } - if (newBind) { - TransactionSynchronizationManager.unbindResource(sessionFactory) - } - if (previousSession) { - sessionHolder?.addSession(previousSession) - } - } - } - - @Override - List executeQuery(String query) { - (List)executeQueryMethod.invoke(persistentClass, "executeQuery", [query] as Object[]) - } - - List executeQuery(String query, arg) { - (List)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, arg] as Object[]) - } - - @Override - List executeQuery(String query, Map args) { - (List)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, args] as Object[]) - } - - @Override - List executeQuery(String query, Map params, Map args) { - (List)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, params, args] as Object[]) - } - - @Override - List executeQuery(String query, Collection params) { - (List)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, params] as Object[]) - } - - @Override - List executeQuery(String query, Collection params, Map args) { - (List)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) { - findMethod.invoke(persistentClass, "find", [query] as Object[]) - } - - D find(String query, Object[] params) { - findMethod.invoke(persistentClass, "find", [query, params] as Object[]) - } - - @Override - D find(String query, Map args) { - findMethod.invoke(persistentClass, "find", [query, args] as Object[]) - } - - @Override - D find(String query, Map params, Map args) { - 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) { - findMethod.invoke(persistentClass, "find", [query, params, args] as Object[]) - } - - @Override - List findAll(String query) { - (List)findAllMethod.invoke(persistentClass, "findAll", [query] as Object[]) - } - - @Override - List findAll(String query, Map args) { - (List)findAllMethod.invoke(persistentClass, "findAll", [query, args] as Object[]) - } - - @Override - List findAll(String query, Map params, Map args) { - (List)findAllMethod.invoke(persistentClass, "findAll", [query, params, args] as Object[]) - } - - @Override - List findAll(String query, Collection params) { - (List)findAllMethod.invoke(persistentClass, "findAll", [query, params] as Object[]) - } - - @Override - List findAll(String query, Collection params, Map args) { - (List)findAllMethod.invoke(persistentClass, "findAll", [query, params, args] as Object[]) - } - - @Override - D create() { - return super.create() //To change body of overridden methods use File | Settings | File Templates. - } -} 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 deleted file mode 100644 index 5e1590c65..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormValidationApi.groovy +++ /dev/null @@ -1,39 +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 - -import groovy.transform.CompileStatic - -import org.codehaus.groovy.grails.domain.GrailsDomainClassMappingContext -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ValidatePersistentMethod - -@CompileStatic -class HibernateGormValidationApi extends AbstractHibernateGormValidationApi { - - ValidatePersistentMethod validateMethod - - HibernateGormValidationApi(Class persistentClass, HibernateDatastore datastore, ClassLoader classLoader) { - super(persistentClass, datastore, classLoader) - - def mappingContext = datastore.mappingContext - if (mappingContext instanceof GrailsDomainClassMappingContext) { - GrailsDomainClassMappingContext domainClassMappingContext = (GrailsDomainClassMappingContext)mappingContext - def validator = mappingContext.getEntityValidator(mappingContext.getPersistentEntity(persistentClass.name)) - validateMethod = new ValidatePersistentMethod(datastore.getSessionFactory(), - classLoader, domainClassMappingContext.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 deleted file mode 100644 index cf1d81254..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateSession.java +++ /dev/null @@ -1,175 +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.codehaus.groovy.grails.orm.hibernate; - -import java.io.Serializable; -import java.sql.SQLException; -import java.util.List; -import java.util.Map; - -import javax.persistence.FlushModeType; - -import org.codehaus.groovy.grails.domain.GrailsDomainClassMappingContext; -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; -import org.grails.datastore.mapping.query.jpa.JpaQueryBuilder; -import org.grails.datastore.mapping.query.jpa.JpaQueryInfo; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Restrictions; -import org.hibernate.proxy.HibernateProxy; -import org.springframework.orm.hibernate3.HibernateCallback; -import org.springframework.orm.hibernate3.HibernateTemplate; - -/** - * Session implementation that wraps a Hibernate {@link Session}. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class HibernateSession extends AbstractHibernateSession { - - ProxyHandler proxyHandler = new HibernateProxyHandler(); - public HibernateSession(HibernateDatastore hibernateDatastore, SessionFactory sessionFactory) { - super(hibernateDatastore, sessionFactory); - - if (datastore.getMappingContext() instanceof GrailsDomainClassMappingContext) { - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, - ((GrailsDomainClassMappingContext)datastore.getMappingContext()).getGrailsApplication()); - } - else { - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory); - } - } - - @Override - public Serializable getObjectIdentifier(Object instance) { - if(instance == null) return null; - if(proxyHandler.isProxy(instance)) { - return ((HibernateProxy)instance).getHibernateLazyInitializer().getIdentifier(); - } - Class type = instance.getClass(); - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(type); - final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(type.getName()); - if(persistentEntity != null) { - return (Serializable) cpf.getPropertyValue(instance, persistentEntity.getIdentity().getName()); - } - return null; - } - - /** - * Deletes all objects matching the given criteria. - * - * @param criteria The criteria - * @return The total number of records deleted - */ - public int deleteAll(final QueryableCriteria criteria) { - return getHibernateTemplate().execute(new HibernateCallback() { - public Integer doInHibernate(Session session) throws HibernateException, SQLException { - JpaQueryBuilder builder = new JpaQueryBuilder(criteria); - builder.setHibernateCompatible(true); - JpaQueryInfo jpaQueryInfo = builder.buildDelete(); - - org.hibernate.Query query = session.createQuery(jpaQueryInfo.getQuery()); - getHibernateTemplate().applySettings(query); - - List parameters = jpaQueryInfo.getParameters(); - if (parameters != null) { - for (int i = 0, count = parameters.size(); i < count; i++) { - query.setParameter(i, parameters.get(i)); - } - } - return query.executeUpdate(); - } - }); - } - - /** - * Updates all objects matching the given criteria and property values. - * - * @param criteria The criteria - * @param properties The properties - * @return The total number of records updated - */ - public int updateAll(final QueryableCriteria criteria, final Map properties) { - return getHibernateTemplate().execute(new HibernateCallback() { - public Integer doInHibernate(Session session) throws HibernateException, SQLException { - JpaQueryBuilder builder = new JpaQueryBuilder(criteria); - builder.setHibernateCompatible(true); - JpaQueryInfo jpaQueryInfo = builder.buildUpdate(properties); - - org.hibernate.Query query = session.createQuery(jpaQueryInfo.getQuery()); - getHibernateTemplate().applySettings(query); - List parameters = jpaQueryInfo.getParameters(); - if (parameters != null) { - for (int i = 0, count = parameters.size(); i < count; i++) { - query.setParameter(i, parameters.get(i)); - } - } - return query.executeUpdate(); - } - }); - } - - public List retrieveAll(final Class type, final Iterable keys) { - final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(type.getName()); - return getHibernateTemplate().execute(new HibernateCallback() { - public List doInHibernate(org.hibernate.Session session) throws HibernateException, SQLException { - Criteria criteria = session.createCriteria(type); - getHibernateTemplate().applySettings(criteria); - return criteria.add( - Restrictions.in(persistentEntity.getIdentity().getName(), getIterableAsCollection(keys))) - .list(); - } - }); - } - - public Query createQuery(Class type) { - final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(type.getName()); - final Criteria criteria = getHibernateTemplate().getSessionFactory().getCurrentSession().createCriteria(type); - getHibernateTemplate().applySettings(criteria); - return new HibernateQuery(criteria, this, persistentEntity); - } - - protected GrailsHibernateTemplate getHibernateTemplate() { - return (GrailsHibernateTemplate)getNativeInterface(); - } - - public void setFlushMode(FlushModeType flushMode) { - if (flushMode == FlushModeType.AUTO) { - hibernateTemplate.setFlushMode(HibernateTemplate.FLUSH_AUTO); - } - else if (flushMode == FlushModeType.COMMIT) { - hibernateTemplate.setFlushMode(HibernateTemplate.FLUSH_COMMIT); - } - } - - public FlushModeType getFlushMode() { - switch (hibernateTemplate.getFlushMode()) { - case HibernateTemplate.FLUSH_AUTO: return FlushModeType.AUTO; - case HibernateTemplate.FLUSH_COMMIT: return FlushModeType.COMMIT; - case HibernateTemplate.FLUSH_ALWAYS: return FlushModeType.AUTO; - default: return FlushModeType.AUTO; - } - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/InstanceApiHelper.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/InstanceApiHelper.java deleted file mode 100644 index b59b71255..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/InstanceApiHelper.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2013 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.codehaus.groovy.grails.orm.hibernate; - -import org.hibernate.FlushMode; -import org.hibernate.Session; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * Workaround for VerifyErrors in Groovy when using a HibernateCallback. - * - * @author Burt Beckwith - */ -public class InstanceApiHelper { - - protected GrailsHibernateTemplate hibernateTemplate; - - public InstanceApiHelper(final GrailsHibernateTemplate hibernateTemplate) { - this.hibernateTemplate = hibernateTemplate; - } - - public void delete(final Object obj, final boolean flush) { - hibernateTemplate.execute(new HibernateCallback() { - public Void doInHibernate(Session session) { - session.delete(obj); - if (flush) { - session.flush(); - } - return null; - } - }); - } - - public void setFlushModeManual() { - hibernateTemplate.execute(new HibernateCallback() { - public Void doInHibernate(Session session) { - session.setFlushMode(FlushMode.MANUAL); - return null; - } - }); - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/SessionFactoryProxy.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/SessionFactoryProxy.java deleted file mode 100644 index dc55c94f6..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/SessionFactoryProxy.java +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Copyright 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.codehaus.groovy.grails.orm.hibernate; - -import groovy.lang.*; -import org.codehaus.groovy.runtime.InvokerHelper; -import org.hibernate.*; -import org.hibernate.Interceptor; -import org.hibernate.cache.QueryCache; -import org.hibernate.cache.Region; -import org.hibernate.cache.UpdateTimestampsCache; -import org.hibernate.cfg.Settings; -import org.hibernate.classic.Session; -import org.hibernate.connection.ConnectionProvider; -import org.hibernate.context.CurrentSessionContext; -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.function.SQLFunctionRegistry; -import org.hibernate.engine.*; -import org.hibernate.engine.profile.FetchProfile; -import org.hibernate.engine.query.QueryPlanCache; -import org.hibernate.exception.SQLExceptionConverter; -import org.hibernate.id.IdentifierGenerator; -import org.hibernate.id.factory.IdentifierGeneratorFactory; -import org.hibernate.metadata.ClassMetadata; -import org.hibernate.metadata.CollectionMetadata; -import org.hibernate.persister.collection.CollectionPersister; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.proxy.EntityNotFoundDelegate; -import org.hibernate.stat.Statistics; -import org.hibernate.stat.StatisticsImplementor; -import org.hibernate.type.Type; -import org.hibernate.type.TypeResolver; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.core.InfrastructureProxy; -import org.springframework.orm.hibernate3.SpringSessionContext; -import org.springframework.util.ReflectionUtils; - -import javax.naming.NamingException; -import javax.naming.Reference; -import javax.transaction.TransactionManager; -import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.sql.Connection; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -/** - *

    Proxies the SessionFactory allowing for the underlying SessionFactory instance to be replaced at runtime. - * Used to enable rebuilding of the SessionFactory at development time

    - * - *

    NOTE: This class is not for production use and is development time only!

    - * - * @since 2.0 - * @author Graeme Rocher - */ -@SuppressWarnings("rawtypes") -public class SessionFactoryProxy extends GroovyObjectSupport implements SessionFactoryImplementor, ApplicationContextAware, InitializingBean, InfrastructureProxy { - - private static final long serialVersionUID = 1; - - private String targetBean; - private ApplicationContext applicationContext; - private Class currentSessionContextClass = SpringSessionContext.class; - - /** - * The target bean to proxy - * - * @param targetBean The name of the target bean - */ - public void setTargetBean(String targetBean) { - this.targetBean = targetBean; - } - - @Override - public Object getProperty(String property) { - try { - return super.getProperty(property); - } catch (MissingPropertyException e) { - return InvokerHelper.getProperty(getCurrentSessionFactory(), property); - } - } - - /** - * The class to use for the current session context - * - * @param currentSessionContextClass The current session context class - */ - public void setCurrentSessionContextClass(Class currentSessionContextClass) { - this.currentSessionContextClass = currentSessionContextClass; - } - - /** - * @return The current SessionFactory being proxied - */ - public SessionFactory getCurrentSessionFactory() { - SessionFactory sf = applicationContext.getBean(targetBean, SessionFactoryHolder.class).getSessionFactory(); - updateCurrentSessionContext(sf); - return sf; - } - - /** - * @return The current SessionFactoryImplementor being proxied - */ - public SessionFactoryImplementor getCurrentSessionFactoryImplementor() { - return (SessionFactoryImplementor) getCurrentSessionFactory(); - } - - public Session openSession() throws HibernateException { - return getCurrentSessionFactory().openSession(); - } - - public Session openSession(Interceptor interceptor) throws HibernateException { - return getCurrentSessionFactory().openSession(interceptor); - } - - public Session openSession(Connection connection) { - return getCurrentSessionFactory().openSession(connection); - } - - public Session openSession(Connection connection, Interceptor interceptor) { - return getCurrentSessionFactory().openSession(connection, interceptor); - } - - public Session getCurrentSession() throws HibernateException { - return getCurrentSessionFactory().getCurrentSession(); - } - - public StatelessSession openStatelessSession() { - return getCurrentSessionFactory().openStatelessSession(); - } - - public StatelessSession openStatelessSession(Connection connection) { - return getCurrentSessionFactory().openStatelessSession(connection); - } - - public ClassMetadata getClassMetadata(Class entityClass) { - return getCurrentSessionFactory().getClassMetadata(entityClass); - } - - public ClassMetadata getClassMetadata(String entityName) { - return getCurrentSessionFactory().getClassMetadata(entityName); - } - - public CollectionMetadata getCollectionMetadata(String roleName) { - return getCurrentSessionFactory().getCollectionMetadata(roleName); - } - - public Map getAllClassMetadata() { - return getCurrentSessionFactory().getAllClassMetadata(); - } - - public Map getAllCollectionMetadata() { - return getCurrentSessionFactory().getAllCollectionMetadata(); - } - - public Statistics getStatistics() { - return getCurrentSessionFactory().getStatistics(); - } - - public void close() throws HibernateException { - getCurrentSessionFactory().close(); - } - - public boolean isClosed() { - return getCurrentSessionFactory().isClosed(); - } - - public Cache getCache() { - return getCurrentSessionFactory().getCache(); - } - - @Deprecated - public void evict(Class persistentClass) throws HibernateException { - getCurrentSessionFactory().evict(persistentClass); - } - - @Deprecated - public void evict(Class persistentClass, Serializable id) throws HibernateException { - getCurrentSessionFactory().evict(persistentClass, id); - } - - @Deprecated - public void evictEntity(String entityName) throws HibernateException { - getCurrentSessionFactory().evictEntity(entityName); - } - - @Deprecated - public void evictEntity(String entityName, Serializable id) throws HibernateException { - getCurrentSessionFactory().evictEntity(entityName, id); - } - - @Deprecated - public void evictCollection(String roleName) throws HibernateException { - getCurrentSessionFactory().evictCollection(roleName); - } - - @Deprecated - public void evictCollection(String roleName, Serializable id) throws HibernateException { - getCurrentSessionFactory().evictCollection(roleName, id); - } - - @Deprecated - public void evictQueries(String cacheRegion) throws HibernateException { - getCurrentSessionFactory().evictQueries(cacheRegion); - } - - @Deprecated - public void evictQueries() throws HibernateException { - getCurrentSessionFactory().evictQueries(); - } - - public Set getDefinedFilterNames() { - return getCurrentSessionFactory().getDefinedFilterNames(); - } - - public FilterDefinition getFilterDefinition(String filterName) throws HibernateException { - return getCurrentSessionFactory().getFilterDefinition(filterName); - } - - public boolean containsFetchProfileDefinition(String name) { - return getCurrentSessionFactory().containsFetchProfileDefinition(name); - } - - public TypeHelper getTypeHelper() { - return getCurrentSessionFactory().getTypeHelper(); - } - - public Reference getReference() throws NamingException { - return getCurrentSessionFactory().getReference(); - } - - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - public TypeResolver getTypeResolver() { - return getCurrentSessionFactoryImplementor().getTypeResolver(); - } - - public Properties getProperties() { - return getCurrentSessionFactoryImplementor().getProperties(); - } - - public EntityPersister getEntityPersister(String entityName) throws MappingException { - return getCurrentSessionFactoryImplementor().getEntityPersister(entityName); - } - - public CollectionPersister getCollectionPersister(String role) throws MappingException { - return getCurrentSessionFactoryImplementor().getCollectionPersister(role); - } - - public Dialect getDialect() { - return getCurrentSessionFactoryImplementor().getDialect(); - } - - public Interceptor getInterceptor() { - return getCurrentSessionFactoryImplementor().getInterceptor(); - } - - public QueryPlanCache getQueryPlanCache() { - return getCurrentSessionFactoryImplementor().getQueryPlanCache(); - } - - public Type[] getReturnTypes(String queryString) throws HibernateException { - return getCurrentSessionFactoryImplementor().getReturnTypes(queryString); - } - - public String[] getReturnAliases(String queryString) throws HibernateException { - return getCurrentSessionFactoryImplementor().getReturnAliases(queryString); - } - - public ConnectionProvider getConnectionProvider() { - return getCurrentSessionFactoryImplementor().getConnectionProvider(); - } - - public String[] getImplementors(String className) throws MappingException { - return getCurrentSessionFactoryImplementor().getImplementors(className); - } - - public String getImportedClassName(String name) { - return getCurrentSessionFactoryImplementor().getImportedClassName(name); - } - - public TransactionManager getTransactionManager() { - return getCurrentSessionFactoryImplementor().getTransactionManager(); - } - - public QueryCache getQueryCache() { - return getCurrentSessionFactoryImplementor().getQueryCache(); - } - - public QueryCache getQueryCache(String regionName) throws HibernateException { - return getCurrentSessionFactoryImplementor().getQueryCache(regionName); - } - - public UpdateTimestampsCache getUpdateTimestampsCache() { - return getCurrentSessionFactoryImplementor().getUpdateTimestampsCache(); - } - - public StatisticsImplementor getStatisticsImplementor() { - return getCurrentSessionFactoryImplementor().getStatisticsImplementor(); - } - - public NamedQueryDefinition getNamedQuery(String queryName) { - return getCurrentSessionFactoryImplementor().getNamedQuery(queryName); - } - - public NamedSQLQueryDefinition getNamedSQLQuery(String queryName) { - return getCurrentSessionFactoryImplementor().getNamedSQLQuery(queryName); - } - - public ResultSetMappingDefinition getResultSetMapping(String name) { - return getCurrentSessionFactoryImplementor().getResultSetMapping(name); - } - - public IdentifierGenerator getIdentifierGenerator(String rootEntityName) { - return getCurrentSessionFactoryImplementor().getIdentifierGenerator(rootEntityName); - } - - public Region getSecondLevelCacheRegion(String regionName) { - return getCurrentSessionFactoryImplementor().getSecondLevelCacheRegion(regionName); - } - - public Map getAllSecondLevelCacheRegions() { - return getCurrentSessionFactoryImplementor().getAllSecondLevelCacheRegions(); - } - - public SQLExceptionConverter getSQLExceptionConverter() { - return getCurrentSessionFactoryImplementor().getSQLExceptionConverter(); - } - - public Settings getSettings() { - return getCurrentSessionFactoryImplementor().getSettings(); - } - - public Session openTemporarySession() throws HibernateException { - return getCurrentSessionFactoryImplementor().openTemporarySession(); - } - - public Session openSession(Connection connection, boolean flushBeforeCompletionEnabled, boolean autoCloseSessionEnabled, ConnectionReleaseMode connectionReleaseMode) throws HibernateException { - return getCurrentSessionFactoryImplementor().openSession(connection,flushBeforeCompletionEnabled,autoCloseSessionEnabled, connectionReleaseMode); - } - - public Set getCollectionRolesByEntityParticipant(String entityName) { - return getCurrentSessionFactoryImplementor().getCollectionRolesByEntityParticipant(entityName); - } - - public EntityNotFoundDelegate getEntityNotFoundDelegate() { - return getCurrentSessionFactoryImplementor().getEntityNotFoundDelegate(); - } - - public SQLFunctionRegistry getSqlFunctionRegistry() { - return getCurrentSessionFactoryImplementor().getSqlFunctionRegistry(); - } - - public FetchProfile getFetchProfile(String name) { - return getCurrentSessionFactoryImplementor().getFetchProfile(name); - } - - public SessionFactoryObserver getFactoryObserver() { - return getCurrentSessionFactoryImplementor().getFactoryObserver(); - } - - @Deprecated - public IdentifierGeneratorFactory getIdentifierGeneratorFactory() { - return getCurrentSessionFactoryImplementor().getIdentifierGeneratorFactory(); - } - - public Type getIdentifierType(String className) throws MappingException { - return getCurrentSessionFactoryImplementor().getIdentifierType(className); - } - - public String getIdentifierPropertyName(String className) throws MappingException { - return getCurrentSessionFactoryImplementor().getIdentifierPropertyName(className); - } - - public Type getReferencedPropertyType(String className, String propertyName) throws MappingException { - return getCurrentSessionFactoryImplementor().getReferencedPropertyType(className,propertyName); - } - - public void afterPropertiesSet() { - SessionFactoryImplementor sessionFactory = getCurrentSessionFactoryImplementor(); - updateCurrentSessionContext(sessionFactory); - } - - private void updateCurrentSessionContext(SessionFactory sessionFactory) { - // patch the currentSessionContext variable of SessionFactoryImpl to use this proxy as the key - CurrentSessionContext ssc = createCurrentSessionContext(); - - try { - Class sessionFactoryClass = sessionFactory.getClass(); - Field currentSessionContextField = sessionFactoryClass.getDeclaredField("currentSessionContext"); - if (currentSessionContextField != null) { - ReflectionUtils.makeAccessible(currentSessionContextField); - currentSessionContextField.set(sessionFactory, ssc); - } - } catch (NoSuchFieldException e) { - // ignore - } catch (SecurityException e) { - // ignore - } catch (IllegalArgumentException e) { - // ignore - } catch (IllegalAccessException e) { - // ignore - } - } - - @SuppressWarnings("unchecked") - protected CurrentSessionContext createCurrentSessionContext() { - Class sessionContextClass = currentSessionContextClass; - if (sessionContextClass == null) { - sessionContextClass = SpringSessionContext.class; - } - try { - Constructor constructor = sessionContextClass.getConstructor(SessionFactoryImplementor.class); - return BeanUtils.instantiateClass(constructor, this); - } catch (NoSuchMethodException e) { - return new SpringSessionContext(this); - } - } - - public Object getWrappedObject() { - return getCurrentSessionFactory(); - } -} 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 deleted file mode 100644 index 958665b15..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/DefaultGrailsDomainConfiguration.java +++ /dev/null @@ -1,126 +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.cfg; - -import groovy.lang.Closure; -import groovy.util.Eval; - -import java.util.HashSet; -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.hibernate.MappingException; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Mappings; - -/** - * Creates runtime configuration mapping for the Grails domain classes - * based on the work done in the Hibernate Annotations project - * - * @author Graeme Rocher - * @since 06-Jul-2005 - */ -public class DefaultGrailsDomainConfiguration extends Configuration implements GrailsDomainConfiguration { - - private static final long serialVersionUID = -7115087342689305517L; - - protected GrailsApplication grailsApplication; - protected Set domainClasses = new HashSet(); - protected boolean configLocked; - protected String sessionFactoryBeanName = "sessionFactory"; - protected String dataSourceName = GrailsDomainClassProperty.DEFAULT_DATA_SOURCE; - - protected static GrailsDomainBinder binder = new GrailsDomainBinder(); - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainConfiguration#addDomainClass(org.codehaus.groovy.grails.commons.GrailsDomainClass) - */ - public GrailsDomainConfiguration addDomainClass(GrailsDomainClass domainClass) { - if (domainClass.getMappingStrategy().equalsIgnoreCase(GrailsDomainClass.GORM)) { - domainClasses.add(domainClass); - } - - return this; - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainConfiguration#setGrailsApplication(org.codehaus.groovy.grails.commons.GrailsApplication) - */ - public void setGrailsApplication(GrailsApplication application) { - grailsApplication = application; - if (grailsApplication == null) { - return; - } - - for (GrailsClass existingDomainClass : grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE)) { - addDomainClass((GrailsDomainClass) existingDomainClass); - } - } - - public void setSessionFactoryBeanName(String name) { - sessionFactoryBeanName = name; - } - - public void setDataSourceName(String name) { - dataSourceName = name; - } - - /** - * Overrides the default behaviour to including binding of Grails domain classes. - */ - @Override - protected void secondPassCompile() throws MappingException { - if (configLocked) { - return; - } - - // set the class loader to load Groovy classes - if (grailsApplication != null) { - Thread.currentThread().setContextClassLoader(grailsApplication.getClassLoader()); - } - - configureDomainBinder(grailsApplication, domainClasses); - - for (GrailsDomainClass domainClass : domainClasses) { - if (!GrailsHibernateUtil.usesDatasource(domainClass, dataSourceName)) { - continue; - } - final Mappings mappings = super.createMappings(); - Mapping m = binder.getMapping(domainClass); - mappings.setAutoImport(m == null || m.getAutoImport()); - binder.bindClass(domainClass, mappings, sessionFactoryBeanName); - } - - super.secondPassCompile(); - configLocked = true; - } - - public static void configureDomainBinder(GrailsApplication grailsApplication, Set domainClasses) { - Object defaultMapping = Eval.x(grailsApplication, "x.config?.grails?.gorm?.default?.mapping"); - // do Grails class configuration - for (GrailsDomainClass domainClass : domainClasses) { - if (defaultMapping instanceof Closure) { - binder.evaluateMapping(domainClass, (Closure)defaultMapping); - } - else { - binder.evaluateMapping(domainClass); - } - } - } -} 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 deleted file mode 100644 index dfa1435ac..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsAnnotationConfiguration.java +++ /dev/null @@ -1,230 +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.cfg; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import org.codehaus.groovy.grails.commons.AnnotationDomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.ArtefactHandler; -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.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.engine.FilterDefinition; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Allows configuring Grails' hibernate support to work in conjuntion with Hibernate's annotation - * support. - * - * @author Graeme Rocher - * @since 18-Feb-2006 - */ -public class GrailsAnnotationConfiguration extends Configuration implements GrailsDomainConfiguration { - - private static final long serialVersionUID = -7115087342689305517L; - - protected final Logger log = LoggerFactory.getLogger(getClass()); - - protected GrailsApplication grailsApplication; - protected Set domainClasses = new HashSet(); - protected boolean configLocked; - protected String sessionFactoryBeanName = "sessionFactory"; - protected String dataSourceName = GrailsDomainClassProperty.DEFAULT_DATA_SOURCE; - protected GrailsDomainBinder binder = new GrailsDomainBinder(); - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainConfiguration#addDomainClass(org.codehaus.groovy.grails.commons.GrailsDomainClass) - */ - public GrailsDomainConfiguration addDomainClass(GrailsDomainClass domainClass) { - if (shouldMapWithGorm(domainClass)) { - domainClasses.add(domainClass); - } - - return this; - } - - protected boolean shouldMapWithGorm(GrailsDomainClass domainClass) { - return !AnnotationDomainClassArtefactHandler.isJPADomainClass(domainClass.getClazz()) && - domainClass.getMappingStrategy().equalsIgnoreCase(GrailsDomainClass.GORM); - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainConfiguration#setGrailsApplication(org.codehaus.groovy.grails.commons.GrailsApplication) - */ - public void setGrailsApplication(GrailsApplication application) { - grailsApplication = application; - if (grailsApplication == null) { - return; - } - - configureNamingStrategy(); - GrailsClass[] existingDomainClasses = grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE); - for (GrailsClass existingDomainClass : existingDomainClasses) { - addDomainClass((GrailsDomainClass) existingDomainClass); - } - - ArtefactHandler handler = grailsApplication.getArtefactHandler(DomainClassArtefactHandler.TYPE); - if (!(handler instanceof AnnotationDomainClassArtefactHandler)) { - return; - } - - Set jpaDomainNames = ((AnnotationDomainClassArtefactHandler)handler).getJpaClassNames(); - if (jpaDomainNames == null) { - return; - } - - final ClassLoader loader = grailsApplication.getClassLoader(); - for (String jpaDomainName : jpaDomainNames) { - try { - addAnnotatedClass(loader.loadClass(jpaDomainName)); - } - catch (ClassNotFoundException e) { - // impossible condition - } - } - } - - public void setSessionFactoryBeanName(String name) { - sessionFactoryBeanName = name; - } - - public void setDataSourceName(String name) { - dataSourceName = name; - } - - /* (non-Javadoc) - * @see org.hibernate.cfg.Configuration#buildSessionFactory() - */ - @Override - public SessionFactory buildSessionFactory() throws HibernateException { - // set the class loader to load Groovy classes - if (grailsApplication != null) { - if (log.isDebugEnabled()) { - log.debug("[GrailsAnnotationConfiguration] Setting context class loader to Grails GroovyClassLoader"); - } - Thread.currentThread().setContextClassLoader(grailsApplication.getClassLoader()); - } - - // work around for HHH-2624 - addFilterDefinition(new FilterDefinition("dynamicFilterEnabler", "1=1", Collections.emptyMap())); - - SessionFactory sessionFactory = super.buildSessionFactory(); - - if (grailsApplication != null) { - GrailsHibernateUtil.configureHibernateDomainClasses( - sessionFactory, sessionFactoryBeanName, grailsApplication); - } - - return sessionFactory; - } - - /** - * Overrides the default behaviour to including binding of Grails domain classes. - */ - @Override - protected void secondPassCompile() throws MappingException { - final Thread currentThread = Thread.currentThread(); - final ClassLoader originalContextLoader = currentThread.getContextClassLoader(); - if (!configLocked) { - if (log.isDebugEnabled()) { - log.debug("[GrailsAnnotationConfiguration] [" + domainClasses.size() + - "] Grails domain classes to bind to persistence runtime"); - } - - // do Grails class configuration - DefaultGrailsDomainConfiguration.configureDomainBinder(grailsApplication, domainClasses); - - for (GrailsDomainClass domainClass : domainClasses) { - - final String fullClassName = domainClass.getFullName(); - - String hibernateConfig = fullClassName.replace('.', '/') + ".hbm.xml"; - final ClassLoader loader = originalContextLoader; - // don't configure Hibernate mapped classes - if (loader.getResource(hibernateConfig) != null) continue; - - final Mappings mappings = super.createMappings(); - if (!GrailsHibernateUtil.usesDatasource(domainClass, dataSourceName)) { - continue; - } - - if (log.isDebugEnabled()) { - log.debug("[GrailsAnnotationConfiguration] Binding persistent class [" + fullClassName + "]"); - } - - Mapping m = binder.getMapping(domainClass); - mappings.setAutoImport(m == null || m.getAutoImport()); - binder.bindClass(domainClass, mappings, sessionFactoryBeanName); - } - } - - try { - currentThread.setContextClassLoader(grailsApplication.getClassLoader()); - super.secondPassCompile(); - } finally { - currentThread.setContextClassLoader(originalContextLoader); - } - - configLocked = true; - } - - /** - * Sets custom naming strategy specified in configuration or the default {@link ImprovedNamingStrategy}. - */ - protected void configureNamingStrategy() { - NamingStrategy strategy = null; - Object customStrategy = grailsApplication.getFlatConfig().get("hibernate.naming_strategy"); - if (customStrategy != null) { - Class namingStrategyClass = null; - if (customStrategy instanceof Class) { - namingStrategyClass = (Class)customStrategy; - } else { - try { - namingStrategyClass = grailsApplication.getClassLoader().loadClass(customStrategy.toString()); - } catch (ClassNotFoundException e) { - // ignore - } - } - - if (namingStrategyClass != null) { - try { - strategy = (NamingStrategy)namingStrategyClass.newInstance(); - } catch (InstantiationException e) { - // ignore - } catch (IllegalAccessException e) { - // ignore - } - } - } - - if (strategy == null) { - strategy = ImprovedNamingStrategy.INSTANCE; - } - - setNamingStrategy(strategy); - } -} 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 deleted file mode 100644 index a6c4dc0c1..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.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.cfg; - -import java.util.Arrays; -import java.util.List; - -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -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; - -/** - * Handles the binding Grails domain classes and properties to the Hibernate runtime meta model. - * Based on the HbmBinder code in Hibernate core and influenced by AnnotationsBinder. - * - * @author Graeme Rocher - * @since 0.1 - */ -public class GrailsDomainBinder extends AbstractGrailsDomainBinder { - - protected Class getGroovyAwareJoinedSubclassEntityPersisterClass() { - return GroovyAwareJoinedSubclassEntityPersister.class; - } - - protected Class getGroovyAwareSingleTableEntityPersisterClass() { - return GroovyAwareSingleTableEntityPersister.class; - } - - protected void handleLazyProxy(GrailsDomainClass domainClass, GrailsDomainClassProperty grailsProperty) { - HibernateUtils.handleLazyProxy(domainClass, grailsProperty); - } - - protected void handleUniqueConstraint(GrailsDomainClassProperty property, Column column, String path, Table table, String columnName, String sessionFactoryBeanName) { - ConstrainedProperty cp = getConstrainedProperty(property); - if (cp != null && cp.hasAppliedConstraint(UniqueConstraint.UNIQUE_CONSTRAINT)) { - Constraint appliedConstraint = cp.getAppliedConstraint(UniqueConstraint.UNIQUE_CONSTRAINT); - if (appliedConstraint instanceof UniqueConstraint) { - UniqueConstraint uc = (UniqueConstraint) appliedConstraint; - if (uc != null && uc.isUnique()) { - if (!uc.isUniqueWithinGroup()) { - column.setUnique(true); - } - else if (uc.getUniquenessGroup().size() > 0) { - createKeyForProps(property, path, table, columnName, uc.getUniquenessGroup(), sessionFactoryBeanName); - } - } - } - } - else { - Object val = cp != null ? cp.getMetaConstraintValue(UniqueConstraint.UNIQUE_CONSTRAINT) : null; - if (val instanceof Boolean) { - column.setUnique((Boolean)val); - } - else if (val instanceof String) { - createKeyForProps(property, path, table, columnName, Arrays.asList((String) val), sessionFactoryBeanName); - } - else if (val instanceof List && ((List)val).size() > 0) { - createKeyForProps(property, path, table, columnName, (List)val, sessionFactoryBeanName); - } - } - } - - protected boolean identityEnumTypeSupports(Class propertyType) { - return IdentityEnumType.supports(propertyType); - } - - protected boolean isNotEmpty(String s) { - return GrailsHibernateUtil.isNotEmpty(s); - } - - protected String qualify(String prefix, String name) { - return GrailsHibernateUtil.qualify(prefix, name); - } - - protected String unqualify(String qualifiedName) { - return GrailsHibernateUtil.unqualify(qualifiedName); - } -} 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 deleted file mode 100644 index 24c961bd5..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsHibernateUtil.java +++ /dev/null @@ -1,628 +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.cfg; - -import grails.util.CollectionUtils; -import grails.util.GrailsWebUtil; -import groovy.lang.GroovyObject; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; - -import java.sql.SQLException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.lang.StringUtils; -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.GrailsClass; -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.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.grails.web.context.GrailsConfigUtils; -import org.hibernate.Criteria; -import org.hibernate.EntityMode; -import org.hibernate.FetchMode; -import org.hibernate.FlushMode; -import org.hibernate.Hibernate; -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Order; -import org.hibernate.engine.EntityEntry; -import org.hibernate.engine.SessionImplementor; -import org.hibernate.engine.Status; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.metadata.ClassMetadata; -import org.hibernate.property.Getter; -import org.hibernate.property.Setter; -import org.hibernate.proxy.HibernateProxy; -import org.hibernate.type.CompositeType; -import org.hibernate.util.StringHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.core.convert.ConversionService; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * Utility methods for configuring Hibernate inside Grails. - * - * @author Graeme Rocher - * @since 0.4 - */ -public class GrailsHibernateUtil { - private static final Logger LOG = LoggerFactory.getLogger(GrailsHibernateUtil.class); - - private static final String DYNAMIC_FILTER_ENABLER = "dynamicFilterEnabler"; - - 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"; - public static final String ARGUMENT_SORT = "sort"; - public static final String ORDER_DESC = "desc"; - public static final String ORDER_ASC = "asc"; - public static final String ARGUMENT_FETCH = "fetch"; - public static final String ARGUMENT_IGNORE_CASE = "ignoreCase"; - public static final String ARGUMENT_CACHE = "cache"; - public static final String ARGUMENT_LOCK = "lock"; - public static final String CONFIG_PROPERTY_CACHE_QUERIES = "grails.hibernate.cache.queries"; - public static final String CONFIG_PROPERTY_OSIV_READONLY = "grails.hibernate.osiv.readonly"; - public static final Class[] EMPTY_CLASS_ARRAY = {}; - - private static HibernateProxyHandler proxyHandler = new HibernateProxyHandler(); - - private static GrailsDomainBinder binder = new GrailsDomainBinder(); - - @SuppressWarnings("rawtypes") - public static void enableDynamicFilterEnablerIfPresent(SessionFactory sessionFactory, Session session) { - if (sessionFactory != null && session != null) { - final Set definedFilterNames = sessionFactory.getDefinedFilterNames(); - if (definedFilterNames != null && definedFilterNames.contains(DYNAMIC_FILTER_ENABLER)) - session.enableFilter(DYNAMIC_FILTER_ENABLER); // work around for HHH-2624 - } - } - - public static void configureHibernateDomainClasses(SessionFactory sessionFactory, - String sessionFactoryName, GrailsApplication application) { - Map hibernateDomainClassMap = new HashMap(); - for (Object o : sessionFactory.getAllClassMetadata().values()) { - ClassMetadata classMetadata = (ClassMetadata) o; - configureDomainClass(sessionFactory, sessionFactoryName, application, classMetadata, - classMetadata.getMappedClass(EntityMode.POJO), - hibernateDomainClassMap); - } - configureInheritanceMappings(hibernateDomainClassMap); - } - - @SuppressWarnings("rawtypes") - public static void configureInheritanceMappings(Map hibernateDomainClassMap) { - // now get through all domainclasses, and add all subclasses to root class - for (Object o : hibernateDomainClassMap.values()) { - GrailsDomainClass baseClass = (GrailsDomainClass) o; - if (!baseClass.isRoot()) { - Class superClass = baseClass.getClazz().getSuperclass(); - - while (!superClass.equals(Object.class) && !superClass.equals(GroovyObject.class)) { - GrailsDomainClass gdc = (GrailsDomainClass) hibernateDomainClassMap.get(superClass.getName()); - - if (gdc == null || gdc.getSubClasses() == null) { - LOG.debug("did not find superclass names when mapping inheritance...."); - break; - } - gdc.getSubClasses().add(baseClass); - superClass = superClass.getSuperclass(); - } - } - } - } - - private static void configureDomainClass(SessionFactory sessionFactory, String sessionFactoryName, - GrailsApplication application, ClassMetadata cmd, Class persistentClass, - Map hibernateDomainClassMap) { - LOG.trace("Configuring domain class [" + persistentClass + "]"); - GrailsDomainClass dc = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE, persistentClass.getName()); - if (dc == null && sessionFactory.getClassMetadata(persistentClass) != null) { - // a patch to add inheritance to this system - GrailsHibernateDomainClass ghdc = new GrailsHibernateDomainClass( - persistentClass, sessionFactory, sessionFactoryName, application, cmd); - - hibernateDomainClassMap.put(persistentClass.getName(), ghdc); - dc = (GrailsDomainClass) application.addArtefact(DomainClassArtefactHandler.TYPE, ghdc); - } - } - - public static void populateArgumentsForCriteria(GrailsApplication grailsApplication, Class targetClass, Criteria c, Map argMap, ConversionService conversionService) { - populateArgumentsForCriteria(grailsApplication, targetClass, c, argMap, conversionService, true); - } - - /** - * Populates criteria arguments for the given target class and arguments map - * - * @param grailsApplication the GrailsApplication instance - * @param targetClass The target class - * @param c The criteria instance - * @param argMap The arguments map - */ - @SuppressWarnings("rawtypes") - public static void populateArgumentsForCriteria(GrailsApplication grailsApplication, Class targetClass, Criteria c, Map argMap, ConversionService conversionService, boolean useDefaultMapping) { - Integer maxParam = null; - Integer offsetParam = null; - if (argMap.containsKey(ARGUMENT_MAX)) { - maxParam = conversionService.convert(argMap.get(ARGUMENT_MAX),Integer.class); - } - if (argMap.containsKey(ARGUMENT_OFFSET)) { - offsetParam = conversionService.convert(argMap.get(ARGUMENT_OFFSET),Integer.class); - } - if (argMap.containsKey(ARGUMENT_FETCH_SIZE)) { - c.setFetchSize(conversionService.convert(argMap.get(ARGUMENT_FETCH_SIZE),Integer.class)); - } - if (argMap.containsKey(ARGUMENT_TIMEOUT)) { - c.setTimeout(conversionService.convert(argMap.get(ARGUMENT_TIMEOUT),Integer.class)); - } - if (argMap.containsKey(ARGUMENT_FLUSH_MODE)) { - c.setFlushMode(convertFlushMode(argMap.get(ARGUMENT_FLUSH_MODE))); - } - if (argMap.containsKey(ARGUMENT_READ_ONLY)) { - c.setReadOnly(GrailsClassUtils.getBooleanFromMap(ARGUMENT_READ_ONLY, argMap)); - } - String orderParam = (String)argMap.get(ARGUMENT_ORDER); - Object fetchObj = argMap.get(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(ARGUMENT_LOCK, argMap)) { - c.setLockMode(LockMode.PESSIMISTIC_WRITE); - c.setCacheable(false); - } - else { - if (argMap.containsKey(ARGUMENT_CACHE)) { - c.setCacheable(GrailsClassUtils.getBooleanFromMap(ARGUMENT_CACHE, argMap)); - } else { - cacheCriteriaByMapping(targetClass, c); - } - } - - final Object sortObj = argMap.get(ARGUMENT_SORT); - if (sortObj != null) { - boolean ignoreCase = true; - Object caseArg = argMap.get(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 = ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? ORDER_DESC : ORDER_ASC; - addOrderPossiblyNested(grailsApplication, c, targetClass, (String) sort, order, ignoreCase); - } - } else { - final String sort = (String) sortObj; - final String order = ORDER_DESC.equalsIgnoreCase(orderParam) ? ORDER_DESC : ORDER_ASC; - addOrderPossiblyNested(grailsApplication, c, targetClass, sort, order, ignoreCase); - } - } - else if(useDefaultMapping) { - Mapping m = binder.getMapping(targetClass); - if (m != null) { - Map sortMap = m.getSort().getNamesAndDirections(); - for (Object sort : sortMap.keySet()) { - final String order = ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? ORDER_DESC : ORDER_ASC; - addOrderPossiblyNested(grailsApplication, c, targetClass, (String) sort, order, true); - } - } - } - } - - /** - * Populates criteria arguments for the given target class and arguments map - * - * @param targetClass The target class - * @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 - @SuppressWarnings("rawtypes") - public static void populateArgumentsForCriteria(Class targetClass, Criteria c, Map argMap, ConversionService conversionService) { - populateArgumentsForCriteria(null, targetClass, c, argMap, conversionService); - } - - @SuppressWarnings("rawtypes") - public static void populateArgumentsForCriteria(Criteria c, Map argMap, ConversionService conversionService) { - populateArgumentsForCriteria(null, null, c, argMap, conversionService); - } - - private static FlushMode convertFlushMode(Object object) { - if(object == null) { - return null; - } - if (object instanceof FlushMode) { - return (FlushMode)object; - } - return FlushMode.parse(String.valueOf(object)); - } - - /** - * Add order to criteria, creating necessary subCriteria if nested sort property (ie. sort:'nested.property'). - */ - private static void addOrderPossiblyNested(GrailsApplication grailsApplication, Criteria c, Class targetClass, 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); - GrailsDomainClassProperty property = getGrailsDomainClassProperty(grailsApplication, targetClass, sortHead); - if (property.isEmbedded()) { - // embedded objects cannot reference entities (at time of writing), so no more recursion needed - addOrder(c, sort, order, ignoreCase); - } else { - Criteria subCriteria = c.createCriteria(sortHead); - Class propertyTargetClass = property.getReferencedDomainClass().getClazz(); - GrailsHibernateUtil.cacheCriteriaByMapping(grailsApplication, propertyTargetClass, subCriteria); - addOrderPossiblyNested(grailsApplication, subCriteria, propertyTargetClass, sortTail, order, ignoreCase); // Recurse on nested sort - } - } - } - - /** - * Add order directly to criteria. - */ - private static void addOrder(Criteria c, String sort, String order, boolean ignoreCase) { - if (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)); - } - } - - /** - * Get hold of the GrailsDomainClassProperty represented by the targetClass' propertyName, - * assuming targetClass corresponds to a GrailsDomainClass. - */ - private static GrailsDomainClassProperty getGrailsDomainClassProperty(GrailsApplication grailsApplication, Class targetClass, String propertyName) { - GrailsClass grailsClass = grailsApplication != null ? grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, targetClass.getName()) : null; - if (!(grailsClass instanceof GrailsDomainClass)) { - throw new IllegalArgumentException("Unexpected: class is not a domain class:"+targetClass.getName()); - } - GrailsDomainClass domainClass = (GrailsDomainClass) grailsClass; - return domainClass.getPropertyByName(propertyName); - } - - /** - * Configures the criteria instance to cache based on the configured mapping. - * - * @param targetClass The target class - * @param criteria The criteria - */ - public static void cacheCriteriaByMapping(Class targetClass, Criteria criteria) { - Mapping m = binder.getMapping(targetClass); - if (m != null && m.getCache() != null && m.getCache().getEnabled()) { - criteria.setCacheable(true); - } - } - - public static void cacheCriteriaByMapping(GrailsApplication grailsApplication, Class targetClass, Criteria criteria) { - cacheCriteriaByMapping(targetClass, criteria); - } - - /** - * 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; - } - - /** - * Sets the target object to read-only using the given SessionFactory instance. This - * avoids Hibernate performing any dirty checking on the object - * - * @see #setObjectToReadWrite(Object, org.hibernate.SessionFactory) - * - * @param target The target object - * @param sessionFactory The SessionFactory instance - */ - public static void setObjectToReadyOnly(Object target, SessionFactory sessionFactory) { - Session session = sessionFactory.getCurrentSession(); - if (canModifyReadWriteState(session, target)) { - if (target instanceof HibernateProxy) { - target = ((HibernateProxy)target).getHibernateLazyInitializer().getImplementation(); - } - session.setReadOnly(target, true); - session.setFlushMode(FlushMode.MANUAL); - } - } - - private static boolean canModifyReadWriteState(Session session, Object target) { - return session.contains(target) && Hibernate.isInitialized(target); - } - - /** - * Sets the target object to read-write, allowing Hibernate to dirty check it and auto-flush changes. - * - * @see #setObjectToReadyOnly(Object, org.hibernate.SessionFactory) - * - * @param target The target object - * @param sessionFactory The SessionFactory instance - */ - public static void setObjectToReadWrite(final Object target, SessionFactory sessionFactory) { - GrailsHibernateTemplate template = new GrailsHibernateTemplate(sessionFactory); - template.setExposeNativeSession(true); - template.execute(new HibernateCallback() { - public Void doInHibernate(Session session) throws HibernateException, SQLException { - if (canModifyReadWriteState(session, target)) { - SessionImplementor sessionImpl = (SessionImplementor) session; - EntityEntry ee = sessionImpl.getPersistenceContext().getEntry(target); - - if (ee != null && ee.getStatus() == Status.READ_ONLY) { - Object actualTarget = target; - if (target instanceof HibernateProxy) { - actualTarget = ((HibernateProxy)target).getHibernateLazyInitializer().getImplementation(); - } - - session.setReadOnly(actualTarget, false); - session.setFlushMode(FlushMode.AUTO); - incrementVersion(target); - } - } - return null; - } - }); - } - - /** - * Increments the entities version number in order to force an update - * @param target The target entity - */ - public static void incrementVersion(Object target) { - MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(target.getClass()); - if (metaClass.hasProperty(target, GrailsDomainClassProperty.VERSION)!=null) { - Object version = metaClass.getProperty(target, GrailsDomainClassProperty.VERSION); - if (version instanceof Long) { - Long newVersion = (Long) version + 1; - metaClass.setProperty(target, GrailsDomainClassProperty.VERSION, newVersion); - } - } - } - - /** - * Ensures the meta class is correct for a given class - * - * @param target The GroovyObject - * @param persistentClass The persistent class - */ - public 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)); - } - } - } - - /** - * Unwraps and initializes a HibernateProxy. - * @param proxy The proxy - * @return the unproxied instance - */ - public static Object unwrapProxy(HibernateProxy proxy) { - return proxyHandler.unwrapProxy(proxy); - } - - /** - * Returns the proxy for a given association or null if it is not proxied - * - * @param obj The object - * @param associationName The named assoication - * @return A proxy - */ - public static HibernateProxy getAssociationProxy(Object obj, String associationName) { - return proxyHandler.getAssociationProxy(obj, associationName); - } - - /** - * Checks whether an associated property is initialized and returns true if it is - * - * @param obj The name of the object - * @param associationName The name of the association - * @return true if is initialized - */ - public static boolean isInitialized(Object obj, String associationName) { - return proxyHandler.isInitialized(obj, associationName); - } - - public static boolean isCacheQueriesByDefault() { - return isCacheQueriesByDefault(GrailsWebUtil.currentApplication()); - } - - public static boolean isCacheQueriesByDefault(GrailsApplication grailsApplication) { - return GrailsConfigUtils.isConfigTrue(grailsApplication, CONFIG_PROPERTY_CACHE_QUERIES); - } - - public static boolean isOsivReadonly(GrailsApplication grailsApplication) { - return GrailsConfigUtils.isConfigTrue(grailsApplication, CONFIG_PROPERTY_OSIV_READONLY); - } - - public static GroovyAwareJavassistProxyFactory buildProxyFactory(PersistentClass persistentClass) { - GroovyAwareJavassistProxyFactory proxyFactory = new GroovyAwareJavassistProxyFactory(); - - @SuppressWarnings("unchecked") - Set> proxyInterfaces = CollectionUtils.newSet(HibernateProxy.class); - - final Class javaClass = persistentClass.getMappedClass(); - final Property identifierProperty = persistentClass.getIdentifierProperty(); - final Getter idGetter = identifierProperty!=null? identifierProperty.getGetter(javaClass) : null; - final Setter idSetter = identifierProperty!=null? identifierProperty.getSetter(javaClass) : null; - - if (idGetter == null || idSetter == null) return null; - - try { - proxyFactory.postInstantiate(persistentClass.getEntityName(), javaClass, proxyInterfaces, - idGetter.getMethod(), idSetter.getMethod(), - persistentClass.hasEmbeddedIdentifier() ? - (CompositeType) persistentClass.getIdentifier().getType() : - null); - } - catch (HibernateException e) { - LOG.warn("Cannot instantiate proxy factory: " + e.getMessage()); - return null; - } - - return proxyFactory; - } - - public static Object unwrapIfProxy(Object instance) { - return proxyHandler.unwrapIfProxy(instance); - } - - public static boolean usesDatasource(GrailsDomainClass domainClass, String dataSourceName) { - if (domainClass instanceof GrailsHibernateDomainClass) { - GrailsHibernateDomainClass hibernateDomainClass = (GrailsHibernateDomainClass)domainClass; - String sessionFactoryName = hibernateDomainClass.getSessionFactoryName(); - if (dataSourceName.equals(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE)) { - return "sessionFactory".equals(sessionFactoryName); - } - return sessionFactoryName.endsWith("_" + dataSourceName); - } - - List names = getDatasourceNames(domainClass); - return names.contains(dataSourceName) || - names.contains(GrailsDomainClassProperty.ALL_DATA_SOURCES); - } - - /** - * If a domain class uses more than one datasource, we need to know which one to use - * when calling a method without a namespace qualifier. - * - * @param domainClass the domain class - * @return the default datasource name - */ - public static String getDefaultDataSource(GrailsDomainClass domainClass) { - if (domainClass instanceof GrailsHibernateDomainClass) { - GrailsHibernateDomainClass hibernateDomainClass = (GrailsHibernateDomainClass)domainClass; - String sessionFactoryName = hibernateDomainClass.getSessionFactoryName(); - if ("sessionFactory".equals(sessionFactoryName)) { - return GrailsDomainClassProperty.DEFAULT_DATA_SOURCE; - } - return sessionFactoryName.substring("sessionFactory_".length()); - } - - List names = getDatasourceNames(domainClass); - if (names.size() == 1 && GrailsDomainClassProperty.ALL_DATA_SOURCES.equals(names.get(0))) { - return GrailsDomainClassProperty.DEFAULT_DATA_SOURCE; - } - return names.get(0); - } - - public static List getDatasourceNames(GrailsDomainClass domainClass) { - // Mappings won't have been built yet when this is called from - // HibernatePluginSupport.doWithSpring so do a temporary evaluation but don't cache it - Mapping mapping = isMappedWithHibernate(domainClass) ? binder .evaluateMapping(domainClass, null, false) : null; - if (mapping == null) { - mapping = new Mapping(); - } - return mapping.getDatasources(); - } - - public static boolean isMappedWithHibernate(GrailsDomainClass domainClass) { - return domainClass instanceof GrailsHibernateDomainClass || domainClass.getMappingStrategy().equals( GrailsDomainClass.GORM ); - } - - public static void autoAssociateBidirectionalOneToOnes(DefaultGrailsDomainClass domainClass, Object target) { - List associations = domainClass.getAssociations(); - for (GrailsDomainClassProperty association : associations) { - if (!association.isOneToOne() || !association.isBidirectional() || !association.isOwningSide()) { - continue; - } - - if (!isInitialized(target, association.getName())) { - continue; - } - - GrailsDomainClassProperty otherSide = association.getOtherSide(); - if (otherSide == null) { - continue; - } - - BeanWrapper bean = new BeanWrapperImpl(target); - Object inverseObject = bean.getPropertyValue(association.getName()); - if (inverseObject == null) { - continue; - } - - if (!isInitialized(inverseObject, otherSide.getName())) { - continue; - } - - BeanWrapper inverseBean = new BeanWrapperImpl(inverseObject); - Object propertyValue = inverseBean.getPropertyValue(otherSide.getName()); - if (propertyValue == null) { - inverseBean.setPropertyValue(otherSide.getName(), target); - } - } - } - - public static String qualify(final String prefix, final String name) { - return StringHelper.qualify(prefix, name); - } - - public static boolean isNotEmpty(final String string) { - return StringHelper.isNotEmpty(string); - } - - public static String unqualify(final String qualifiedName) { - return StringHelper.unqualify(qualifiedName); - } -} 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 deleted file mode 100644 index ac08b6b36..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtils.groovy +++ /dev/null @@ -1,362 +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.cfg - -import grails.artefact.Enhanced -import grails.util.GrailsNameUtils -import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode - -import org.apache.commons.beanutils.PropertyUtils -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.plugins.DomainClassGrailsPlugin -import org.codehaus.groovy.runtime.InvokerHelper -import org.codehaus.groovy.runtime.StringGroovyMethods -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.hibernate.FlushMode -import org.hibernate.Session -import org.hibernate.SessionFactory -import org.hibernate.proxy.HibernateProxy -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.context.ApplicationContext -import org.springframework.core.convert.ConversionService -import org.springframework.dao.DataAccessException -import org.springframework.orm.hibernate3.HibernateCallback -import org.springframework.orm.hibernate3.HibernateTemplate -import org.springframework.transaction.PlatformTransactionManager - -//@CompileStatic -class HibernateUtils { - - static final Logger LOG = LoggerFactory.getLogger(HibernateUtils) - - /** - * Overrides a getter on a property that is a Hibernate proxy in order to make sure the initialized object is returned hence avoiding Hibernate proxy hell. - */ - static void handleLazyProxy(GrailsDomainClass domainClass, GrailsDomainClassProperty property) { - String propertyName = property.name - String getterName = GrailsClassUtils.getGetterName(propertyName) - String setterName = GrailsClassUtils.getSetterName(propertyName) - - GroovyObject mc = (GroovyObject)domainClass.metaClass - - mc.setProperty(getterName, {-> - def propertyValue = PropertyUtils.getProperty(getDelegate(), propertyName) - if (propertyValue instanceof HibernateProxy) { - propertyValue = GrailsHibernateUtil.unwrapProxy(propertyValue) - } - return propertyValue - }) - mc.setProperty(setterName, { PropertyUtils.setProperty(getDelegate(), propertyName, it) }) - - for (GrailsDomainClass sub in domainClass.subClasses) { - handleLazyProxy(sub, sub.getPropertyByName(property.name)) - } - } - - static void enhanceSessionFactories(ApplicationContext ctx, GrailsApplication grailsApplication, Object source = null) { - - Map datastores = [:] - - for (entry in ctx.getBeansOfType(SessionFactory).entrySet()) { - SessionFactory sessionFactory = entry.value - String beanName = entry.key - String suffix = beanName - 'sessionFactory' - enhanceSessionFactory sessionFactory, grailsApplication, ctx, suffix, datastores, source - } - - ctx.getBean("eventTriggeringInterceptor", ClosureEventTriggeringInterceptor).datastores = datastores - } - - static enhanceSessionFactory(SessionFactory sessionFactory, GrailsApplication application, ApplicationContext ctx) { - enhanceSessionFactory(sessionFactory, application, ctx, '', [:]) - } - - static enhanceSessionFactory(SessionFactory sessionFactory, GrailsApplication application, - ApplicationContext ctx, String suffix, Map datastores, Object source = null) { - - MappingContext mappingContext = ctx.getBean("grailsDomainClassMappingContext", MappingContext) - PlatformTransactionManager transactionManager = ctx.getBean("transactionManager$suffix", PlatformTransactionManager) - HibernateDatastore datastore = (HibernateDatastore)ctx.getBean("hibernateDatastore$suffix", Datastore) - datastores[sessionFactory] = datastore - String datasourceName = suffix ? suffix[1..-1] : GrailsDomainClassProperty.DEFAULT_DATA_SOURCE - - HibernateGormEnhancer enhancer = new HibernateGormEnhancer(datastore, transactionManager, application) - - def enhanceEntity = { PersistentEntity entity -> - GrailsDomainClass dc = (GrailsDomainClass)application.getArtefact(DomainClassArtefactHandler.TYPE, entity.javaClass.name) - if (!GrailsHibernateUtil.isMappedWithHibernate(dc) || !GrailsHibernateUtil.usesDatasource(dc, datasourceName)) { - return - } - - if (!datasourceName.equals(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE)) { - LOG.debug "Registering namespace methods for $dc.clazz.name in DataSource '$datasourceName'" - registerNamespaceMethods dc, datastore, datasourceName, transactionManager, application - } - - if (datasourceName.equals(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE) || datasourceName.equals(GrailsHibernateUtil.getDefaultDataSource(dc))) { - LOG.debug "Enhancing GORM entity ${entity.name}" - if (entity.javaClass.getAnnotation(Enhanced) == null) { - enhancer.enhance entity - } - else { - enhancer.enhance entity, true - } - - DomainClassGrailsPlugin.addRelationshipManagementMethods(dc, ctx) - } - } - - // If we are reloading via an onChange event, the source indicates the specific - // entity that needs to be reloaded. Otherwise, just reload all of them. - if (source) { - PersistentEntity entity = getPersistentEntity(mappingContext, InvokerHelper.getPropertySafe(source, 'name')?.toString()) - if (entity) { - enhanceEntity(entity) - } - } - else { - for (PersistentEntity entity in mappingContext.getPersistentEntities()) { - enhanceEntity(entity) - } - } - } - - // workaround CS bug - @CompileStatic(TypeCheckingMode.SKIP) - private static PersistentEntity getPersistentEntity(mappingContext, String name) { - mappingContext.getPersistentEntity(name) - } - - static 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 - } - - private static List removeNullNames(Map query) { - List nullNames = [] - Set allNames = new HashSet(query.keySet()) - for (String name in allNames) { - if (query[name] == null) { - query.remove name - nullNames << name - } - } - nullNames - } - - // 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) - if (grailsEnhancedMetaMethod != null && grailsEnhancedMetaMethod.invoke(proxyClass, null) == proxyClass) { - return - } - - MetaClass mc = (MetaClass)InvokerHelper.getMetaClass(proxyClass) - MetaClass superMc = InvokerHelper.getMetaClass(proxyClass.getSuperclass()) - - // hasProperty - registerMetaMethod(mc, 'hasProperty', { String name -> - Object obj = getDelegate() - boolean result = superMc.hasProperty(obj, name) - if (!result) { - Object unwrapped = GrailsHibernateUtil.unwrapProxy((HibernateProxy)obj) - result = unwrapped.getMetaClass().hasProperty(obj, name) - } - return result - }) - // respondsTo - registerMetaMethod(mc, 'respondsTo', { String name -> - Object obj = getDelegate() - def result = superMc.respondsTo(obj, name) - if (!result) { - Object unwrapped = GrailsHibernateUtil.unwrapProxy((HibernateProxy)obj) - result = unwrapped.getMetaClass().respondsTo(obj, name) - } - result - }) - registerMetaMethod(mc, 'respondsTo', { String name, Object[] args -> - Object obj = getDelegate() - def result = superMc.respondsTo(obj, name, args) - if (!result) { - Object unwrapped = GrailsHibernateUtil.unwrapProxy((HibernateProxy)obj) - result = unwrapped.getMetaClass().respondsTo(obj, name, args) - } - result - }) - - // setter - registerMetaMethod(mc, 'propertyMissing', { String name, Object val -> - Object obj = getDelegate() - try { - superMc.setProperty(proxyClass, obj, name, val, true, true) - } catch (MissingPropertyException e) { - Object unwrapped = GrailsHibernateUtil.unwrapProxy((HibernateProxy)obj) - unwrapped.getMetaClass().setProperty(unwrapped, name, val) - } - }) - - // getter - registerMetaMethod(mc, 'propertyMissing', { String name -> - Object obj = getDelegate() - try { - return superMc.getProperty(proxyClass, obj, name, true, true) - } catch (MissingPropertyException e) { - Object unwrapped = GrailsHibernateUtil.unwrapProxy((HibernateProxy)obj) - unwrapped.getMetaClass().getProperty(unwrapped, name) - } - }) - - registerMetaMethod(mc, 'methodMissing', { String name, Object args -> - Object obj = getDelegate() - Object[] argsArray = (Object[])args - try { - superMc.invokeMethod(proxyClass, obj, name, argsArray, true, true) - } catch (MissingMethodException e) { - Object unwrapped = GrailsHibernateUtil.unwrapProxy((HibernateProxy)obj) - unwrapped.getMetaClass().invokeMethod(unwrapped, name, argsArray) - } - }) - - mc.static.grailsEnhanced = {->proxyClass} - } - - @CompileStatic(TypeCheckingMode.SKIP) - private static final registerMetaMethod(MetaClass mc, String name, Closure c) { - mc."$name" = c - } - - static void enhanceProxy(HibernateProxy proxy) { - // no need to do anything here - } - - private static void registerNamespaceMethods(GrailsDomainClass dc, HibernateDatastore datastore, - String datasourceName, PlatformTransactionManager transactionManager, - GrailsApplication application) { - - String getter = GrailsNameUtils.getGetterName(datasourceName) - if (dc.metaClass.methods.any { MetaMethod it -> it.name == getter && it.parameterTypes.size() == 0 }) { - LOG.warn "The $dc.clazz.name domain class has a method '$getter' - unable to add namespaced methods for datasource '$datasourceName'" - return - } - - def classLoader = application.classLoader - - def finders = new HibernateGormEnhancer(datastore, transactionManager, application).getFinders() - def staticApi = new HibernateGormStaticApi(dc.clazz, datastore, finders, classLoader, transactionManager) - ((GroovyObject)((GroovyObject)dc.metaClass).getProperty('static')).setProperty(getter, { -> staticApi }) - - def validateApi = new HibernateGormValidationApi(dc.clazz, datastore, classLoader) - def instanceApi = new HibernateGormInstanceApi(dc.clazz, datastore, classLoader) - ((GroovyObject)dc.metaClass).setProperty(getter, { -> new InstanceProxy(getDelegate(), instanceApi, validateApi) }) - } - - /** - * Session should no longer be flushed after a data access exception occurs (such a constriant violation) - */ - static void handleDataAccessException(HibernateTemplate template, DataAccessException e) { - try { - template.execute({Session session -> - session.setFlushMode(FlushMode.MANUAL) - } as HibernateCallback) - } - finally { - throw e - } - } - - static shouldFlush(GrailsApplication application, Map map = [:]) { - def shouldFlush - - if (map?.containsKey('flush')) { - shouldFlush = Boolean.TRUE == map.flush - } else { - def config = application.flatConfig - shouldFlush = Boolean.TRUE == config.get('grails.gorm.autoFlush') - } - return shouldFlush - } - - /** - * Converts an id value to the appropriate type for a domain class. - * - * @param grailsDomainClass a GrailsDomainClass - * @param idValue an value to be converted - * @return the idValue parameter converted to the type that grailsDomainClass expects - * its identifiers to be - */ - static Object convertValueToIdentifierType(GrailsDomainClass grailsDomainClass, Object idValue, ConversionService conversionService) { - convertValueToType(idValue, grailsDomainClass.identifier.type, conversionService) - } - - 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/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/IdentityEnumType.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/IdentityEnumType.java deleted file mode 100644 index 787812af6..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/IdentityEnumType.java +++ /dev/null @@ -1,221 +0,0 @@ -/* 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.cfg; - -import grails.util.GrailsWebUtil; - -import java.io.Serializable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Collections; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import org.hibernate.HibernateException; -import org.hibernate.MappingException; -import org.hibernate.type.AbstractStandardBasicType; -import org.hibernate.type.TypeResolver; -import org.hibernate.usertype.ParameterizedType; -import org.hibernate.usertype.UserType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Hibernate Usertype that enum values by their ID. - * - * @author Siegfried Puchbauer - * @since 1.1 - */ -public class IdentityEnumType implements UserType, ParameterizedType, Serializable { - - private static final long serialVersionUID = -6625622185856547501L; - - private static final Logger LOG = LoggerFactory.getLogger(IdentityEnumType.class); - - private static TypeResolver typeResolver = new TypeResolver(); - public static final String ENUM_ID_ACCESSOR = "getId"; - - public static final String PARAM_ENUM_CLASS = "enumClass"; - - private static final Map>, BidiEnumMap> ENUM_MAPPINGS = new HashMap>, BidiEnumMap>(); - private Class> enumClass; - private BidiEnumMap bidiMap; - private AbstractStandardBasicType type; - private int[] sqlTypes; - - public static BidiEnumMap getBidiEnumMap(Class> cls) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - BidiEnumMap m = ENUM_MAPPINGS.get(cls); - if (m == null) { - synchronized (ENUM_MAPPINGS) { - if (!ENUM_MAPPINGS.containsKey(cls)) { - m = new BidiEnumMap(cls); - ENUM_MAPPINGS.put(cls, m); - } - else { - m = ENUM_MAPPINGS.get(cls); - } - } - } - return m; - } - - public static boolean isEnabled() { - Object disableConfigOption = GrailsWebUtil.currentFlatConfiguration().get("grails.orm.enum.id.mapping"); - return disableConfigOption == null || !(Boolean.FALSE.equals(disableConfigOption)); - } - - @SuppressWarnings("unchecked") - public static boolean supports(@SuppressWarnings("rawtypes") Class enumClass) { - if (!isEnabled()) return false; - if (enumClass.isEnum()) { - try { - Method idAccessor = enumClass.getMethod(ENUM_ID_ACCESSOR); - int mods = idAccessor.getModifiers(); - if (Modifier.isPublic(mods) && !Modifier.isStatic(mods)) { - Class returnType = idAccessor.getReturnType(); - return returnType != null && typeResolver.basic(returnType.getName()) instanceof AbstractStandardBasicType; - } - } - catch (NoSuchMethodException e) { - // ignore - } - } - return false; - } - - @SuppressWarnings("unchecked") - public void setParameterValues(Properties properties) { - try { - enumClass = (Class>)Thread.currentThread().getContextClassLoader().loadClass( - (String)properties.get(PARAM_ENUM_CLASS)); - if (LOG.isDebugEnabled()) { - LOG.debug(String.format("Building ID-mapping for Enum Class %s", enumClass.getName())); - } - bidiMap = getBidiEnumMap(enumClass); - type = (AbstractStandardBasicType)typeResolver.basic(bidiMap.keyType.getName()); - if (LOG.isDebugEnabled()) { - LOG.debug(String.format("Mapped Basic Type is %s", type)); - } - sqlTypes = type.sqlTypes(null); - } - catch (Exception e) { - throw new MappingException("Error mapping Enum Class using IdentifierEnumType", e); - } - } - - public int[] sqlTypes() { - return sqlTypes; - } - - public Class returnedClass() { - return enumClass; - } - - public boolean equals(Object o1, Object o2) throws HibernateException { - return o1 == o2; - } - - public int hashCode(Object o) throws HibernateException { - return o.hashCode(); - } - - public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException { - Object id = type.nullSafeGet(resultSet, names[0], null); - if ((!resultSet.wasNull()) && id != null) { - return bidiMap.getEnumValue(id); - } - return null; - } - - public void nullSafeSet(PreparedStatement pstmt, Object value, int idx) throws HibernateException, SQLException { - if (value == null) { - pstmt.setNull(idx, sqlTypes[0]); - } - else { - type.nullSafeSet(pstmt, bidiMap.getKey(value), idx, null); - } - } - - public Object deepCopy(Object o) throws HibernateException { - return o; - } - - public boolean isMutable() { - return false; - } - - public Serializable disassemble(Object o) throws HibernateException { - return (Serializable) o; - } - - public Object assemble(Serializable cached, Object owner) throws HibernateException { - return cached; - } - - public Object replace(Object orig, Object target, Object owner) throws HibernateException { - return orig; - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - private static class BidiEnumMap implements Serializable { - - private static final long serialVersionUID = 3325751131102095834L; - private final Map enumToKey; - private final Map keytoEnum; - private Class keyType; - - private BidiEnumMap(Class enumClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - if (LOG.isDebugEnabled()) { - LOG.debug(String.format("Building Bidirectional Enum Map...")); - } - - EnumMap enumToKey = new EnumMap(enumClass); - HashMap keytoEnum = new HashMap(); - - Method idAccessor = enumClass.getMethod(ENUM_ID_ACCESSOR); - - keyType = idAccessor.getReturnType(); - - Method valuesAccessor = enumClass.getMethod("values"); - Object[] values = (Object[]) valuesAccessor.invoke(enumClass); - - for (Object value : values) { - Object id = idAccessor.invoke(value); - enumToKey.put((Enum) value, id); - if (keytoEnum.containsKey(id)) { - LOG.warn(String.format("Duplicate Enum ID '%s' detected for Enum %s!", id, enumClass.getName())); - } - keytoEnum.put(id, value); - } - - this.enumToKey = Collections.unmodifiableMap(enumToKey); - this.keytoEnum = Collections.unmodifiableMap(keytoEnum); - } - - public Object getEnumValue(Object id) { - return keytoEnum.get(id); - } - - public Object getKey(Object enumValue) { - return enumToKey.get(enumValue); - } - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/events/PatchedDefaultFlushEventListener.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/events/PatchedDefaultFlushEventListener.java deleted file mode 100644 index d98e8e89d..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/events/PatchedDefaultFlushEventListener.java +++ /dev/null @@ -1,57 +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.events; - -import org.hibernate.HibernateException; -import org.hibernate.event.EventSource; -import org.hibernate.event.def.DefaultFlushEventListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Patches Hibernate to prevent this issue - * http://opensource.atlassian.com/projects/hibernate/browse/HHH-2763 - * - * TODO: Remove this patch when HHH-2763 is resolved - * - * @author Graeme Rocher - * @since 1.2 - */ -public class PatchedDefaultFlushEventListener extends DefaultFlushEventListener{ - - private static final long serialVersionUID = -7413770767669684078L; - private static final Logger LOG = LoggerFactory.getLogger(PatchedDefaultFlushEventListener.class); - - @Override - protected void performExecutions(EventSource session) throws HibernateException { - session.getPersistenceContext().setFlushing(true); - try { - session.getJDBCContext().getConnectionManager().flushBeginning(); - // we need to lock the collection caches before - // executing entity inserts/updates in order to - // account for bidi associations - session.getActionQueue().prepareActions(); - session.getActionQueue().executeActions(); - } - catch (HibernateException he) { - LOG.error("Could not synchronize database state with session", he); - throw he; - } - finally { - session.getPersistenceContext().setFlushing(false); - session.getJDBCContext().getConnectionManager().flushEnding(); - } - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/events/SaveOrUpdateEventListener.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/events/SaveOrUpdateEventListener.java deleted file mode 100644 index a6673195b..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/events/SaveOrUpdateEventListener.java +++ /dev/null @@ -1,28 +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.events; - -import org.hibernate.event.def.DefaultSaveOrUpdateEventListener; - -/** - * Intermediary class, because def in package name is blocking IntelliJ from compiling. - * Seems to be an intellij bug not a Groovy one - * - * @author Graeme Rocher - * @since 1.1 - */ -public class SaveOrUpdateEventListener extends DefaultSaveOrUpdateEventListener { - private static final long serialVersionUID = 5329080291582964284L; -} 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 95cfcc20b..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractClausedStaticPersistentMethod.java +++ /dev/null @@ -1,537 +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 java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Locale; -import java.util.regex.Matcher; -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.commons.GrailsDomainClassProperty; -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.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.TypeMismatchException; -import org.springframework.core.convert.ConversionService; -import org.springframework.util.Assert; - -/** - * @author Graeme Rocher - * @since 31-Aug-2005 - */ -public abstract class AbstractClausedStaticPersistentMethod extends AbstractStaticPersistentMethod { - - private static final Logger LOG = LoggerFactory.getLogger(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++) { - if (args[i] == null) continue; - // convert GStrings to strings - if (prop.getType() == String.class && (args[i] instanceof CharSequence)) { - args[i] = args[i].toString(); - } - else if (!prop.getType().isAssignableFrom(args[i].getClass()) && !(GrailsClassUtils.isMatchBetweenPrimativeAndWrapperTypes(prop.getType(), args[i].getClass()))) { - try { - if (type.equals(IN_LIST)) { - args[i] = conversionService.convert(args[i], Collection.class); - } - else { - args[i] = conversionService.convert(args[i], 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(args[i].getClass())) { - try { - args[i] = conversionService.convert(args[i].toString(), prop.getType()); - } - catch(TypeMismatchException tme1) { - throw new IllegalArgumentException("Cannot convert value " + args[i] + " of property '"+propertyName+"' to required type " + prop.getType() + ": " + tme1.getMessage()); - } - } - else { - throw new IllegalArgumentException("Cannot convert value " + args[i] + " of property '"+propertyName+"' to required type " + prop.getType()); - } - } - } - } - - arguments = args; - } - - 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) { - super(sessionFactory, classLoader, pattern, application); - 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 expressions = new ArrayList(); - 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 bf079e494..000000000 --- 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; - - public AbstractDynamicPersistentMethod(Pattern pattern, SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application) { - 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); - } - - 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. Note that the binding errors - * will no longer be flagged as binding errors - * - * @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 90fd77547..000000000 --- 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 useLimitCache = new ConcurrentHashMap(); - - public AbstractFindByPersistentMethod(HibernateDatastore datastore, GrailsApplication application, - SessionFactory sessionFactory, ClassLoader classLoader, - Pattern pattern, String[] operators) { - super(application, sessionFactory, classLoader, pattern, operators, datastore.getMappingContext().getConversionService()); - 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() { - 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 ab61484f7..000000000 --- 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> disableAutoValidationFor = new ThreadLocal>(); - - static { - ShutdownOperations.addOperation(new Runnable() { - public void run() { - disableAutoValidationFor.remove(); - } - }); - } - - private static Set getDisableAutoValidationFor() { - Set identifiers = disableAutoValidationFor.get(); - if (identifiers == null) - disableAutoValidationFor.set(identifiers = new HashSet()); - return identifiers; - } - - public static boolean isAutoValidationDisabled(Object obj) { - Set 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); - - 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 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 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 2d803ac96..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractStaticPersistentMethod.java +++ /dev/null @@ -1,120 +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) { - 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); - } - - 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()); - 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/BeforeValidateHelper.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/BeforeValidateHelper.java deleted file mode 100644 index fd58fbc34..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/BeforeValidateHelper.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.codehaus.groovy.grails.orm.hibernate.metaclass; - -/** - * @deprecated Here for backwards compatibility, use {@link org.grails.datastore.gorm.support.BeforeValidateHelper} instead - */ -public class BeforeValidateHelper extends org.grails.datastore.gorm.support.BeforeValidateHelper { -} 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 ee712448d..000000000 --- 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()); - 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() { - 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)expressions) { - dis.add(current.getCriterion()); - } - crit.add(dis); - } - else { - for (GrailsMethodExpression current : (List)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 17bca3a8b..000000000 --- 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. - *

    - * 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 http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html - * @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 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) { - super(sessionFactory, classLoader, METHOD_PATTERN, application); - 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() { - 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 777ce5e42..000000000 --- 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. - *

    - * 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) { - super(sessionFactory, classLoader, METHOD_PATTERN, application); - } - - @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)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 985fe1eac..000000000 --- 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 "findAllBy*" 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 1185ad615..000000000 --- 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()); - 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() { - 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 b54628a62..000000000 --- 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; - -/** - *

    - * 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. - *

    - * Syntax: - * DomainClass.findAll(query, params?) - * DomainClass.findAll(query, params?, max) - * DomainClass.findAll(query, params?, max, offset) - * DomainClass.findAll(query, params?, [max:10, offset:5]) - * - *

    - * Examples in Groovy: - * // 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) - * - * - * - * @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) { - super(sessionFactory, classLoader, Pattern.compile("^findAll$"), application); - 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() { - 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() { - 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() { - 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 ed086a55f..000000000 --- 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 "findBy*" 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 973df9926..000000000 --- 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 306f352c0..000000000 --- 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 bae77133e..000000000 --- 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 7abcc762f..000000000 --- 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; - -/** - *

    - * 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. - * - *

    - * Examples in Groovy: - * // 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) - * - * - * - * @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) { - super(sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), application); - 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() { - 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() { - 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 ee063fcb9..000000000 --- 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); - 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() { - 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 1a581d957..000000000 --- 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) { - super(sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), grailsApplication); - 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() { - 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 4c2cc8a41..000000000 --- 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() { - 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 3329d965c..000000000 --- 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() { - 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() { - 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 33d31afcc..000000000 --- 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); - 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/persister/entity/GroovyAwareJoinedSubclassEntityPersister.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/persister/entity/GroovyAwareJoinedSubclassEntityPersister.java deleted file mode 100644 index 33d5e7f08..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/persister/entity/GroovyAwareJoinedSubclassEntityPersister.java +++ /dev/null @@ -1,54 +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.persister.entity; - -import java.io.Serializable; - -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwareJavassistProxyFactory; -import org.hibernate.HibernateException; -import org.hibernate.cache.access.EntityRegionAccessStrategy; -import org.hibernate.engine.Mapping; -import org.hibernate.engine.SessionFactoryImplementor; -import org.hibernate.engine.SessionImplementor; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.persister.entity.JoinedSubclassEntityPersister; - -/** - * A customized EntityPersister that creates proxies valid for use with Groovy. - * - * @author Graeme Rocher - * @since 1.1.1 - */ -public class GroovyAwareJoinedSubclassEntityPersister extends JoinedSubclassEntityPersister { - - private GroovyAwareJavassistProxyFactory proxyFactory; - - public GroovyAwareJoinedSubclassEntityPersister(PersistentClass persistentClass, - EntityRegionAccessStrategy cacheAccessStrategy, SessionFactoryImplementor factory, - Mapping mapping) throws HibernateException { - super(persistentClass, cacheAccessStrategy, factory, mapping); - proxyFactory = GrailsHibernateUtil.buildProxyFactory(persistentClass); - } - - @Override - public Object createProxy(Serializable id, SessionImplementor session) throws HibernateException { - if (proxyFactory != null) { - return proxyFactory.getProxy(id,session); - } - - return super.createProxy(id, session); - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/persister/entity/GroovyAwareSingleTableEntityPersister.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/persister/entity/GroovyAwareSingleTableEntityPersister.java deleted file mode 100644 index 179757f62..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/persister/entity/GroovyAwareSingleTableEntityPersister.java +++ /dev/null @@ -1,54 +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.persister.entity; - -import java.io.Serializable; - -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwareJavassistProxyFactory; -import org.hibernate.HibernateException; -import org.hibernate.cache.access.EntityRegionAccessStrategy; -import org.hibernate.engine.Mapping; -import org.hibernate.engine.SessionFactoryImplementor; -import org.hibernate.engine.SessionImplementor; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.persister.entity.SingleTableEntityPersister; - -/** - * A customized EntityPersister that creates proxies valid for use with Groovy. - * - * @author Graeme Rocher - * @since 1.1.1 - */ -public class GroovyAwareSingleTableEntityPersister extends SingleTableEntityPersister { - - private GroovyAwareJavassistProxyFactory proxyFactory; - - public GroovyAwareSingleTableEntityPersister(PersistentClass persistentClass, - EntityRegionAccessStrategy cacheAccessStrategy, SessionFactoryImplementor factory, - Mapping mapping) throws HibernateException { - super(persistentClass, cacheAccessStrategy, factory, mapping); - proxyFactory = GrailsHibernateUtil.buildProxyFactory(persistentClass); - } - - @Override - public Object createProxy(Serializable id, SessionImplementor session) throws HibernateException { - if (proxyFactory != null) { - return proxyFactory.getProxy(id,session); - } - - return super.createProxy(id, session); - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwareJavassistLazyInitializer.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwareJavassistLazyInitializer.java deleted file mode 100644 index 35c1330f9..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwareJavassistLazyInitializer.java +++ /dev/null @@ -1,246 +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.proxy; - -import grails.util.CollectionUtils; -import groovy.lang.GroovyObject; - -import java.io.Serializable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import javassist.util.proxy.MethodFilter; -import javassist.util.proxy.MethodHandler; -import javassist.util.proxy.ProxyFactory; -import javassist.util.proxy.ProxyObject; - -import org.codehaus.groovy.grails.orm.hibernate.cfg.HibernateUtils; -import org.grails.datastore.mapping.proxy.GroovyObjectMethodHandler; -import org.hibernate.HibernateException; -import org.hibernate.engine.SessionImplementor; -import org.hibernate.proxy.HibernateProxy; -import org.hibernate.proxy.pojo.BasicLazyInitializer; -import org.hibernate.proxy.pojo.javassist.SerializableProxy; -import org.hibernate.type.CompositeType; -import org.hibernate.util.ReflectHelper; -import org.slf4j.LoggerFactory; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public class GroovyAwareJavassistLazyInitializer extends BasicLazyInitializer implements MethodHandler { - - private static final String WRITE_CLASSES_DIRECTORY = System.getProperty("javassist.writeDirectory"); - - private static final Set GROOVY_METHODS = CollectionUtils.newSet("$getStaticMetaClass"); - - private static final MethodFilter METHOD_FILTERS = new MethodFilter() { - public boolean isHandled(Method m) { - // skip finalize methods - return m.getName().indexOf("super$") == -1 && - !GROOVY_METHODS.contains(m.getName()) && - !(m.getParameterTypes().length == 0 && (m.getName().equals("finalize"))); - } - }; - - private Class[] interfaces; - private boolean constructed = false; - HibernateGroovyObjectMethodHandler groovyObjectMethodHandler; - - protected GroovyAwareJavassistLazyInitializer( - final String entityName, - final Class persistentClass, - final Class[] interfaces, - final Serializable id, - final Method getIdentifierMethod, - final Method setIdentifierMethod, - final CompositeType componentIdType, - final SessionImplementor session) { - super(entityName, persistentClass, id, getIdentifierMethod, setIdentifierMethod, componentIdType, session); - this.interfaces = interfaces; - } - - public static HibernateProxy getProxy( - final String entityName, - final Class persistentClass, - final Class[] interfaces, - final Method getIdentifierMethod, - final Method setIdentifierMethod, - CompositeType componentIdType, - final Serializable id, - final SessionImplementor session) throws HibernateException { - // note: interface is assumed to already contain HibernateProxy.class - final GroovyAwareJavassistLazyInitializer instance = new GroovyAwareJavassistLazyInitializer(entityName, - persistentClass, interfaces, id, getIdentifierMethod, setIdentifierMethod, componentIdType, session); - Class proxyClass = getProxyFactory(persistentClass, interfaces); - return createProxyInstance(proxyClass, instance); - } - - protected static HibernateProxy createProxyInstance(Class proxyClass, - final GroovyAwareJavassistLazyInitializer instance) { - final HibernateProxy proxy; - try { - proxy = (HibernateProxy)proxyClass.newInstance(); - } catch (Exception e) { - throw new HibernateException("Javassist Enhancement failed: " + proxyClass.getName(), e); - } - ((ProxyObject) proxy).setHandler(instance); - instance.groovyObjectMethodHandler = new HibernateGroovyObjectMethodHandler(proxyClass, proxy); - HibernateUtils.enhanceProxy(proxy); - instance.constructed = true; - return proxy; - } - - public static HibernateProxy getProxy( - final Class factory, - final String entityName, - final Class persistentClass, - final Class[] interfaces, - final Method getIdentifierMethod, - final Method setIdentifierMethod, - final CompositeType componentIdType, - final Serializable id, - final SessionImplementor session) throws HibernateException { - - final GroovyAwareJavassistLazyInitializer instance = new GroovyAwareJavassistLazyInitializer( - entityName, - persistentClass, - interfaces, id, - getIdentifierMethod, - setIdentifierMethod, - componentIdType, - session); - - return createProxyInstance(factory, instance); - } - - public static Class getProxyFactory(Class persistentClass, Class[] interfaces) throws HibernateException { - // note: interfaces is assumed to already contain HibernateProxy.class - - try { - Set> allInterfaces = new HashSet>(); - if(interfaces != null) { - allInterfaces.addAll(Arrays.asList(interfaces)); - } - allInterfaces.add(GroovyObject.class); - ProxyFactory factory = createProxyFactory(persistentClass, allInterfaces.toArray(new Class[allInterfaces.size()])); - Class proxyClass = factory.createClass(); - HibernateUtils.enhanceProxyClass(proxyClass); - return proxyClass; - } - catch (Throwable t) { - LoggerFactory.getLogger(BasicLazyInitializer.class).error( - "Javassist Enhancement failed: " + persistentClass.getName(), t); - throw new HibernateException("Javassist Enhancement failed: " + persistentClass.getName(), t); - } - } - - private static ProxyFactory createProxyFactory(Class persistentClass, Class[] interfaces) { - ProxyFactory factory = new ProxyFactory(); - factory.setSuperclass(persistentClass); - factory.setInterfaces(interfaces); - factory.setFilter(METHOD_FILTERS); - factory.setUseCache(true); - if (WRITE_CLASSES_DIRECTORY != null) { - factory.writeDirectory = WRITE_CLASSES_DIRECTORY; - } - return factory; - } - - public Object invoke(final Object proxy, final Method thisMethod, final Method proceed, - final Object[] args) throws Throwable { - Object result = groovyObjectMethodHandler.handleInvocation(proxy, thisMethod, args); - if (groovyObjectMethodHandler.wasHandled(result)) { - return result; - } - - if (constructed) { - try { - result = invoke(thisMethod, args, proxy); - } - catch (Throwable t) { - throw new Exception(t.getCause()); - } - if (result == INVOKE_IMPLEMENTATION) { - Object target = getImplementation(); - final Object returnValue; - try { - if (ReflectHelper.isPublic(persistentClass, thisMethod)) { - if (!thisMethod.getDeclaringClass().isInstance(target)) { - throw new ClassCastException(target.getClass().getName()); - } - returnValue = thisMethod.invoke(target, args); - } - else { - if (!thisMethod.isAccessible()) { - thisMethod.setAccessible(true); - } - returnValue = thisMethod.invoke(target, args); - } - return returnValue == target ? proxy : returnValue; - } - catch (InvocationTargetException ite) { - throw ite.getTargetException(); - } - } - return result; - } - - // while constructor is running - if (thisMethod.getName().equals("getHibernateLazyInitializer")) { - return this; - } - - return proceed.invoke(proxy, args); - } - - @Override - protected Object serializableProxy() { - return new SerializableProxy( - getEntityName(), - persistentClass, - interfaces, - getIdentifier(), - false, - getIdentifierMethod, - setIdentifierMethod, - componentIdType); - } - - private static class HibernateGroovyObjectMethodHandler extends GroovyObjectMethodHandler { - private Object target; - private final Object originalSelf; - - public HibernateGroovyObjectMethodHandler(Class proxyClass, Object originalSelf) { - super(proxyClass); - this.originalSelf = originalSelf; - } - - @Override - protected Object resolveDelegate(Object self) { - if (self != originalSelf) { - throw new IllegalStateException("self instance has changed."); - } - if (target == null) { - target = ((HibernateProxy)self).getHibernateLazyInitializer().getImplementation(); - } - return target; - } - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwareJavassistProxyFactory.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwareJavassistProxyFactory.java deleted file mode 100644 index 72b63557f..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwareJavassistProxyFactory.java +++ /dev/null @@ -1,75 +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.proxy; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.Set; - -import org.hibernate.HibernateException; -import org.hibernate.engine.SessionImplementor; -import org.hibernate.proxy.HibernateProxy; -import org.hibernate.proxy.ProxyFactory; -import org.hibernate.type.CompositeType; - -/** - * Hibernate's default proxying mechanism proxies Groovy's getMetaClass() method. To avoid this - * we customize the proxying creation proxy here and in #GroovyAwareJavassistLazyInitializer. - * - * @author Graeme Rocher - * @since 1.1.1 - */ -public class GroovyAwareJavassistProxyFactory implements ProxyFactory, Serializable { - - private static final long serialVersionUID = 8959336753472691947L; - protected static final Class[] NO_CLASSES = {}; - private Class persistentClass; - private String entityName; - private Class[] interfaces; - private Method getIdentifierMethod; - private Method setIdentifierMethod; - private CompositeType componentIdType; - private Class factory; - - @SuppressWarnings({"unchecked", "rawtypes"}) - public void postInstantiate( - final String entityName, - final Class persistentClass, - final Set interfaces, - final Method getIdentifierMethod, - final Method setIdentifierMethod, - final CompositeType componentIdType) throws HibernateException { - this.entityName = entityName; - this.persistentClass = persistentClass; - this.interfaces = (Class[])interfaces.toArray(NO_CLASSES); - this.getIdentifierMethod = getIdentifierMethod; - this.setIdentifierMethod = setIdentifierMethod; - this.componentIdType = componentIdType; - factory = GroovyAwareJavassistLazyInitializer.getProxyFactory(persistentClass, this.interfaces); - } - - public HibernateProxy getProxy(Serializable id, SessionImplementor session) throws HibernateException { - return GroovyAwareJavassistLazyInitializer.getProxy( - factory, - entityName, - persistentClass, - interfaces, - getIdentifierMethod, - setIdentifierMethod, - componentIdType, - id, - session); - } -} 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 deleted file mode 100644 index f6c2d8eae..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/HibernateProxyHandler.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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 java.lang.reflect.InvocationTargetException; - -import org.apache.commons.beanutils.PropertyUtils; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.support.proxy.EntityProxyHandler; -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. - * - * @author Graeme Rocher - * @since 1.2.2 - */ -public class HibernateProxyHandler implements EntityProxyHandler { - - 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 = PropertyUtils.getProperty(obj, associationName); - return Hibernate.isInitialized(proxy); - } - catch (IllegalAccessException e) { - return false; - } - catch (InvocationTargetException e) { - return false; - } - catch (NoSuchMethodException e) { - return false; - } - } - - 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 = PropertyUtils.getProperty(obj, associationName); - if (proxy instanceof HibernateProxy) { - return (HibernateProxy) proxy; - } - return null; - } - catch (IllegalAccessException e) { - return null; - } - catch (InvocationTargetException e) { - return null; - } - catch (NoSuchMethodException e) { - return null; - } - } - - public boolean isProxy(Object o) { - return (o instanceof HibernateProxy) || (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) { - 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); - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateCriterionAdapter.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateCriterionAdapter.java deleted file mode 100644 index d765f4f86..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateCriterionAdapter.java +++ /dev/null @@ -1,46 +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.codehaus.groovy.grails.orm.hibernate.query; - -import grails.orm.HibernateCriteriaBuilder; -import grails.orm.RlikeExpression; - -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.hibernate.criterion.Criterion; - -/** - * @author Graeme Rocher - * @since 2.0 - */ -public class HibernateCriterionAdapter extends AbstractHibernateCriterionAdapter { - - public HibernateCriterionAdapter(PersistentEntity entity, Query.Criterion criterion, String alias) { - super(entity, criterion, alias); - } - - public HibernateCriterionAdapter(Query.Criterion criterion) { - super(criterion); - } - - protected Criterion createRlikeExpression(String propertyName, String pattern) { - return new RlikeExpression(propertyName, pattern); - } - - protected Object getHibernateDetachedCriteria(QueryableCriteria value) { - return HibernateCriteriaBuilder.getHibernateDetachedCriteria(value); - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateQuery.java deleted file mode 100644 index 1d62a3895..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateQuery.java +++ /dev/null @@ -1,113 +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.codehaus.groovy.grails.orm.hibernate.query; - -import grails.orm.HibernateCriteriaBuilder; -import grails.orm.RlikeExpression; - -import java.sql.SQLException; -import java.util.Iterator; -import java.util.List; - -import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateSession; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.HibernateSession; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.DetachedCriteria; -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.function.SQLFunction; -import org.hibernate.engine.SessionFactoryImplementor; -import org.hibernate.impl.CriteriaImpl; -import org.hibernate.persister.entity.PropertyMapping; -import org.hibernate.type.BasicType; -import org.hibernate.type.TypeResolver; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * Bridges the Query API with the Hibernate Criteria API - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class HibernateQuery extends AbstractHibernateQuery { - - public HibernateQuery(Criteria criteria, AbstractHibernateSession session, PersistentEntity entity) { - super(criteria, session, entity); - } - - public HibernateQuery(Criteria subCriteria, AbstractHibernateSession session, PersistentEntity associatedEntity, String newAlias) { - super(subCriteria, session, associatedEntity, newAlias); - } - - protected AbstractHibernateCriterionAdapter createHibernateCriterionAdapter(PersistentEntity entity, Criterion c, String alias) { - return new HibernateCriterionAdapter(entity, c, alias); - } - - protected org.hibernate.criterion.Criterion createRlikeExpression(String propertyName, String value) { - return new RlikeExpression(propertyName, value); - } - - protected void setDetachedCriteriaValue(QueryableCriteria value, PropertyCriterion pc) { - DetachedCriteria hibernateDetachedCriteria = HibernateCriteriaBuilder.getHibernateDetachedCriteria(value); - pc.setValue(hibernateDetachedCriteria); - } - - protected String render(BasicType basic, List columns, SessionFactory sessionFactory, SQLFunction sqlFunction) { - return sqlFunction.render(basic, columns, (SessionFactoryImplementor) sessionFactory); - } - - protected PropertyMapping getEntityPersister(String name, SessionFactory sessionFactory) { - return (PropertyMapping) ((SessionFactoryImplementor) sessionFactory).getEntityPersister(name); - } - - protected TypeResolver getTypeResolver(SessionFactory sessionFactory) { - return ((SessionFactoryImplementor) sessionFactory).getTypeResolver(); - } - - protected Dialect getDialect(SessionFactory sessionFactory) { - return ((SessionFactoryImplementor) sessionFactory).getDialect(); - } - - @Override - public Object clone() { - final CriteriaImpl impl = (CriteriaImpl) criteria; - final HibernateSession hibernateSession = (HibernateSession) getSession(); - final GrailsHibernateTemplate hibernateTemplate = (GrailsHibernateTemplate) hibernateSession.getNativeInterface(); - return hibernateTemplate.execute(new HibernateCallback() { - @Override - public HibernateQuery doInHibernate(Session session) throws HibernateException, SQLException { - Criteria newCriteria = session.createCriteria(impl.getEntityOrClassName()); - - Iterator iterator = impl.iterateExpressionEntries(); - while (iterator.hasNext()) { - CriteriaImpl.CriterionEntry entry = (CriteriaImpl.CriterionEntry) iterator.next(); - newCriteria.add(entry.getCriterion()); - } - Iterator subcriteriaIterator = impl.iterateSubcriteria(); - while (subcriteriaIterator.hasNext()) { - CriteriaImpl.Subcriteria sub = (CriteriaImpl.Subcriteria) subcriteriaIterator.next(); - newCriteria.createAlias(sub.getPath(), sub.getAlias(), sub.getJoinType(), sub.getWithClause()); - } - return new HibernateQuery(newCriteria, hibernateSession, entity); - } - }); - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AggregatePersistenceContextInterceptor.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AggregatePersistenceContextInterceptor.java deleted file mode 100644 index f36a479a3..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AggregatePersistenceContextInterceptor.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 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.codehaus.groovy.grails.orm.hibernate.support; - -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.hibernate.SessionFactory; - -/** - * @author Burt Beckwith - */ -public class AggregatePersistenceContextInterceptor extends AbstractAggregatePersistenceContextInterceptor { - - public void afterPropertiesSet() { - // need to lazily create these instead of registering as beans since GrailsPageFilter - // looks for instances of PersistenceContextInterceptor and picks one assuming - // there's only one, so this one has to be the only one - for (String name : dataSourceNames) { - String suffix = name == GrailsDomainClassProperty.DEFAULT_DATA_SOURCE ? "" : "_" + name; - HibernatePersistenceContextInterceptor interceptor = new HibernatePersistenceContextInterceptor(); - String beanName = "sessionFactory" + suffix; - if (applicationContext.containsBean(beanName)) { - interceptor.setSessionFactory((SessionFactory)applicationContext.getBean(beanName)); - } - interceptors.add(interceptor); - } - } -} 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 deleted file mode 100644 index fb5abc2e0..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventListener.java +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Copyright 2003-2007 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.support; - -import grails.validation.ValidationException; -import groovy.lang.Closure; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; -import groovy.lang.MetaMethod; -import groovy.lang.MetaProperty; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang.ArrayUtils; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -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; -import org.grails.datastore.mapping.engine.event.ValidationEvent; -import org.hibernate.EntityMode; -import org.hibernate.FlushMode; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.event.AbstractEvent; -import org.hibernate.event.PostDeleteEvent; -import org.hibernate.event.PostDeleteEventListener; -import org.hibernate.event.PostInsertEvent; -import org.hibernate.event.PostInsertEventListener; -import org.hibernate.event.PostLoadEvent; -import org.hibernate.event.PostLoadEventListener; -import org.hibernate.event.PostUpdateEvent; -import org.hibernate.event.PostUpdateEventListener; -import org.hibernate.event.PreDeleteEvent; -import org.hibernate.event.PreDeleteEventListener; -import org.hibernate.event.PreInsertEvent; -import org.hibernate.event.PreLoadEvent; -import org.hibernate.event.PreLoadEventListener; -import org.hibernate.event.PreUpdateEvent; -import org.hibernate.event.PreUpdateEventListener; -import org.hibernate.event.SaveOrUpdateEvent; -import org.hibernate.event.SaveOrUpdateEventListener; -import org.hibernate.persister.entity.EntityPersister; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.ReflectionUtils; -import org.springframework.validation.Errors; - -/** - *

    Invokes closure events on domain entities such as beforeInsert, beforeUpdate and beforeDelete. - * - *

    Also deals with auto time stamping of domain classes that have properties named 'lastUpdated' and/or 'dateCreated'. - * - * @author Lari Hotari - * @since 1.3.5 - */ -@SuppressWarnings({"rawtypes", "unchecked", "serial"}) -public class ClosureEventListener implements SaveOrUpdateEventListener, - PreLoadEventListener, - PostLoadEventListener, - PostInsertEventListener, - PostUpdateEventListener, - PostDeleteEventListener, - PreDeleteEventListener, - PreUpdateEventListener { - - private static final long serialVersionUID = 1; - private static final Logger log = LoggerFactory.getLogger(ClosureEventListener.class); - private static final Object[] EMPTY_OBJECT_ARRAY = {}; - - EventTriggerCaller saveOrUpdateCaller; - EventTriggerCaller beforeInsertCaller; - EventTriggerCaller preLoadEventCaller; - EventTriggerCaller postLoadEventListener; - EventTriggerCaller postInsertEventListener; - EventTriggerCaller postUpdateEventListener; - EventTriggerCaller postDeleteEventListener; - EventTriggerCaller preDeleteEventListener; - EventTriggerCaller preUpdateEventListener; - private BeforeValidateHelper beforeValidateHelper = new BeforeValidateHelper(); - boolean shouldTimestamp = false; - MetaProperty dateCreatedProperty; - MetaProperty lastUpdatedProperty; - MetaClass domainMetaClass; - boolean failOnErrorEnabled = false; - MetaProperty errorsProperty; - Map validateParams; - MetaMethod validateMethod; - - public ClosureEventListener(Class domainClazz, boolean failOnError, List failOnErrorPackages) { - domainMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(domainClazz); - dateCreatedProperty = domainMetaClass.getMetaProperty(GrailsDomainClassProperty.DATE_CREATED); - lastUpdatedProperty = domainMetaClass.getMetaProperty(GrailsDomainClassProperty.LAST_UPDATED); - if (dateCreatedProperty != null || lastUpdatedProperty != null) { - Mapping m = new GrailsDomainBinder().getMapping(domainClazz); - shouldTimestamp = m == null || m.isAutoTimestamp(); - } - - saveOrUpdateCaller = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.ONLOAD_SAVE); - beforeInsertCaller = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.BEFORE_INSERT_EVENT); - preLoadEventCaller = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.ONLOAD_EVENT); - if (preLoadEventCaller == null) { - preLoadEventCaller = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.BEFORE_LOAD_EVENT); - } - postLoadEventListener = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.AFTER_LOAD_EVENT); - postInsertEventListener = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.AFTER_INSERT_EVENT); - postUpdateEventListener = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.AFTER_UPDATE_EVENT); - postDeleteEventListener = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.AFTER_DELETE_EVENT); - preDeleteEventListener = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.BEFORE_DELETE_EVENT); - preUpdateEventListener = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.BEFORE_UPDATE_EVENT); - - if (failOnErrorPackages.size() > 0) { - failOnErrorEnabled = GrailsClassUtils.isClassBelowPackage(domainClazz, failOnErrorPackages); - } else { - failOnErrorEnabled = failOnError; - } - - validateParams = new HashMap(); - validateParams.put(ValidatePersistentMethod.ARGUMENT_DEEP_VALIDATE, Boolean.FALSE); - - errorsProperty = domainMetaClass.getMetaProperty(AbstractDynamicPersistentMethod.ERRORS_PROPERTY); - - validateMethod = domainMetaClass.getMetaMethod(ValidatePersistentMethod.METHOD_SIGNATURE, - new Object[] { Map.class }); - } - - private EventTriggerCaller buildCaller(Class domainClazz, String event) { - Method method = ReflectionUtils.findMethod(domainClazz, event); - if (method != null) { - ReflectionUtils.makeAccessible(method); - return new MethodCaller(method); - } - - Field field = ReflectionUtils.findField(domainClazz, event); - if (field != null) { - ReflectionUtils.makeAccessible(field); - return new FieldClosureCaller(field); - } - - MetaMethod metaMethod = domainMetaClass.getMetaMethod(event, EMPTY_OBJECT_ARRAY); - if (metaMethod != null) { - return new MetaMethodCaller(metaMethod); - } - - MetaProperty metaProperty = domainMetaClass.getMetaProperty(event); - if (metaProperty != null) { - return new MetaPropertyClosureCaller(metaProperty); - } - - return null; - } - - public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException { - // no-op, merely a hook for plugins to override - } - - private void synchronizePersisterState(Object entity, EntityPersister persister, Object[] state) { - String[] propertyNames = persister.getPropertyNames(); - for (int i = 0; i < propertyNames.length; i++) { - String p = propertyNames[i]; - MetaProperty metaProperty = domainMetaClass.getMetaProperty(p); - if (ClosureEventTriggeringInterceptor.IGNORED.contains(p) || metaProperty == null) { - continue; - } - Object value = metaProperty.getProperty(entity); - state[i] = value; - persister.setPropertyValue(entity, i, value, EntityMode.POJO); - } - } - - public void onPreLoad(final PreLoadEvent event) { - if (preLoadEventCaller == null) { - return; - } - - doWithManualSession(event, new Closure(this) { - @Override - public Object call() { - preLoadEventCaller.call(event.getEntity()); - return null; - } - }); - } - - public void onPostLoad(final PostLoadEvent event) { - if (postLoadEventListener == null) { - return; - } - - doWithManualSession(event, new Closure(this) { - @Override - public Object call() { - postLoadEventListener.call(event.getEntity()); - return null; - } - }); - } - - public void onPostInsert(PostInsertEvent event) { - final Object entity = event.getEntity(); - AbstractSavePersistentMethod.clearDisabledValidations(entity); - if (postInsertEventListener == null) { - return; - } - - doWithManualSession(event, new Closure(this) { - @Override - public Object call() { - postInsertEventListener.call(entity); - return null; - } - }); - } - - public void onPostUpdate(PostUpdateEvent event) { - final Object entity = event.getEntity(); - AbstractSavePersistentMethod.clearDisabledValidations(entity); - if (postUpdateEventListener == null) { - return; - } - - doWithManualSession(event, new Closure(this) { - @Override - public Object call() { - postUpdateEventListener.call(entity); - return null; - } - }); - } - - public void onPostDelete(PostDeleteEvent event) { - final Object entity = event.getEntity(); - AbstractSavePersistentMethod.clearDisabledValidations(entity); - if (postDeleteEventListener == null) { - return; - } - - doWithManualSession(event, new Closure(this) { - @Override - public Object call() { - postDeleteEventListener.call(entity); - return null; - } - }); - } - - public boolean onPreDelete(final PreDeleteEvent event) { - if (preDeleteEventListener == null) { - return false; - } - - return doWithManualSession(event, new Closure(this) { - @Override - public Boolean call() { - return preDeleteEventListener.call(event.getEntity()); - } - }); - } - - public boolean onPreUpdate(final PreUpdateEvent event) { - return doWithManualSession(event, new Closure(this) { - @Override - public Boolean call() { - Object entity = event.getEntity(); - boolean evict = false; - if (preUpdateEventListener != null) { - evict = preUpdateEventListener.call(entity); - synchronizePersisterState(entity, event.getPersister(), event.getState()); - } - if (lastUpdatedProperty != null && shouldTimestamp) { - Object now = DefaultGroovyMethods.newInstance(lastUpdatedProperty.getType(), new Object[] { System.currentTimeMillis() }); - event.getState()[ArrayUtils.indexOf(event.getPersister().getPropertyNames(), GrailsDomainClassProperty.LAST_UPDATED)] = now; - lastUpdatedProperty.setProperty(entity, now); - } - if (!AbstractSavePersistentMethod.isAutoValidationDisabled(entity) - && !DefaultTypeTransformation.castToBoolean(validateMethod.invoke(entity, new Object[] { validateParams }))) { - evict = true; - if (failOnErrorEnabled) { - Errors errors = (Errors) errorsProperty.getProperty(entity); - throw new ValidationException("Validation error whilst flushing entity [" + entity.getClass().getName() - + "]", errors); - } - } - return evict; - } - }); - } - - private T doWithManualSession(AbstractEvent event, Closure callable) { - Session session = event.getSession(); - FlushMode current = session.getFlushMode(); - try { - session.setFlushMode(FlushMode.MANUAL); - return callable.call(); - } finally { - session.setFlushMode(current); - } - } - - public boolean onPreInsert(final PreInsertEvent event) { - return doWithManualSession(event, new Closure(this) { - @Override - public Boolean call() { - Object entity = event.getEntity(); - boolean synchronizeState = false; - if (beforeInsertCaller != null) { - if (beforeInsertCaller.call(entity)) { - return true; - } - synchronizeState = true; - } - if (shouldTimestamp) { - long time = System.currentTimeMillis(); - if (dateCreatedProperty != null) { - Object now = DefaultGroovyMethods.newInstance(dateCreatedProperty.getType(), new Object[] { time }); - dateCreatedProperty.setProperty(entity, now); - synchronizeState = true; - } - if (lastUpdatedProperty != null) { - Object now = DefaultGroovyMethods.newInstance(lastUpdatedProperty.getType(), new Object[] { time }); - lastUpdatedProperty.setProperty(entity, now); - synchronizeState = true; - } - } - - if (synchronizeState) { - synchronizePersisterState(entity, event.getPersister(), event.getState()); - } - - boolean evict = false; - if (!AbstractSavePersistentMethod.isAutoValidationDisabled(entity) - && !DefaultTypeTransformation.castToBoolean(validateMethod.invoke(entity, - new Object[] { validateParams }))) { - evict = true; - if (failOnErrorEnabled) { - Errors errors = (Errors) errorsProperty.getProperty(entity); - throw new ValidationException("Validation error whilst flushing entity [" + entity.getClass().getName() - + "]", errors); - } - } - return evict; - } - }); - } - - public void onValidate(ValidationEvent event) { - beforeValidateHelper.invokeBeforeValidate( - event.getEntityObject(), event.getValidatedFields()); - } - - private static abstract class EventTriggerCaller { - - public abstract boolean call(Object entity); - - boolean resolveReturnValue(Object retval) { - if (retval instanceof Boolean) { - return !(Boolean)retval; - } - return false; - } - } - - private static class MethodCaller extends EventTriggerCaller { - Method method; - - MethodCaller(Method method) { - this.method = method; - } - - @Override - public boolean call(Object entity) { - Object retval = ReflectionUtils.invokeMethod(method, entity); - return resolveReturnValue(retval); - } - } - - private static class MetaMethodCaller extends EventTriggerCaller { - MetaMethod method; - - MetaMethodCaller(MetaMethod method) { - this.method = method; - } - - @Override - public boolean call(Object entity) { - Object retval = method.invoke(entity, EMPTY_OBJECT_ARRAY); - return resolveReturnValue(retval); - } - } - - private static abstract class ClosureCaller extends EventTriggerCaller { - boolean cloneFirst = false; - - Object callClosure(Object entity, Closure callable) { - if (cloneFirst) { - callable = (Closure)callable.clone(); - } - callable.setResolveStrategy(Closure.DELEGATE_FIRST); - callable.setDelegate(entity); - return callable.call(); - } - } - - private static class FieldClosureCaller extends ClosureCaller { - Field field; - - FieldClosureCaller(Field field) { - this.field = field; - if (Modifier.isStatic(field.getModifiers())) { - cloneFirst = true; - } - } - - @Override - public boolean call(Object entity) { - Object fieldval = ReflectionUtils.getField(field, entity); - if (fieldval instanceof Closure) { - return resolveReturnValue(callClosure(entity, (Closure) fieldval)); - } - log.error("Field " + field + " is not Closure or method."); - return false; - } - } - - private static class MetaPropertyClosureCaller extends ClosureCaller { - MetaProperty metaProperty; - - MetaPropertyClosureCaller(MetaProperty metaProperty) { - this.metaProperty = metaProperty; - if (Modifier.isStatic(metaProperty.getModifiers())) { - cloneFirst = true; - } - } - - @Override - public boolean call(Object entity) { - Object fieldval = metaProperty.getProperty(entity); - if (fieldval instanceof Closure) { - return resolveReturnValue(callClosure(entity, (Closure) fieldval)); - } - log.error("Field " + metaProperty + " is not Closure."); - return false; - } - } -} 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 deleted file mode 100644 index ecd7dd4fe..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright 2003-2007 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.support; - -import grails.util.CollectionUtils; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.Map; - -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; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.SessionFactory; -import org.hibernate.action.EntityIdentityInsertAction; -import org.hibernate.action.EntityInsertAction; -import org.hibernate.engine.EntityKey; -import org.hibernate.engine.ForeignKeys; -import org.hibernate.engine.Nullability; -import org.hibernate.engine.Status; -import org.hibernate.engine.Versioning; -import org.hibernate.event.*; -import org.hibernate.event.def.AbstractSaveEventListener; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.type.Type; -import org.hibernate.type.TypeHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.util.ReflectionUtils; - -/** - * Listens for Hibernate events and publishes corresponding Datastore events. - * - * @author Graeme Rocher - * @author Lari Hotari - * @author Burt Beckwith - * @since 1.0 - */ -public class ClosureEventTriggeringInterceptor extends SaveOrUpdateEventListener - implements ApplicationContextAware, - PreLoadEventListener, - PostLoadEventListener, - PostInsertEventListener, - PostUpdateEventListener, - PostDeleteEventListener, - PreDeleteEventListener, - PreUpdateEventListener, - PreInsertEventListener { - - private final Logger log = LoggerFactory.getLogger(getClass()); - private static final long serialVersionUID = 1; - - public static final Collection IGNORED = CollectionUtils.newSet("version", "id"); - public static final String ONLOAD_EVENT = "onLoad"; - public static final String ONLOAD_SAVE = "onSave"; - public static final String BEFORE_LOAD_EVENT = "beforeLoad"; - public static final String BEFORE_INSERT_EVENT = "beforeInsert"; - public static final String AFTER_INSERT_EVENT = "afterInsert"; - public static final String BEFORE_UPDATE_EVENT = "beforeUpdate"; - public static final String AFTER_UPDATE_EVENT = "afterUpdate"; - public static final String BEFORE_DELETE_EVENT = "beforeDelete"; - public static final String AFTER_DELETE_EVENT = "afterDelete"; - public static final String AFTER_LOAD_EVENT = "afterLoad"; - - private Method markInterceptorDirtyMethod; - private ApplicationContext ctx; - private Map datastores; - - private static final ThreadLocal insertActiveThreadLocal = new ThreadLocal(); - - public ClosureEventTriggeringInterceptor() { - try { - markInterceptorDirtyMethod = ReflectionUtils.findMethod(AbstractSaveEventListener.class, "markInterceptorDirty", - new Class[] { Object.class, EntityPersister.class, EventSource.class }); - ReflectionUtils.makeAccessible(markInterceptorDirtyMethod); - } catch (Exception e) { - // ignore - } - } - - public void setDatastores(Map datastores) { - this.datastores = datastores; - } - - @Override - public void onSaveOrUpdate(SaveOrUpdateEvent hibernateEvent) throws HibernateException { - publishEvent(hibernateEvent, new org.grails.datastore.mapping.engine.event.SaveOrUpdateEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity())); - super.onSaveOrUpdate(hibernateEvent); - } - - public void onPreLoad(PreLoadEvent hibernateEvent) { - publishEvent(hibernateEvent, new org.grails.datastore.mapping.engine.event.PreLoadEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity())); - } - - public void onPostLoad(PostLoadEvent hibernateEvent) { - publishEvent(hibernateEvent, new org.grails.datastore.mapping.engine.event.PostLoadEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity())); - } - - public boolean onPreInsert(PreInsertEvent hibernateEvent) { - AbstractPersistenceEvent event = new org.grails.datastore.mapping.engine.event.PreInsertEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity()); - publishEvent(hibernateEvent, event); - return event.isCancelled(); - } - - public void onPostInsert(PostInsertEvent hibernateEvent) { - publishEvent(hibernateEvent, new org.grails.datastore.mapping.engine.event.PostInsertEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity())); - } - - public boolean onPreUpdate(PreUpdateEvent hibernateEvent) { - AbstractPersistenceEvent event = new org.grails.datastore.mapping.engine.event.PreUpdateEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity()); - publishEvent(hibernateEvent, event); - return event.isCancelled(); - } - - public void onPostUpdate(PostUpdateEvent hibernateEvent) { - publishEvent(hibernateEvent, new org.grails.datastore.mapping.engine.event.PostUpdateEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity())); - } - - public boolean onPreDelete(PreDeleteEvent hibernateEvent) { - AbstractPersistenceEvent event = new org.grails.datastore.mapping.engine.event.PreDeleteEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity()); - publishEvent(hibernateEvent, event); - return event.isCancelled(); - } - - public void onPostDelete(PostDeleteEvent hibernateEvent) { - publishEvent(hibernateEvent, new org.grails.datastore.mapping.engine.event.PostDeleteEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity())); - } - - public void setApplicationContext(ApplicationContext applicationContext) { - ctx = applicationContext; - } - - private void publishEvent(AbstractEvent hibernateEvent, AbstractPersistenceEvent mappingEvent) { - mappingEvent.setNativeEvent(hibernateEvent); - ctx.publishEvent(mappingEvent); - } - - private Datastore findDatastore(AbstractEvent hibernateEvent) { - SessionFactory sessionFactory = hibernateEvent.getSession().getSessionFactory(); - if (!(sessionFactory instanceof SessionFactoryProxy)) { - // should always be the case - for (Map.Entry entry : datastores.entrySet()) { - SessionFactory sf = entry.getKey(); - if (sf instanceof SessionFactoryProxy) { - if (((SessionFactoryProxy)sf).getCurrentSessionFactory() == sessionFactory) { - return entry.getValue(); - } - } - } - } - - Datastore datastore = datastores.get(sessionFactory); - if (datastore == null && datastores.size() == 1) { - datastore = datastores.values().iterator().next(); - } - return datastore; - } - - /* - * TODO: This is a horrible hack due to a bug in Hibernate's post-insert event processing (HHH-3904) - */ - @Override - protected Serializable performSaveOrReplicate(Object entity, EntityKey key, EntityPersister persister, boolean useIdentityColumn, Object anything, EventSource source, boolean requiresImmediateIdAccess) { - validate(entity, persister, source); - - Serializable id = key == null ? null : key.getIdentifier(); - - boolean inTxn = source.getJDBCContext().isTransactionInProgress(); - boolean shouldDelayIdentityInserts = !inTxn && !requiresImmediateIdAccess; - - // Put a placeholder in entries, so we don't recurse back and try to save() the - // same object again. QUESTION: should this be done before onSave() is called? - // likewise, should it be done before onUpdate()? - source.getPersistenceContext().addEntry( - entity, - Status.SAVING, - null, - null, - id, - null, - LockMode.WRITE, - useIdentityColumn, - persister, - false, - false); - - cascadeBeforeSave(source, persister, entity, anything); - - if (useIdentityColumn && !shouldDelayIdentityInserts) { - log.trace("executing insertions"); - source.getActionQueue().executeInserts(); - } - - Object[] values = persister.getPropertyValuesToInsert(entity, getMergeMap(anything), source); - Type[] types = persister.getPropertyTypes(); - - boolean substitute = substituteValuesIfNecessary(entity, id, values, persister, source); - - if (persister.hasCollections()) { - substitute = substitute || visitCollectionsBeforeSave(entity, id, values, types, source); - } - - if (substitute) { - persister.setPropertyValues(entity, values, source.getEntityMode()); - } - - TypeHelper.deepCopy( - values, - types, - persister.getPropertyUpdateability(), - values, - source); - - new ForeignKeys.Nullifier(entity, false, useIdentityColumn, source) - .nullifyTransientReferences(values, types); - - if (useIdentityColumn) { - EntityIdentityInsertAction insert = new EntityIdentityInsertAction( - values, entity, persister, source, shouldDelayIdentityInserts); - if (!shouldDelayIdentityInserts) { - log.debug("executing identity-insert immediately"); - source.getActionQueue().execute(insert); - id = insert.getGeneratedId(); - if (id != null) { - // As of HHH-3904, if the id is null the operation was vetoed so we bail - key = new EntityKey(id, persister, source.getEntityMode()); - source.getPersistenceContext().checkUniqueness(key, entity); - } - } - else { - log.debug("delaying identity-insert due to no transaction in progress"); - source.getActionQueue().addAction(insert); - key = insert.getDelayedEntityKey(); - } - } - - if (key != null) { - Object version = Versioning.getVersion(values, persister); - source.getPersistenceContext().addEntity( - entity, - (persister.isMutable() ? Status.MANAGED : Status.READ_ONLY), - values, - key, - version, - LockMode.WRITE, - useIdentityColumn, - persister, - isVersionIncrementDisabled(), - false); - - if (!useIdentityColumn) { - source.getActionQueue().addAction( - new EntityInsertAction(id, values, entity, version, persister, source)); - } - - cascadeAfterSave(source, persister, entity, anything); - // Very unfortunate code, but markInterceptorDirty is private. Once HHH-3904 is resolved remove this overridden method! - if (markInterceptorDirtyMethod != null) { - ReflectionUtils.invokeMethod(markInterceptorDirtyMethod, this, entity, persister, source); - } - } - - return id; - } - - public static final void addNullabilityCheckerPreInsertEventListener(EventListeners listenerRegistry) { - PreInsertEventListener[] preListeners = listenerRegistry.getPreInsertEventListeners(); - - // Register the nullability check as the last PreInsertEventListener - if (preListeners == null) { - preListeners = new PreInsertEventListener[1]; - } else { - PreInsertEventListener[] newPreListeners = new PreInsertEventListener[preListeners.length+1]; - System.arraycopy(preListeners, 0, newPreListeners, 0, preListeners.length); - preListeners = newPreListeners; - } - - preListeners[preListeners.length - 1] = NULLABILITY_CHECKER_INSTANCE; - listenerRegistry.setPreInsertEventListeners(preListeners); - } - - private static final PreInsertEventListener NULLABILITY_CHECKER_INSTANCE = new NullabilityCheckerPreInsertEventListener(); - - @SuppressWarnings("serial") - private static class NullabilityCheckerPreInsertEventListener implements PreInsertEventListener { - public boolean onPreInsert(PreInsertEvent event) { - new Nullability(event.getSession()).checkNullability(event.getState(), event.getPersister(), false); - return false; - } - } - - /** - * 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() - */ - @Override - protected 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(); - } -} 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 deleted file mode 100644 index 327db7569..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/FlushOnRedirectEventListener.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.support; - -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; -import org.springframework.orm.hibernate3.HibernateCallback; - -/** - * Flushes the session on a redirect. - * - * @author Graeme Rocher - * @since 1.2 - */ -public class FlushOnRedirectEventListener implements RedirectEventListener { - - private SessionFactory sessionFactory; - - public FlushOnRedirectEventListener(SessionFactory sf) { - sessionFactory = sf; - } - - public void responseRedirected(String url) { - new GrailsHibernateTemplate(sessionFactory).execute(new HibernateCallback() { - public Void doInHibernate(Session session) { - if (!FlushMode.isManualFlushMode(session.getFlushMode())) { - session.flush(); - } - return null; - } - }); - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewFilter.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewFilter.java deleted file mode 100644 index a3ec7d094..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewFilter.java +++ /dev/null @@ -1,77 +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.support; - -import java.io.IOException; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.codehaus.groovy.grails.commons.ApplicationAttributes; -import org.hibernate.FlushMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.orm.hibernate3.SessionFactoryUtils; -import org.springframework.orm.hibernate3.support.OpenSessionInViewFilter; - -/** - * Uses the GrailsApplication sessionFactory to apply the filter. - * - * @author Graeme Rocher - * @since Oct 20, 2005 - */ -public class GrailsOpenSessionInViewFilter extends OpenSessionInViewFilter { - - @Override - protected SessionFactory lookupSessionFactory() { - ApplicationContext context = (ApplicationContext)getServletContext().getAttribute(ApplicationAttributes.APPLICATION_CONTEXT); - - if (context != null) { - return context.getBean(getSessionFactoryBeanName(), SessionFactory.class); - } - return null; - } - - @Override - protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException { - Session session = SessionFactoryUtils.getSession(sessionFactory, true); - session.setFlushMode(FlushMode.AUTO); - return session; - } - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - SessionFactory sf = lookupSessionFactory(); - if (sf != null) { - super.doFilterInternal(request,response,filterChain); - } - else { - filterChain.doFilter(request,response); - } - } - - @Override - protected void closeSession(Session session, SessionFactory sessionFactory) { - if (!FlushMode.isManualFlushMode(session.getFlushMode())) { - session.flush(); - } - super.closeSession(session, 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 deleted file mode 100644 index fa93fdfeb..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewInterceptor.java +++ /dev/null @@ -1,138 +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.support; - -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; - -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.hibernate.FlushMode; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.dao.DataAccessException; -import org.springframework.orm.hibernate3.SessionFactoryUtils; -import org.springframework.orm.hibernate3.SessionHolder; -import org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.ui.ModelMap; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.WebRequest; - -/** - * Extends the default spring OSIVI and doesn't flush the session if it has been set - * to MANUAL on the session itself. - * - * @author Graeme Rocher - * @since 0.5 - */ -public class GrailsOpenSessionInViewInterceptor extends OpenSessionInViewInterceptor { - private static final String IS_FLOW_REQUEST_ATTRIBUTE = "org.codehaus.groovy.grails.webflow.flow_request"; - - @Override - public void preHandle(WebRequest request) throws DataAccessException { - GrailsWebRequest webRequest = GrailsWebRequest.lookup(); - final boolean isFlowRequest = webRequest != null && webRequest.isFlowRequest(); - if (isFlowRequest) { - webRequest.setAttribute(IS_FLOW_REQUEST_ATTRIBUTE, "true", WebRequest.SCOPE_REQUEST); - } - else { - super.preHandle(request); - SessionFactory sessionFactory = getSessionFactory(); - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory); - Session session = sessionHolder.getSession(); - GrailsHibernateUtil.enableDynamicFilterEnablerIfPresent(sessionFactory, session); - } - } - - @Override - public void postHandle(WebRequest request, ModelMap model) throws DataAccessException { - final boolean isFlowRequest = request.getAttribute(IS_FLOW_REQUEST_ATTRIBUTE, WebRequest.SCOPE_REQUEST) != null; - if (isFlowRequest) { - return; - } - - try { - super.postHandle(request, model); - } - finally { - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(getSessionFactory()); - Session session = sessionHolder.getSession(); - session.setFlushMode(FlushMode.MANUAL); - } - } - - @Override - public void afterCompletion(WebRequest request, Exception ex) throws DataAccessException { - try { - final boolean isWebRequest = request.getAttribute(IS_FLOW_REQUEST_ATTRIBUTE, WebRequest.SCOPE_REQUEST) != null; - if (isWebRequest) { - return; - } - - request = (WebRequest) RequestContextHolder.currentRequestAttributes(); - if (!(request instanceof GrailsWebRequest)) { - super.afterCompletion(request, ex); - 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); - if (session != null) { - session.disconnect(); - } - } - catch (IllegalStateException e) { - super.afterCompletion(request, ex); - } - } finally { - AbstractSavePersistentMethod.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())) { - super.flushIfNecessary(session, existingTransaction); - } - } -} 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 deleted file mode 100644 index e34d3747c..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java +++ /dev/null @@ -1,103 +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.support; - -import groovy.util.ConfigObject; - -import java.sql.Connection; -import java.util.Properties; - -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; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.jdbc.datasource.DataSourceUtils; -import org.springframework.jdbc.support.JdbcUtils; -import org.springframework.jdbc.support.MetaDataAccessException; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * @author Steven Devijver - */ -public class HibernateDialectDetectorFactoryBean implements FactoryBean, InitializingBean, GrailsApplicationAware { - - private DataSource dataSource; - private Properties vendorNameDialectMappings; - private String hibernateDialectClassName; - private Dialect hibernateDialect; - private GrailsApplication grailsApplication; - - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - } - - public void setVendorNameDialectMappings(Properties mappings) { - vendorNameDialectMappings = mappings; - } - - public String getObject() { - return hibernateDialectClassName; - } - - public Class getObjectType() { - return String.class; - } - - public boolean isSingleton() { - return true; - } - - public void afterPropertiesSet() throws MetaDataAccessException { - Assert.notNull(dataSource, "Data source is not set!"); - Assert.notNull(vendorNameDialectMappings, "Vendor name/dialect mappings are not set!"); - - Connection connection = null; - - String dbName = (String)JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName"); - - try { - connection = DataSourceUtils.getConnection(dataSource); - - try { - ConfigObject config = grailsApplication != null ? grailsApplication.getConfig() : null; - Properties properties = config != null ? config.toProperties() : new Properties(); - hibernateDialect = DialectFactory.buildDialect(properties, connection); - hibernateDialectClassName = hibernateDialect.getClass().getName(); - } catch (HibernateException e) { - hibernateDialectClassName = vendorNameDialectMappings.getProperty(dbName); - } - - if (!StringUtils.hasText(hibernateDialectClassName)) { - throw new CouldNotDetermineHibernateDialectException( - "Could not determine Hibernate dialect for database name [" + dbName + "]!"); - } - } finally { - DataSourceUtils.releaseConnection(connection,dataSource); - } - - } - - public void setGrailsApplication(GrailsApplication grailsApplication) { - this.grailsApplication = grailsApplication; - } -} 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 deleted file mode 100644 index 361bbbcbf..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2004-2006 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.support; - -import grails.validation.DeferredBindingActions; - -import org.codehaus.groovy.grails.lifecycle.ShutdownOperations; -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.hibernate.FlushMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.orm.hibernate3.SessionFactoryUtils; -import org.springframework.orm.hibernate3.SessionHolder; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -/** - * @author Graeme Rocher - * @since 0.4 - */ -public class HibernatePersistenceContextInterceptor implements PersistenceContextInterceptor { - - private static final Logger LOG = LoggerFactory.getLogger(HibernatePersistenceContextInterceptor.class); - private SessionFactory sessionFactory; - - private ThreadLocal participate = new ThreadLocal(); - private ThreadLocal nestingCount = new ThreadLocal(); - - public HibernatePersistenceContextInterceptor() { - ShutdownOperations.addOperation(new Runnable() { - public void run() { - participate.remove(); - nestingCount.remove(); - } - }); - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.support.PersistenceContextInterceptor#destroy() - */ - public void destroy() { - DeferredBindingActions.clear(); - if (decNestingCount() > 0 || getParticipate()) { - return; - } - - try { -// single session mode - SessionHolder holder = (SessionHolder)TransactionSynchronizationManager.unbindResource(getSessionFactory()); - LOG.debug("Closing single Hibernate session in GrailsDispatcherServlet"); - try { - SessionFactoryUtils.closeSession(holder.getSession()); - } - catch (RuntimeException ex) { - LOG.error("Unexpected exception on closing Hibernate Session", ex); - } - } finally { - AbstractSavePersistentMethod.clearDisabledValidations(); - } - } - - public void disconnect() { - try { - getSession(false).disconnect(); - } - catch (IllegalStateException e) { - // no session ignore - } - } - - public void reconnect() { - getSession(); - } - - public void flush() { - getSession().flush(); - } - - public void clear() { - getSession().clear(); - } - - public void setReadOnly() { - getSession().setFlushMode(FlushMode.MANUAL); - } - - public void setReadWrite() { - getSession().setFlushMode(FlushMode.AUTO); - } - - public boolean isOpen() { - try { - return getSession(false).isOpen(); - } - catch (IllegalStateException e) { - return false; - } - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.support.PersistenceContextInterceptor#init() - */ - public void init() { - if (incNestingCount() > 1) { - return; - } - SessionFactory sf = getSessionFactory(); - if (TransactionSynchronizationManager.hasResource(sf)) { - // Do not modify the Session: just set the participate flag. - setParticipate(true); - } - else { - setParticipate(false); - LOG.debug("Opening single Hibernate session in HibernatePersistenceContextInterceptor"); - Session session = getSession(); - GrailsHibernateUtil.enableDynamicFilterEnablerIfPresent(sf, session); - session.setFlushMode(FlushMode.AUTO); - TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); - } - } - - private Session getSession() { - return getSession(true); - } - - private Session getSession(boolean allowCreate) { - return SessionFactoryUtils.getSession(getSessionFactory(), allowCreate); - } - - /** - * @return the sessionFactory - */ - public SessionFactory getSessionFactory() { - return sessionFactory; - } - - /** - * @param sessionFactory the sessionFactory to set - */ - public void setSessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - - private int incNestingCount() { - Integer current = nestingCount.get(); - int value = (current != null) ? current + 1 : 1; - nestingCount.set(value); - return value; - } - - private int decNestingCount() { - Integer current = nestingCount.get(); - int value = current == null ? 0 : current - 1; - if (value < 0) { - value = 0; - } - nestingCount.set(value); - return value; - } - - private void setParticipate(boolean flag) { - participate.set(flag); - } - - private boolean getParticipate() { - Boolean ret = participate.get(); - return ret == null ? false : ret; - } -} 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 ad39be7f3..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java +++ /dev/null @@ -1,89 +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.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 = new ThreadLocal(); - - 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); - } - return new HibernateTemplate(sf, true); - } - - /** - * 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 deleted file mode 100644 index 08c5d22a1..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateConstraintsEvaluator.java +++ /dev/null @@ -1,53 +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.codehaus.groovy.grails.orm.hibernate.validation; - -import java.util.Map; - -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -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; - -/** - * Extends default implementation to add Hibernate specific exceptions. - * - * @author Graeme Rocher - * @since 2.0 - */ -public class HibernateConstraintsEvaluator extends DefaultConstraintEvaluator { - - public HibernateConstraintsEvaluator(Map defaultConstraints) { - super(defaultConstraints); - } - - public HibernateConstraintsEvaluator() { - // default - } - - @Override - protected void applyDefaultNullableConstraint(GrailsDomainClassProperty p, ConstrainedProperty cp) { - final PropertyConfig propertyConfig = new GrailsDomainBinder().getPropertyConfig(p); - boolean insertable = propertyConfig != null ? propertyConfig.isInsertable() : true; - - if (!insertable) { - cp.applyConstraint(ConstrainedProperty.NULLABLE_CONSTRAINT,true); - } - else { - super.applyDefaultNullableConstraint(p, cp); - } - } -} 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 deleted file mode 100644 index 018c85fc4..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateDomainClassValidator.java +++ /dev/null @@ -1,100 +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.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.validation.GrailsDomainClassValidator; -import org.hibernate.FlushMode; -import org.hibernate.SessionFactory; -import org.hibernate.classic.Session; -import org.hibernate.collection.PersistentCollection; -import org.hibernate.proxy.HibernateProxy; -import org.springframework.beans.BeanWrapper; -import org.springframework.validation.Errors; - -/** - * First checks if the Hibernate PersistentCollection instance has been initialised before bothering - * to cascade. - * - * @author Graeme Rocher - * @since 0.5 - */ -public class HibernateDomainClassValidator extends GrailsDomainClassValidator { - - private SessionFactory sessionFactory; - - @Override - protected GrailsDomainClass getAssociatedDomainClassFromApplication(Object associatedObject) { - String associatedObjectType = associatedObject.getClass().getName(); - if (associatedObject instanceof HibernateProxy) { - associatedObjectType = ((HibernateProxy) associatedObject).getHibernateLazyInitializer().getEntityName(); - } - return (GrailsDomainClass) grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, associatedObjectType); - } - - @Override - public void validate(Object obj, Errors errors, boolean cascade) { - final Session session = sessionFactory.getCurrentSession(); - FlushMode previousMode = null; - try { - if (session != null) { - previousMode = session.getFlushMode(); - session.setFlushMode(FlushMode.MANUAL); - } - - super.validate(obj, errors, cascade); - } - finally { - if (session != null && previousMode != null && !errors.hasErrors()) { - session.setFlushMode(previousMode); - } - } - } - - /** - * Overrides the default behaviour and first checks if a PersistentCollection instance has been initialised using the - * wasInitialised() method before cascading - * - * @param errors The Spring Errors instance - * @param bean The BeanWrapper for the bean - * @param persistentProperty The GrailsDomainClassProperty instance - * @param propertyName The name of the property - * - * @see org.hibernate.collection.PersistentCollection#wasInitialized() - */ - @Override - protected void cascadeValidationToMany(Errors errors, BeanWrapper bean, GrailsDomainClassProperty persistentProperty, String propertyName) { - Object collection = bean.getPropertyValue(propertyName); - if (collection == null) { - return; - } - - if (collection instanceof PersistentCollection) { - PersistentCollection persistentCollection = (PersistentCollection)collection; - if (persistentCollection.wasInitialized()) { - super.cascadeValidationToMany(errors, bean, persistentProperty, propertyName); - } - } - else { - super.cascadeValidationToMany(errors, bean, persistentProperty, propertyName); - } - } - - public void setSessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraint.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraint.java deleted file mode 100644 index c3fe4ee23..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraint.java +++ /dev/null @@ -1,35 +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.validation.Constraint; -import org.springframework.context.ApplicationContextAware; -import org.springframework.orm.hibernate3.HibernateTemplate; - -/** - * 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 - */ - HibernateTemplate 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/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraintFactory.java deleted file mode 100644 index 6535d91c6..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/PersistentConstraintFactory.java +++ /dev/null @@ -1,62 +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-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 deleted file mode 100644 index 4aaef23b4..000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/UniqueConstraint.java +++ /dev/null @@ -1,261 +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 java.util.ArrayList; -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 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.hibernate.criterion.Restrictions; -import org.hibernate.metadata.ClassMetadata; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.orm.hibernate3.HibernateCallback; -import org.springframework.orm.hibernate3.HibernateTemplate; -import org.springframework.util.Assert; -import org.springframework.validation.Errors; - -/** - * A constraint that validates the uniqueness of a property (will query the - * database during validation process). - * - * @author Graeme Rocher - * @author Sergey Nebolsin - * @since 0.4 - */ -public class UniqueConstraint extends AbstractPersistentConstraint { - - private static final String DEFAULT_NOT_UNIQUE_MESSAGE_CODE = "default.not.unique.message"; - private static final String TARGET_DOMAIN_CLASS_ALIAS = "domain_"; - - public static final String UNIQUE_CONSTRAINT = "unique"; - - private boolean unique; - private List uniquenessGroup = new ArrayList(); - - public UniqueConstraint() { - ShutdownOperations.addOperation(new Runnable() { - public void run() { - ConstrainedProperty.removeConstraint(UNIQUE_CONSTRAINT, PersistentConstraintFactory.class); - } - }); - } - - /** - * @return Returns the unique. - */ - public boolean isUnique() { - return unique; - } - - /** - * @return Whether the property is unique within a group - */ - public boolean isUniqueWithinGroup() { - return !uniquenessGroup.isEmpty(); - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) - */ - @Override - public void setParameter(Object constraintParameter) { - if (!(constraintParameter instanceof Boolean || - constraintParameter instanceof String || - constraintParameter instanceof CharSequence || - constraintParameter instanceof List)) { - throw new IllegalArgumentException("Parameter for constraint [" + UNIQUE_CONSTRAINT + - "] of property [" + constraintPropertyName + "] of class [" + - constraintOwningClass + "] must be a boolean or string value"); - } - - if (constraintParameter instanceof List) { - for (Object parameter : ((List) constraintParameter)) { - if (!(parameter instanceof String || parameter instanceof CharSequence)) { - throw new IllegalArgumentException("Parameter for constraint [" + UNIQUE_CONSTRAINT + - "] of property [" + constraintPropertyName + "] of class [" + - constraintOwningClass + "] must be a boolean or string value"); - } - uniquenessGroup.add(parameter.toString()); - } - } - else if (constraintParameter instanceof String || constraintParameter instanceof CharSequence) { - uniquenessGroup.add(constraintParameter.toString()); - unique = true; - } - else { - unique = (Boolean)constraintParameter; - } - - if (!uniquenessGroup.isEmpty()) { - unique = true; - for (Object anUniquenessGroup : uniquenessGroup) { - String propertyName = (String) anUniquenessGroup; - if (GrailsClassUtils.getPropertyType(constraintOwningClass, propertyName) == null) { - throw new IllegalArgumentException("Scope for constraint [" + UNIQUE_CONSTRAINT + - "] of property [" + constraintPropertyName + "] of class [" + - constraintOwningClass + "] must be a valid property name of same class"); - } - } - } - - super.setParameter(constraintParameter); - } - - public String getName() { - return UNIQUE_CONSTRAINT; - } - - @Override - protected void processValidate(final Object target, final Object propertyValue, Errors errors) { - if (!unique) { - return; - } - - final Object id; - try { - id = InvokerHelper.invokeMethod(target, "ident", null); - } - catch (Exception e) { - throw new GrailsRuntimeException("Target of [unique] constraints [" + target + - "] is not a domain instance. Unique constraint can only be applied to " + - "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.executeFind(new HibernateCallback>() { - public List doInHibernate(Session session) throws HibernateException { - session.setFlushMode(FlushMode.MANUAL); - try { - 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()); - 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()); - if (domainClass != null) { - property = domainClass.getPropertyByName(constraintPropertyName); - } - } - constraintClass = domainClass != null ? domainClass.getClazz() : constraintClass; - } - Criteria criteria = null; - - if (domainClass.getPersistentProperty(constraintPropertyName).isOneToOne()) { - criteria = session.createCriteria(constraintClass, TARGET_DOMAIN_CLASS_ALIAS); - - String constraintPropertyAlias = constraintPropertyName + "_"; - criteria.createAlias(TARGET_DOMAIN_CLASS_ALIAS + "." + constraintPropertyName, constraintPropertyAlias); - - GrailsDomainClassProperty property = domainClass.getPropertyByName(constraintPropertyName); - ClassMetadata classMetadata = session.getSessionFactory().getClassMetadata(property.getType()); - String identifierPropertyName = classMetadata.getIdentifierPropertyName(); - - BeanWrapper bean = new BeanWrapperImpl(propertyValue); - Object identifierPropertyValue = bean.getPropertyValue(identifierPropertyName); - - criteria.add(Restrictions.eq(constraintPropertyAlias + "." + identifierPropertyName, identifierPropertyValue)); - } else { - criteria = session.createCriteria(constraintClass) - .add(Restrictions.eq(constraintPropertyName, propertyValue)); - } - - if (uniquenessGroup != null) { - for (Object anUniquenessGroup : uniquenessGroup) { - String uniquenessGroupPropertyName = (String) anUniquenessGroup; - Object uniquenessGroupPropertyValue = GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(target, uniquenessGroupPropertyName); - - if (uniquenessGroupPropertyValue != null && DomainClassArtefactHandler.isDomainClass(uniquenessGroupPropertyValue.getClass())) { - // We are merely verifying that the object is not transient here - shouldValidate = session.contains(uniquenessGroupPropertyValue); - } - if (shouldValidate) { - criteria.add(Restrictions.eq(uniquenessGroupPropertyName, uniquenessGroupPropertyValue)); - } - else { - break; // we aren't validating, so no point continuing - } - } - } - - if (shouldValidate) { - return criteria.list(); - } - return Collections.EMPTY_LIST; - } - return Collections.EMPTY_LIST; - } - finally { - session.setFlushMode(FlushMode.AUTO); - } - } - }); - - if (results.isEmpty()) { - return; - } - - boolean reject = false; - if (id != null) { - Object existing = results.get(0); - Object existingId = null; - try { - existingId = InvokerHelper.invokeMethod(existing, "ident", null); - } - catch (Exception e) { - // result is not a domain class - } - if (!id.equals(existingId)) { - reject = true; - } - } - else { - reject = true; - } - if (reject) { - Object[] args = { constraintPropertyName, constraintOwningClass, propertyValue }; - rejectValue(target, errors, UNIQUE_CONSTRAINT, args, getDefaultMessage(DEFAULT_NOT_UNIQUE_MESSAGE_CODE)); - } - } - - public List getUniquenessGroup() { - return uniquenessGroup; - } - -} diff --git a/grails-datastore-gorm-hibernate/src/main/resources/META-INF/spring.handlers b/grails-datastore-gorm-hibernate/src/main/resources/META-INF/spring.handlers deleted file mode 100644 index fef2eece4..000000000 --- a/grails-datastore-gorm-hibernate/src/main/resources/META-INF/spring.handlers +++ /dev/null @@ -1 +0,0 @@ -http\://grails.org/schema/gorm=org.codehaus.groovy.grails.orm.hibernate.cfg.GORMNamespaceHandler diff --git a/grails-datastore-gorm-hibernate/src/main/resources/META-INF/spring.schemas b/grails-datastore-gorm-hibernate/src/main/resources/META-INF/spring.schemas deleted file mode 100644 index 966d5c701..000000000 --- a/grails-datastore-gorm-hibernate/src/main/resources/META-INF/spring.schemas +++ /dev/null @@ -1 +0,0 @@ -http\://grails.org/schema/gorm/gorm.xsd=org/codehaus/groovy/grails/orm/hibernate/cfg/gorm.xsd \ No newline at end of file diff --git a/grails-datastore-gorm-hibernate/src/main/resources/org/codehaus/groovy/grails/orm/hibernate/cfg/gorm.xsd b/grails-datastore-gorm-hibernate/src/main/resources/org/codehaus/groovy/grails/orm/hibernate/cfg/gorm.xsd deleted file mode 100644 index 69b36148b..000000000 --- a/grails-datastore-gorm-hibernate/src/main/resources/org/codehaus/groovy/grails/orm/hibernate/cfg/gorm.xsd +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DefaultSortSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DefaultSortSpec.groovy deleted file mode 100644 index 61470a952..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DefaultSortSpec.groovy +++ /dev/null @@ -1,107 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -class DefaultSortSpec extends GormDatastoreSpec { - - void "Test default sort"() { - given: - domainClasses.each { domainClass -> - def age = 40 - ["Bob", "Fred", "Ernie", "Bob", "Joe", "Ernie"].each { - domainClass.newInstance(name: it, age: age++).save() - } - } - - when: - def results = TestEntityWithSortProperty.list() - - then: - results[0].name == "Bob" - results[1].name == "Bob" - results[2].name == "Ernie" - results[3].name == "Ernie" - - when: - results = TestEntityWithSortOrderProperty.list() - - then: - results[0].name == "Joe" - results[1].name == "Fred" - results[2].name == "Ernie" - results[3].name == "Ernie" - - when: - results = TestEntityWithSingleEntrySortOrderMap.list() - - then: - results[0].name == "Joe" - results[1].name == "Fred" - results[2].name == "Ernie" - results[3].name == "Ernie" - - when: - results = TestEntityWithMultiEntrySortOrderMap.list() - - then: - results[0].name == "Joe" && results[0].age == 44 - results[1].name == "Fred" && results[1].age == 41 - results[2].name == "Ernie" && results[2].age == 45 - results[3].name == "Ernie" && results[3].age == 42 - } - - @Override - List getDomainClasses() { - [ - TestEntityWithSortProperty, - TestEntityWithSortOrderProperty, - TestEntityWithSingleEntrySortOrderMap, - TestEntityWithMultiEntrySortOrderMap - ] - } -} - -@Entity -class TestEntityWithSortProperty { - Long id - Long version - String name - Integer age - static mapping = { - sort "name" - } -} - -@Entity -class TestEntityWithSortOrderProperty { - Long id - Long version - String name - Integer age - static mapping = { - sort "name" - order "desc" - } -} - -@Entity -class TestEntityWithSingleEntrySortOrderMap { - Long id - Long version - String name - Integer age - static mapping = { - sort name: "desc" - } -} - -@Entity -class TestEntityWithMultiEntrySortOrderMap { - Long id - Long version - String name - Integer age - static mapping = { - sort name: "desc", age: "desc" - } -} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DeleteSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DeleteSpec.groovy deleted file mode 100644 index 9163b644b..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DeleteSpec.groovy +++ /dev/null @@ -1,30 +0,0 @@ -package grails.gorm.tests - -import spock.lang.Issue - -class DeleteSpec extends GormDatastoreSpec { - - @Issue("GRAILS-9922") - def "Test deleting an entity that has a validation error"() { - when: - def entity = new TestEntity(name: "Bob", age: 44).save(flush: true) - - then: - !entity.hasErrors() - TestEntity.count() == 1 - - when: - entity.name = "" - entity.save(flush: true) - - then: - entity.hasErrors() - - when: - entity.delete(flush: true) - - then: - TestEntity.count() == 0 - } - -} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/GroovyProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/GroovyProxySpec.groovy deleted file mode 100644 index 750de479b..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/GroovyProxySpec.groovy +++ /dev/null @@ -1,36 +0,0 @@ -package grails.gorm.tests - -import org.grails.datastore.gorm.proxy.GroovyProxyFactory - -import spock.lang.Ignore - -/** - * @author graemerocher - */ -class GroovyProxySpec extends GormDatastoreSpec { - - @Ignore - void "Test creation and behavior of Groovy proxies"() { - - given: - session.mappingContext.proxyFactory = new GroovyProxyFactory() - def id = new Location(name:"United Kingdom", code:"UK").save(flush:true)?.id - session.clear() - - when: - def location = Location.proxy(id) - - then: - - location != null - id == location.id - false == location.isInitialized() - false == location.initialized - - "UK" == location.code - "United Kingdom - UK" == location.namedAndCode() - true == location.isInitialized() - true == location.initialized - null != location.target - } -} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/MultipleOrderBySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/MultipleOrderBySpec.groovy deleted file mode 100644 index 460bbb9d1..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/MultipleOrderBySpec.groovy +++ /dev/null @@ -1,94 +0,0 @@ -package grails.gorm.tests - -class MultipleOrderBySpec extends GormDatastoreSpec { - - void "Test multiple order by with list() method"() { - given: - def age = 40 - - ["Bob", "Fred", "Ernie", "Bob", "Joe", "Ernie"].each { - new TestEntity(name: it, age: age++).save() - } - - when: - def results = TestEntity.list(sort: [name: "asc", age: "asc"]) - - then: - results[0].name == "Bob" && results[0].age == 40 - results[1].name == "Bob" && results[1].age == 43 - results[2].name == "Ernie" && results[2].age == 42 - results[3].name == "Ernie" && results[3].age == 45 - - when: - results = TestEntity.list(sort: [name: "desc", age: "desc"]) - - then: - results[0].name == "Joe" && results[0].age == 44 - results[1].name == "Fred" && results[1].age == 41 - results[2].name == "Ernie" && results[2].age == 45 - results[3].name == "Ernie" && results[3].age == 42 - - when: - results = TestEntity.list(sort: [name: "asc", age: "desc"]) - - then: - results[0].name == "Bob" && results[0].age == 43 - results[1].name == "Bob" && results[1].age == 40 - results[2].name == "Ernie" && results[2].age == 45 - results[3].name == "Ernie" && results[3].age == 42 - - when: - results = TestEntity.list(sort: [age: "asc", name: "asc"]) - - then: - results[0].name == "Bob" && results[0].age == 40 - results[1].name == "Fred" && results[1].age == 41 - results[2].name == "Ernie" && results[2].age == 42 - results[3].name == "Bob" && results[3].age == 43 - } - - void "Test multiple order by property name with dynamic finder"() { - given: - def age = 40 - - ["Bob", "Fred", "Ernie", "Bob", "Joe", "Ernie"].each { - new TestEntity(name: it, age: age++).save() - } - - when: - def results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort: [name: "asc", age: "asc"]]) - - then: - results[0].name == "Bob" && results[0].age == 40 - results[1].name == "Bob" && results[1].age == 43 - results[2].name == "Ernie" && results[2].age == 42 - results[3].name == "Ernie" && results[3].age == 45 - - when: - results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort: [name: "desc", age: "desc"]]) - - then: - results[0].name == "Joe" && results[0].age == 44 - results[1].name == "Fred" && results[1].age == 41 - results[2].name == "Ernie" && results[2].age == 45 - results[3].name == "Ernie" && results[3].age == 42 - - when: - results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort: [name: "asc", age: "desc"]]) - - then: - results[0].name == "Bob" && results[0].age == 43 - results[1].name == "Bob" && results[1].age == 40 - results[2].name == "Ernie" && results[2].age == 45 - results[3].name == "Ernie" && results[3].age == 42 - - when: - results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort: [age: "asc", name: "asc"]]) - - then: - results[0].name == "Bob" && results[0].age == 40 - results[1].name == "Fred" && results[1].age == 41 - results[2].name == "Ernie" && results[2].age == 42 - results[3].name == "Bob" && results[3].age == 43 - } -} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy deleted file mode 100644 index 8caa81c61..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy +++ /dev/null @@ -1,109 +0,0 @@ -package grails.gorm.tests - -import org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException - -/** - * @author Burt Beckwith - */ -class OptimisticLockingSpec extends GormDatastoreSpec { - - void "Test versioning"() { - - given: - def o = new OptLockVersioned(name: 'locked') - - when: - o.save flush: true - - then: - o.version == 0 - - when: - session.clear() - o = OptLockVersioned.get(o.id) - o.name = 'Fred' - o.save flush: true - - then: - o.version == 1 - - when: - session.clear() - o = OptLockVersioned.get(o.id) - - then: - o.name == 'Fred' - o.version == 1 - } - - void "Test optimistic locking"() { - - given: - def o = new OptLockVersioned(name: 'locked').save(flush: true) - session.clear() - setupClass.transactionManager.commit setupClass.transactionStatus - setupClass.transactionStatus = null - - when: - o = OptLockVersioned.get(o.id) - - OptLockVersioned.withNewSession { s -> - def reloaded = OptLockVersioned.get(o.id) - assert reloaded - reloaded.name += ' in new session' - reloaded.save(flush: true) - } - - o.name += ' in main session' - def ex - try { - o.save(flush: true) - } - catch (e) { - ex = e - e.printStackTrace() - } - - session.clear() - o = OptLockVersioned.get(o.id) - - then: - ex instanceof HibernateOptimisticLockingFailureException - o.version == 1 - o.name == 'locked in new session' - } - - void "Test optimistic locking disabled with 'version false'"() { - given: - def o = new OptLockNotVersioned(name: 'locked').save(flush: true) - session.clear() - setupClass.transactionManager.commit setupClass.transactionStatus - setupClass.transactionStatus = null - - when: - o = OptLockNotVersioned.get(o.id) - - OptLockNotVersioned.withNewSession { s -> - def reloaded = OptLockNotVersioned.get(o.id) - reloaded.name += ' in new session' - reloaded.save(flush: true) - } - - o.name += ' in main session' - def ex - try { - o.save(flush: true) - } - catch (e) { - ex = e - e.printStackTrace() - } - - session.clear() - o = OptLockNotVersioned.get(o.id) - - then: - ex == null - o.name == 'locked in main session' - } -} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/QueryEventsSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/QueryEventsSpec.groovy deleted file mode 100644 index 606aec4a1..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/QueryEventsSpec.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package grails.gorm.tests - -import spock.lang.Specification -import spock.lang.Ignore - -/** - * Ignored - */ -@Ignore("Hibernate GORM uses hibernate Criteria in place of Query class, so events not applicable.") -class QueryEventsSpec extends Specification { -} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/TablePerConcreteClassSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/TablePerConcreteClassSpec.groovy deleted file mode 100644 index 0bb520144..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/TablePerConcreteClassSpec.groovy +++ /dev/null @@ -1,75 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity -import org.hibernate.Session -import java.sql.Connection - -/** - */ -class TablePerConcreteClassSpec extends GormDatastoreSpec{ - - void "Test that table per concrete class produces correct tables"() { - expect:"The table structure is correct" - Payment.withSession { Session session -> - - Connection conn = session.connection() - - conn.prepareStatement("select id, version, amount from payment").execute() - conn.prepareStatement("select id, version, amount, credit_card_type from credit_card_payment").execute() - conn.prepareStatement("select id, version, amount, currency from cash_payment").execute() - } - } - - void "Test that polymorphic queries work correctly with table per concrete class"() { - given:"Some test data with subclasses" - def p = new Payment(amount: 1.1) - p.save() - new CreditCardPayment(creditCardType: 'mastercard', amount: 110).save() - new CreditCardPayment(creditCardType: 'amex', amount: 115).save() - new CashPayment(currency: Currency.getInstance("USD"), amount: 50).save(flush:true) - session.clear() - - expect:"The correct results from queries" - Payment.count() == 4 - CreditCardPayment.count() == 2 - CashPayment.count() == 1 - - when:"The subclasses are loaded" - List creditCardPayments = CreditCardPayment.list() - List cashPayments = CashPayment.list() - List allPayments = Payment.list() - - then:"The results are correct" - creditCardPayments.size() == 2 - creditCardPayments[0].creditCardType == 'mastercard' - creditCardPayments[0].amount== 110 - creditCardPayments[1].creditCardType == 'amex' - creditCardPayments[1].amount== 115 - cashPayments.size() == 1 - cashPayments[0].currency == Currency.getInstance("USD") - allPayments.size() == 4 - - } - - @Override - List getDomainClasses() { - [Payment, CreditCardPayment, CashPayment] - } -} - -@Entity -class Payment { - Long id - Long version - Double amount - - static mapping = { - tablePerConcreteClass true - } -} -class CreditCardPayment extends Payment { - String creditCardType -} -class CashPayment extends Payment { - Currency currency -} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/UniqueConstraintGroupWhithowtVersioningSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/UniqueConstraintGroupWhithowtVersioningSpec.groovy deleted file mode 100644 index ecb07ed5b..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/UniqueConstraintGroupWhithowtVersioningSpec.groovy +++ /dev/null @@ -1,53 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity -import spock.lang.Issue - -class UniqueConstraintGroupWithoutVersioningSpec extends GormDatastoreSpec{ - - @Issue('GRAILS-9936') - void "Test transient uniqueness handling"() { - given:"Some linked objects" - def a2 = new UniqueConstraintTestParentEntity(prop: "prop1") - a2.id = 1 - def b3 = new UniqueConstraintTestChildEntity(prop: "b1", a: a2) - a2.bs = [b3] - when:"validate child item" - def processed = true - try { - b3.validate() - } catch (Exception ex) { - processed = false - } - then:"no exception is thrown" - processed - } - - @Override - List getDomainClasses() { - [UniqueConstraintTestParentEntity, UniqueConstraintTestChildEntity] - } - - def setup() {} -} - -@Entity -class UniqueConstraintTestParentEntity { - Long id - String prop - static hasMany = [bs: UniqueConstraintTestChildEntity] - static mapping = { - version false - id generator: "assigned" - } -} - -@Entity -class UniqueConstraintTestChildEntity { - String prop - static belongsTo = [a: UniqueConstraintTestParentEntity] - - static constraints = { - prop unique:["a"] - } -} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy deleted file mode 100644 index e902aae6c..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy +++ /dev/null @@ -1,79 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Tests the unique constraint - */ -class UniqueConstraintSpec extends GormDatastoreSpec { - - void "Test simple unique constraint"() { - when:"Two domain classes with the same name are saved" - def one = new UniqueGroup(name:"foo").save(flush:true) - def two = new UniqueGroup(name:"foo") - two.save(flush:true) - - then:"The second has errors" - one != null - two.hasErrors() - UniqueGroup.count() == 1 - - when:"The first is saved again" - one = one.save(flush:true) - - then:"The are no errors" - one != null - - when:"Three domain classes are saved within different uniqueness groups" - one = new GroupWithin(name:"foo", org:"mycompany").save(flush:true) - two = new GroupWithin(name:"foo", org:"othercompany").save(flush:true) - def three = new GroupWithin(name:"foo", org:"mycompany") - three.save(flush:true) - - then:"Only the third has errors" - one != null - two != null - three.hasErrors() - GroupWithin.count() == 2 - } - - def "Test unique constraint with a hasOne association"() { - when:"Two domain classes with the same license are saved" - def license = new License() - def one = new Driver(license: license).save(flush: true) - def two = new Driver(license: license) - two.save(flush: true) - - then:"The second has errors" - one != null - two.hasErrors() - Driver.count() == 1 - License.count() == 1 - - when:"The first is saved again" - one = one.save(flush:true) - - then:"The are no errors" - one != null - } - - @Override - List getDomainClasses() { - [UniqueGroup, GroupWithin, Driver, License] - } -} - -@Entity -class Driver implements Serializable { - Long id - static hasOne = [license: License] - static constraints = { - license unique: true - } -} - -@Entity -class License implements Serializable { - Long id - Driver driver -} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy deleted file mode 100644 index 8b4fb738b..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy +++ /dev/null @@ -1,178 +0,0 @@ -package grails.gorm.tests - -import org.springframework.transaction.support.TransactionSynchronizationManager - -/** - * Tests validation semantics. - */ -class ValidationSpec extends GormDatastoreSpec { - - void "Test validate() method"() { - // test assumes name cannot be blank - given: - def t - - when: - t = new TestEntity(name:"") - boolean validationResult = t.validate() - def errors = t.errors - - then: - !validationResult - t.hasErrors() - errors != null - errors.hasErrors() - - when: - t.clearErrors() - - then: - !t.hasErrors() - } - - void 'Test that the binding rejected value is retained after validation'() { - when: - def t = new TestEntity() - t.age = null - t.properties = [age: 'bad value'] - - then: - t.errors.errorCount == 1 - - when: - def ageError = t.errors.getFieldError('age') - - then: - 'bad value' == ageError.rejectedValue - - when: - t.validate() - ageError = t.errors.getFieldError('age') - - then: - 'bad value' == ageError.rejectedValue - } - - void "Test that validate is called on save()"() { - - given: - def t - - when: - t = new TestEntity(name:"") - - then: - t.save() == null - t.hasErrors() == true - 0 == TestEntity.count() - - when: - t.clearErrors() - t.name = "Bob" - t.age = 45 - t.child = new ChildEntity(name:"Fred") - t = t.save() - - then: - t != null - 1 == TestEntity.count() - } - - void "Test beforeValidate gets called on save()"() { - given: - def entityWithNoArgBeforeValidateMethod - def entityWithListArgBeforeValidateMethod - def entityWithOverloadedBeforeValidateMethod - - when: - entityWithNoArgBeforeValidateMethod = new ClassWithNoArgBeforeValidate() - entityWithListArgBeforeValidateMethod = new ClassWithListArgBeforeValidate() - entityWithOverloadedBeforeValidateMethod = new ClassWithOverloadedBeforeValidate() - entityWithNoArgBeforeValidateMethod.save() - entityWithListArgBeforeValidateMethod.save() - entityWithOverloadedBeforeValidateMethod.save() - - then: - 1 == entityWithNoArgBeforeValidateMethod.noArgCounter - 1 == entityWithListArgBeforeValidateMethod.listArgCounter - 1 == entityWithOverloadedBeforeValidateMethod.noArgCounter - 0 == entityWithOverloadedBeforeValidateMethod.listArgCounter - } - - void "Test beforeValidate gets called on validate()"() { - given: - def entityWithNoArgBeforeValidateMethod - def entityWithListArgBeforeValidateMethod - def entityWithOverloadedBeforeValidateMethod - - when: - entityWithNoArgBeforeValidateMethod = new ClassWithNoArgBeforeValidate() - entityWithListArgBeforeValidateMethod = new ClassWithListArgBeforeValidate() - entityWithOverloadedBeforeValidateMethod = new ClassWithOverloadedBeforeValidate() - entityWithNoArgBeforeValidateMethod.validate() - entityWithListArgBeforeValidateMethod.validate() - entityWithOverloadedBeforeValidateMethod.validate() - - then: - 1 == entityWithNoArgBeforeValidateMethod.noArgCounter - 1 == entityWithListArgBeforeValidateMethod.listArgCounter - 1 == entityWithOverloadedBeforeValidateMethod.noArgCounter - 0 == entityWithOverloadedBeforeValidateMethod.listArgCounter - } - - void "Test beforeValidate gets called on validate() and passing a list of field names to validate"() { - given: - def entityWithNoArgBeforeValidateMethod - def entityWithListArgBeforeValidateMethod - def entityWithOverloadedBeforeValidateMethod - - when: - entityWithNoArgBeforeValidateMethod = new ClassWithNoArgBeforeValidate() - entityWithListArgBeforeValidateMethod = new ClassWithListArgBeforeValidate() - entityWithOverloadedBeforeValidateMethod = new ClassWithOverloadedBeforeValidate() - entityWithNoArgBeforeValidateMethod.validate(['name']) - entityWithListArgBeforeValidateMethod.validate(['name']) - entityWithOverloadedBeforeValidateMethod.validate(['name']) - - then: - 1 == entityWithNoArgBeforeValidateMethod.noArgCounter - 1 == entityWithListArgBeforeValidateMethod.listArgCounter - 0 == entityWithOverloadedBeforeValidateMethod.noArgCounter - 1 == entityWithOverloadedBeforeValidateMethod.listArgCounter - ['name'] == entityWithOverloadedBeforeValidateMethod.propertiesPassedToBeforeValidate - } - - void "Test that validate works without a bound Session"() { - - given: - def t - - when: - session.disconnect() - if (TransactionSynchronizationManager.hasResource(session.datastore)) { - TransactionSynchronizationManager.unbindResource(session.datastore) - } - - t = new TestEntity(name:"") - - then: - !session.datastore.hasCurrentSession() - t.save() == null - t.hasErrors() == true - 1 == t.errors.allErrors.size() - TestEntity.getValidationErrorsMap().get(System.identityHashCode(t)).is(t.errors) - 0 == TestEntity.count() - - when: - t.clearErrors() - t.name = "Bob" - t.age = 45 - t.child = new ChildEntity(name:"Fred") - t = t.save(flush: true) - - then: - !session.datastore.hasCurrentSession() - t != null - 1 == TestEntity.count() - } -} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/orm/PagedResultListTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/orm/PagedResultListTests.groovy deleted file mode 100644 index 03a825e77..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/orm/PagedResultListTests.groovy +++ /dev/null @@ -1,40 +0,0 @@ -package grails.orm - -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate -import org.hibernate.impl.CriteriaImpl - -/** - * @author Burt Beckwith - */ -class PagedResultListTests extends GroovyTestCase { - - void testSerialize() { - - def list = new TestPagedResultList() - - new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(list) - - assertTrue list.totalCountCalled - } -} - -class TestCriteria extends CriteriaImpl { - TestCriteria() { super(null, null) } - @Override - List list() { /* do nothing */ } -} - -class TestPagedResultList extends PagedResultList { - - private boolean totalCountCalled = false - - TestPagedResultList() { - super(new GrailsHibernateTemplate(), new TestCriteria()) - } - - @Override - int getTotalCount() { - totalCountCalled = true - 42 - } -} 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/codehaus/groovy/grails/compiler/gorm/GormTransformerSpec.groovy deleted file mode 100644 index 9d59c3655..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformerSpec.groovy +++ /dev/null @@ -1,181 +0,0 @@ -package org.codehaus.groovy.grails.compiler.gorm - -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.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.GormValidationApi -import org.grails.datastore.mapping.simple.SimpleMapDatastore -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 { - - private alwaysInjectGormTransformer = new GormTransformer() { - boolean shouldInject(URL url) { true } - } - - private GrailsAwareClassLoader gcl = new GrailsAwareClassLoader() - - void "Test missing method thrown for uninitialized entity"() { - given: - gcl.classInjectors = [alwaysInjectGormTransformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -@grails.persistence.Entity -class TestEntity { - Long id -} - ''') - cls.load(1) - then: - def e = thrown(MissingMethodException) - e.message.contains '''No signature of method: TestEntity.load() is applicable for argument types''' - } - - void "Test that generic information is added to hasMany collections"() { - given: - def domainTransformer = new DefaultGrailsDomainClassInjector() { - boolean shouldInject(URL url) { true } - } - gcl.classInjectors = [alwaysInjectGormTransformer, domainTransformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -@grails.persistence.Entity -class TestEntity { - Long id - - static hasMany = [associated:Associated] -} - -@grails.persistence.Entity -class Associated { - Long id -} - ''') - - then: - cls.getAnnotation(Entity) != null - cls.getDeclaredField("associated") != null - cls.getDeclaredField("associated").genericType != null - cls.getDeclaredField("associated").genericType.getActualTypeArguments()[0] == gcl.loadClass("Associated") - } - - void "Test that only one annotation is added on already annotated entity"() { - given: - gcl.classInjectors = [alwaysInjectGormTransformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -@grails.persistence.Entity -class TestEntity { - Long id -} - ''') - - then: - cls.getAnnotation(Entity) != null - } - - void "Test transforming a @grails.persistence.Entity marked class doesn't generate duplication methods"() { - given: - gcl.classInjectors = [alwaysInjectGormTransformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -@grails.persistence.Entity -class TestEntity { - Long id -} - ''') - - then: - cls - } - - void "Test that GORM static methods are available on transformation"() { - given: - gcl.classInjectors = [alwaysInjectGormTransformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -class TestEntity { - Long id -} - ''') - cls.count() - - then: - thrown MissingMethodException - - when: - cls.metaClass.static.currentGormStaticApi = {-> null} - cls.count() - - then: - thrown MissingMethodException - - when: - def ds = new SimpleMapDatastore(new BeanBuilder().createApplicationContext() as ConfigurableApplicationContext) - ds.mappingContext.addPersistentEntity(cls) - - cls.metaClass.static.currentGormStaticApi = {-> new GormStaticApi(cls, ds, [])} - - then: - cls.count() == 0 - } - - void "Test that the new Errors property is valid"() { - given: - def transformer = new GormValidationTransformer() { - boolean shouldInject(URL url) { true } - } - gcl.classInjectors = [transformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -class TestEntity { - Long id - Long version - String name -} - ''') - def dc = new DefaultGrailsDomainClass(cls) - - then: - dc.persistentProperties.size() == 1 - - when: - def obj = dc.newInstance() - - then: - obj != null - obj.errors instanceof Errors - - when: - def ds = new SimpleMapDatastore() - - cls.metaClass.static.currentGormValidationApi = {-> new GormValidationApi(cls, ds)} - obj.clearErrors() - - then: - obj.errors.hasErrors() == false - obj.hasErrors() == false - - when: - Errors errors = obj.errors - errors.reject("bad") - - then: - obj.hasErrors() == true - } -} 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/codehaus/groovy/grails/compiler/gorm/GormValidationTransformerSpec.groovy deleted file mode 100644 index 702d3a8c9..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformerSpec.groovy +++ /dev/null @@ -1,43 +0,0 @@ -package org.codehaus.groovy.grails.compiler.gorm - -import org.codehaus.groovy.grails.compiler.injection.ClassInjector -import org.codehaus.groovy.grails.compiler.injection.GrailsAwareClassLoader -import org.grails.datastore.gorm.GormValidationApi -import org.grails.datastore.mapping.simple.SimpleMapDatastore - -import spock.lang.Specification - -class GormValidationTransformerSpec extends Specification { - - void "Test that the validate methods are available via an AST transformation"() { - given: - def gcl = new GrailsAwareClassLoader() - def transformer = new GormValidationTransformer() { - boolean shouldInject(URL url) { true } - } - gcl.classInjectors = [transformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -class TestEntity { - Long id - - String name -} - ''') - def obj = cls.newInstance() - obj.validate() - - then: - thrown IllegalStateException - - when: - - def ds = new SimpleMapDatastore() - ds.mappingContext.addPersistentEntity(cls) - cls.metaClass.static.currentGormValidationApi = {-> new GormValidationApi(cls, ds)} - - then: - obj.validate() == true - } -} \ No newline at end of file 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/codehaus/groovy/grails/compiler/gorm/SessionFactoryProxySpec.groovy deleted file mode 100644 index 8c1e7ef2d..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/SessionFactoryProxySpec.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package org.codehaus.groovy.grails.compiler.gorm - -import grails.spring.BeanBuilder - -import org.codehaus.groovy.grails.orm.hibernate.SessionFactoryHolder -import org.codehaus.groovy.grails.orm.hibernate.SessionFactoryProxy -import org.hibernate.dialect.H2Dialect -import org.springframework.context.ApplicationContext -import org.springframework.orm.hibernate3.LocalSessionFactoryBean - -import spock.lang.Specification - - /** - * Tests for the SessionFactoryProxy class - */ -class SessionFactoryProxySpec extends Specification { - - void "Ensure that SessionFactoryProxy patches SessionFactoryImpl with an appropriate SpringSessionContext"() { - given: - def ctx = applicationContext - when: - def sessionFactory = ctx.getBean("sessionFactoryHolder").sessionFactory - def sessionFactoryProxy = ctx.getBean("sessionFactoryProxy") - - then: - sessionFactory.@currentSessionContext.@sessionFactory == sessionFactoryProxy - } - - void "Verify that we can access other properties of the SessionFactoryImpl via the proxy in Groovy code"() { - given: - def ctx = applicationContext - def sessionFactoryProxy = ctx.getBean("sessionFactoryProxy") - - when: - def eventListeners = sessionFactoryProxy.eventListeners - - then: - eventListeners != null - } - - ApplicationContext getApplicationContext() { - BeanBuilder bb = new BeanBuilder() - bb.beans { - - sessionFactoryHolder(SessionFactoryHolder) { - sessionFactory = bean(LocalSessionFactoryBean) { - hibernateProperties = ["hibernate.dialect":H2Dialect.name] - } - } - - sessionFactoryProxy(SessionFactoryProxy) { - targetBean = "sessionFactoryHolder" - } - } - bb.createApplicationContext() - } -} 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 deleted file mode 100644 index 80ab2f876..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/HibernateSuite.groovy +++ /dev/null @@ -1,60 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.AttachMethodSpec -import grails.gorm.tests.CircularOneToManySpec -import grails.gorm.tests.CommonTypesPersistenceSpec -import grails.gorm.tests.CriteriaBuilderSpec -import grails.gorm.tests.CrudOperationsSpec -import grails.gorm.tests.DomainEventsSpec -import grails.gorm.tests.FindByMethodSpec -import grails.gorm.tests.GormEnhancerSpec -import grails.gorm.tests.GroovyProxySpec -import grails.gorm.tests.InheritanceSpec -import grails.gorm.tests.ListOrderBySpec -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.ProxyLoadingSpec -import grails.gorm.tests.QueryAfterPropertyChangeSpec -import grails.gorm.tests.RangeQuerySpec -import grails.gorm.tests.SaveAllSpec -import grails.gorm.tests.UpdateWithProxyPresentSpec -import grails.gorm.tests.ValidationSpec -import grails.gorm.tests.WithTransactionSpec -import grails.gorm.tests.DeleteAllSpec - -import org.junit.runner.RunWith -import org.junit.runners.Suite -import org.junit.runners.Suite.SuiteClasses - -@RunWith(Suite) -@SuiteClasses([ -// ValidationSpec, -// GroovyProxySpec, -// CommonTypesPersistenceSpec, -// OneToManySpec, -// SaveAllSpec, -// GormEnhancerSpec, -// DomainEventsSpec, -// ProxyLoadingSpec, -// QueryAfterPropertyChangeSpec, -// CircularOneToManySpec, -// InheritanceSpec, -// FindByMethodSpec, -// ListOrderBySpec, -// CriteriaBuilderSpec, -// NegationSpec, -// NamedQuerySpec, -// OrderBySpec, -// RangeQuerySpec, -// UpdateWithProxyPresentSpec, -// AttachMethodSpec, -// WithTransactionSpec, -// CrudOperationsSpec, -// SaveAllSpec, -// DeleteAllSpec - OneToOneSpec -]) -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 deleted file mode 100644 index 28a260a68..000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ /dev/null @@ -1,183 +0,0 @@ -package org.grails.datastore.gorm - -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.metaclass.MetaClassEnhancer -import org.codehaus.groovy.grails.domain.GrailsDomainClassMappingContext -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTransactionManager -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore -import org.codehaus.groovy.grails.orm.hibernate.HibernateGormEnhancer -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration -import org.codehaus.groovy.grails.orm.hibernate.cfg.HibernateUtils -import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor -import org.codehaus.groovy.grails.orm.hibernate.validation.HibernateConstraintsEvaluator -import org.codehaus.groovy.grails.orm.hibernate.validation.PersistentConstraintFactory -import org.codehaus.groovy.grails.orm.hibernate.validation.UniqueConstraint -import org.codehaus.groovy.grails.plugins.web.api.ControllersDomainBindingApi -import org.codehaus.groovy.grails.validation.ConstrainedProperty -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.model.MappingContext -import org.h2.Driver -import org.hibernate.SessionFactory -import org.hibernate.cfg.Environment -import org.hibernate.dialect.H2Dialect -import org.springframework.beans.BeanUtils -import org.springframework.beans.BeanWrapper -import org.springframework.beans.BeanWrapperImpl -import org.springframework.beans.factory.config.BeanDefinition -import org.springframework.beans.factory.support.AbstractBeanDefinition -import org.springframework.beans.factory.support.GenericBeanDefinition -import org.springframework.context.ApplicationContext -import org.springframework.context.support.GenericApplicationContext -import org.springframework.orm.hibernate3.SessionFactoryUtils -import org.springframework.orm.hibernate3.SpringSessionContext -import org.springframework.transaction.TransactionStatus -import org.springframework.transaction.support.DefaultTransactionDefinition -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -class Setup { - static HibernateDatastore hibernateDatastore - static hibernateSession - static GrailsHibernateTransactionManager transactionManager - static TransactionStatus transactionStatus - - static destroy() { - if (hibernateSession != null) { - SessionFactoryUtils.releaseSession hibernateSession, hibernateDatastore.sessionFactory - } - if (transactionStatus) { - transactionManager.rollback(transactionStatus) - transactionStatus = null - } - } - - static Session setup(List classes) { - - def grailsApplication = new DefaultGrailsApplication(classes as Class[], Setup.getClassLoader()) - def ctx = new GenericApplicationContext() - - grailsApplication.applicationContext = ctx - grailsApplication.mainContext = ctx - grailsApplication.initialise() - ctx.beanFactory.registerSingleton 'grailsApplication', grailsApplication - - for (GrailsDomainClass dc in grailsApplication.domainClasses) { - if (!dc.abstract) { - ctx.registerBeanDefinition dc.clazz.name, new GenericBeanDefinition( - autowireMode: AbstractBeanDefinition.AUTOWIRE_BY_NAME, - beanClass: dc.clazz, - scope: BeanDefinition.SCOPE_PROTOTYPE) - } - } - ctx.refresh() - - def config = new Properties() - config.setProperty Environment.DIALECT, H2Dialect.name - config.setProperty Environment.DRIVER, Driver.name - config.setProperty Environment.URL, "jdbc:h2:mem:devDB;MVCC=true" - config.setProperty Environment.USER, "sa" - config.setProperty Environment.PASS, "" - config.setProperty Environment.HBM2DDL_AUTO, "create-drop" - config.setProperty Environment.SHOW_SQL, "true" - config.setProperty Environment.FORMAT_SQL, "true" - config.setProperty Environment.CURRENT_SESSION_CONTEXT_CLASS, SpringSessionContext.name - - GrailsAnnotationConfiguration hibernateConfig = new GrailsAnnotationConfiguration() - hibernateConfig.setProperties config - - def eventTriggeringInterceptor = new ClosureEventTriggeringInterceptor(applicationContext: ctx) - hibernateConfig.setListener 'pre-load', eventTriggeringInterceptor - hibernateConfig.setListener 'post-load', eventTriggeringInterceptor - hibernateConfig.setListener 'save', eventTriggeringInterceptor - hibernateConfig.setListener 'save-update', eventTriggeringInterceptor - hibernateConfig.setListener 'pre-insert', eventTriggeringInterceptor - hibernateConfig.setListener 'post-insert', eventTriggeringInterceptor - hibernateConfig.setListener 'pre-update', eventTriggeringInterceptor - hibernateConfig.setListener 'pre-delete', eventTriggeringInterceptor - hibernateConfig.setListener 'post-update', eventTriggeringInterceptor - hibernateConfig.setListener 'post-delete', eventTriggeringInterceptor - - hibernateConfig.grailsApplication = grailsApplication - - def context = new GrailsDomainClassMappingContext(grailsApplication) - ctx.beanFactory.registerSingleton 'grailsDomainClassMappingContext', context - - SessionFactory sessionFactory = hibernateConfig.buildSessionFactory() - ctx.beanFactory.registerSingleton 'sessionFactory', sessionFactory - - transactionManager = new GrailsHibernateTransactionManager(sessionFactory: sessionFactory) - ctx.beanFactory.registerSingleton 'transactionManager', transactionManager - - hibernateDatastore = new HibernateDatastore(context, sessionFactory, grailsApplication.config, ctx) - ctx.beanFactory.registerSingleton 'hibernateDatastore', hibernateDatastore - - eventTriggeringInterceptor.datastores = [(sessionFactory): hibernateDatastore] - ctx.beanFactory.registerSingleton 'eventTriggeringInterceptor', eventTriggeringInterceptor - - def metaClassEnhancer = new MetaClassEnhancer() - metaClassEnhancer.addApi new ControllersDomainBindingApi() - - HibernateConstraintsEvaluator evaluator = new HibernateConstraintsEvaluator() - grailsApplication.domainClasses.each { GrailsDomainClass dc -> - if (dc.abstract) { - return - } - - metaClassEnhancer.enhance dc.metaClass - - def validator = [supports: { Class c -> true}, validate: { target, Errors errors -> - for (ConstrainedProperty cp in evaluator.evaluate(dc.clazz).values()) { - cp.validate(target, target[cp.propertyName], errors) - } - }] as Validator - - dc.validator = validator - - dc.metaClass.constructor = { -> - def obj - if (ctx.containsBean(dc.fullName)) { - obj = ctx.getBean(dc.fullName) - } - else { - obj = BeanUtils.instantiateClass(dc.clazz) - } - obj - } - } - - def enhancer = new HibernateGormEnhancer(hibernateDatastore, transactionManager, grailsApplication) - enhancer.enhance() - - hibernateDatastore.mappingContext.addMappingContextListener({ e -> - enhancer.enhance e - } as MappingContext.Listener) - - transactionManager = new GrailsHibernateTransactionManager(sessionFactory: sessionFactory) - if (transactionStatus == null) { - transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()) - } - else { - throw new RuntimeException("new transaction started during active transaction") - } - - hibernateSession = SessionFactoryUtils.doGetSession(sessionFactory, true) - - ApplicationContext.metaClass.getProperty = { String name -> - if (delegate.containsBean(name)) { - return delegate.getBean(name) - } - BeanWrapper bw = new BeanWrapperImpl(delegate) - if (bw.isReadableProperty(name)) { - return bw.getPropertyValue(name) - } - } - - HibernateUtils.enhanceSessionFactories(ctx, grailsApplication) - - ConstrainedProperty.registerNewConstraint(UniqueConstraint.UNIQUE_CONSTRAINT, - new PersistentConstraintFactory(ctx, UniqueConstraint)) - - return hibernateDatastore.connect() - } -} diff --git a/grails-datastore-gorm-hibernate4/build.gradle b/grails-datastore-gorm-hibernate4/build.gradle deleted file mode 100644 index 3d1f1159e..000000000 --- a/grails-datastore-gorm-hibernate4/build.gradle +++ /dev/null @@ -1,149 +0,0 @@ -configurations { - provided -} - -dependencies { - - String hibernateVersion = '4.1.11.Final' - - compile("org.grails:grails-core:$grailsVersion") { - exclude group:'commons-logging',module:'commons-logging' - } - compile("org.grails:grails-bootstrap:$grailsVersion") - compile("org.grails:grails-plugin-domain-class:$grailsVersion") { - exclude group: 'org.grails', module:'grails-plugin-testing' - exclude group: 'org.grails', module:'grails-datastore-core' - exclude group: 'org.grails', module:'grails-datastore-gorm' - exclude group: 'org.grails', module:'grails-datastore-simple' - } - compile("org.grails:grails-web:$grailsVersion") - provided 'javax.servlet:servlet-api:2.5' - - compile(project(":grails-datastore-gorm")) { - exclude group: 'org.grails', module:'grails-bootstrap' - exclude group: 'org.grails', module:'grails-core' - exclude group: 'org.grails', module:'grails-async' - exclude group: 'org.grails', module:'grails-plugin-testing' - exclude group: 'org.slf4j', module:'jcl-over-slf4j' - exclude group: 'org.slf4j', module:'jul-to-slf4j' - exclude group: 'org.slf4j', module:'slf4j-api' - exclude group: 'org.slf4j', module:'slf4j-simple' - } - compile(project(":grails-datastore-gorm-plugin-support")) { - exclude group: 'org.grails', module:'grails-bootstrap' - exclude group: 'org.grails', module:'grails-core' - exclude group: 'org.grails', module:'grails-plugin-testing' - } - compile(project(":grails-datastore-core")) { - exclude group: 'org.grails', module:'grails-plugin-testing' - } - compile(project(":grails-datastore-gorm-hibernate-core")) - - compile "org.springframework:spring-jdbc:$springVersion" - compile "org.springframework:spring-orm:$springVersion" - compile "org.springframework:spring-tx:$springVersion" - compile "org.springframework:spring-web:$springVersion" - compile "org.hibernate:hibernate-entitymanager:$hibernateVersion" - - // Specs - compile 'javax.transaction:jta:1.1' - - compile("org.hibernate:hibernate-core:$hibernateVersion") { - exclude group: 'antlr', module: 'antlr' - exclude group:'commons-logging', module:'commons-logging' - exclude group:'dom4j', module:'dom4j' - exclude group:'com.h2database', module:'h2' - exclude group:'commons-collections', module:'commons-collections' - exclude group:'org.slf4j', module:'jcl-over-slf4j' - exclude group:'org.slf4j', module:'slf4j-api' - exclude group:'org.slf4j', module:'slf4j-log4j12' - exclude group:'xml-apis', module:'xml-apis' - } - compile 'org.javassist:javassist:3.17.1-GA' - compile 'javax.transaction:jta:1.1' - runtime('dom4j:dom4j:1.6.1') { - exclude group: 'xml-apis', module:'xml-apis' - } - - compile('org.hibernate.common:hibernate-commons-annotations:4.0.1.Final'){ - exclude group: 'org.slf4j', module:'slf4j-api' - exclude group: 'commons-logging', module:'commons-logging' - } - runtime ("net.sf.ehcache:ehcache-core:2.4.6") { - exclude group: 'commons-logging', module:'commons-logging' - } - compile('org.hibernate:hibernate-validator:4.1.0.Final') { - exclude group:'commons-logging', module:'commons-logging' - exclude group:'commons-collections', module:'commons-collections' - exclude group:'org.slf4j', module:'slf4j-api' - } - runtime("org.hibernate:hibernate-ehcache:$hibernateVersion") { - exclude group:'commons-collections', module:'commons-collections' - exclude group:'commons-logging', module:'commons-logging' - exclude group:'com.h2database', module:'h2' - exclude group:'dom4j', module:'dom4j' - exclude group:'net.sf.ehcache', module:'ehcache' - exclude group:'net.sf.ehcache', module:'ehcache-core' - exclude group:'org.hibernate', module:'hibernate-core' - exclude group:'org.slf4j', module:'jcl-over-slf4j' - exclude group:'org.slf4j', module:'slf4j-api' - exclude group:'org.slf4j', module:'slf4j-log4j12' - exclude group:'xml-apis', module:'xml-apis' - } - runtime ('antlr:antlr:2.7.7') { - exclude group: 'commons-logging', module:'commons-logging' - } - runtime 'javax.validation:validation-api:1.0.0.GA' - - runtime "commons-lang:commons-lang:2.4" - compile("commons-beanutils:commons-beanutils:1.8.0") { - exclude group: 'commons-logging', module:'commons-logging' - } - - testCompile project(":grails-datastore-gorm-test") - testCompile project(":grails-datastore-gorm-tck") - testCompile "com.h2database:h2:1.3.164" - - testCompile("org.grails:grails-core:$grailsVersion") - testCompile("org.grails:grails-bootstrap:$grailsVersion") - testCompile("org.grails:grails-plugin-domain-class:$grailsVersion") { - transitive = false - exclude group: 'org.grails', module:'grails-plugin-testing' - exclude group: 'org.grails', module:'grails-datastore-core' - exclude group: 'org.grails', module:'grails-datastore-gorm' - exclude group: 'org.grails', module:'grails-datastore-simple' - } - testCompile("org.grails:grails-web:$grailsVersion") - testCompile("org.grails:grails-plugin-controllers:$grailsVersion") { - transitive = false - exclude group: 'org.grails', module:'grails-plugin-domain-class' - exclude group: 'org.grails', module:'grails-web' - } - testCompile("org.grails:grails-plugin-validation:$grailsVersion"){ - exclude group: 'org.grails', module:'grails-plugin-domain-class' - } - - testRuntime "javax.servlet:servlet-api:2.5" -} - -sourceSets { - main { - compileClasspath += configurations.provided - } - javadoc { - classpath = configurations.compile + configurations.provided - } -} -idea { - module { - scopes.PROVIDED.plus += configurations.provided - } -} - - -/* -test { - jvmArgs '-Xmx1024m', '-Xdebug', '-Xnoagent', '-Dgrails.full.stacktrace=true', '-Djava.compiler=NONE', - '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005' -} -*/ diff --git a/grails-datastore-gorm-hibernate4/merging_changes.txt b/grails-datastore-gorm-hibernate4/merging_changes.txt deleted file mode 100644 index f2eea1970..000000000 --- a/grails-datastore-gorm-hibernate4/merging_changes.txt +++ /dev/null @@ -1,9 +0,0 @@ - -Hibernate3 and Hibernate4 modules should be kept up-to-date manually. -Code has been copy&pasted. - -Here is an example of patching hibernate4 with changes from hibernate3 module: -git diff 114b02...master ../grails-datastore-gorm-hibernate | sed -e 's/hibernate3/hibernate4/g' | patch -p2 -f - -114b02 is the last merge point in this example - diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java deleted file mode 100644 index f822c6c91..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java +++ /dev/null @@ -1,1987 +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 grails.orm; - -import grails.gorm.DetachedCriteria; -import grails.util.CollectionUtils; -import groovy.lang.Closure; -import groovy.lang.GroovyObjectSupport; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; -import groovy.lang.MetaMethod; -import groovy.lang.MissingMethodException; - -import java.beans.PropertyDescriptor; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -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.query.HibernateCriterionAdapter; -import org.codehaus.groovy.grails.orm.hibernate.query.HibernateProjectionAdapter; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.hibernate.Criteria; -import org.hibernate.FetchMode; -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.TypeHelper; -import org.hibernate.criterion.AggregateProjection; -import org.hibernate.criterion.CountProjection; -import org.hibernate.criterion.CriteriaSpecification; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.IdentifierProjection; -import org.hibernate.criterion.Junction; -import org.hibernate.criterion.Order; -import org.hibernate.criterion.Projection; -import org.hibernate.criterion.ProjectionList; -import org.hibernate.criterion.Projections; -import org.hibernate.criterion.Property; -import org.hibernate.criterion.PropertyProjection; -import org.hibernate.criterion.Restrictions; -import org.hibernate.criterion.SimpleExpression; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metadata.ClassMetadata; -import org.hibernate.sql.JoinType; -import org.hibernate.transform.ResultTransformer; -import org.hibernate.type.AssociationType; -import org.hibernate.type.EmbeddedComponentType; -import org.hibernate.type.StandardBasicTypes; -import org.hibernate.type.Type; -import org.springframework.beans.BeanUtils; -import org.springframework.core.convert.ConversionService; -import org.springframework.orm.hibernate4.SessionHolder; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -/** - *

    Wraps the Hibernate Criteria API in a builder. The builder can be retrieved through the "createCriteria()" dynamic static - * method of Grails domain classes (Example in Groovy): - * - *

    - *         def c = Account.createCriteria()
    - *         def results = c {
    - *             projections {
    - *                 groupProperty("branch")
    - *             }
    - *             like("holderFirstName", "Fred%")
    - *             and {
    - *                 between("balance", 500, 1000)
    - *                 eq("branch", "London")
    - *             }
    - *             maxResults(10)
    - *             order("holderLastName", "desc")
    - *         }
    - * 
    - * - *

    The builder can also be instantiated standalone with a SessionFactory and persistent Class instance: - * - *

    - *      new HibernateCriteriaBuilder(clazz, sessionFactory).list {
    - *         eq("firstName", "Fred")
    - *      }
    - * 
    - * - * @author Graeme Rocher - */ -public class HibernateCriteriaBuilder extends GroovyObjectSupport implements org.grails.datastore.mapping.query.api.Criteria, org.grails.datastore.mapping.query.api.ProjectionList { - - public static final String AND = "and"; // builder - public static final String IS_NULL = "isNull"; // builder - public static final String IS_NOT_NULL = "isNotNull"; // builder - public static final String NOT = "not";// builder - public static final String OR = "or"; // builder - public static final String ID_EQUALS = "idEq"; // builder - public static final String IS_EMPTY = "isEmpty"; //builder - public static final String IS_NOT_EMPTY = "isNotEmpty"; //builder - public static final String RLIKE = "rlike";//method - public static final String BETWEEN = "between";//method - public static final String EQUALS = "eq";//method - public static final String EQUALS_PROPERTY = "eqProperty";//method - public static final String GREATER_THAN = "gt";//method - public static final String GREATER_THAN_PROPERTY = "gtProperty";//method - public static final String GREATER_THAN_OR_EQUAL = "ge";//method - public static final String GREATER_THAN_OR_EQUAL_PROPERTY = "geProperty";//method - public static final String ILIKE = "ilike";//method - public static final String IN = "in";//method - public static final String LESS_THAN = "lt"; //method - public static final String LESS_THAN_PROPERTY = "ltProperty";//method - public static final String LESS_THAN_OR_EQUAL = "le";//method - public static final String LESS_THAN_OR_EQUAL_PROPERTY = "leProperty";//method - public static final String LIKE = "like";//method - public static final String NOT_EQUAL = "ne";//method - public static final String NOT_EQUAL_PROPERTY = "neProperty";//method - public static final String SIZE_EQUALS = "sizeEq"; //method - public static final String ORDER_DESCENDING = "desc"; - public static final String ORDER_ASCENDING = "asc"; - private static final String ROOT_DO_CALL = "doCall"; - private static final String ROOT_CALL = "call"; - private static final String LIST_CALL = "list"; - private static final String LIST_DISTINCT_CALL = "listDistinct"; - private static final String COUNT_CALL = "count"; - private static final String GET_CALL = "get"; - private static final String SCROLL_CALL = "scroll"; - private static final String SET_RESULT_TRANSFORMER_CALL = "setResultTransformer"; - private static final String PROJECTIONS = "projections"; - - private SessionFactory sessionFactory; - private Session hibernateSession; - private Class targetClass; - private Criteria criteria; - private MetaClass criteriaMetaClass; - - private boolean uniqueResult = false; - private List logicalExpressionStack = new ArrayList(); - private List associationStack = new ArrayList(); - private boolean participate; - private boolean scroll; - private boolean count; - private ProjectionList projectionList = Projections.projectionList(); - private List aliasStack = new ArrayList(); - private List aliasInstanceStack = new ArrayList(); - private Map aliasMap = new HashMap(); - private static final String ALIAS = "_alias"; - private ResultTransformer resultTransformer; - private int aliasCount; - - private boolean paginationEnabledList = false; - private List orderEntries; - private GrailsApplication grailsApplication; - private ConversionService conversionService; - - @SuppressWarnings("rawtypes") - public HibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory) { - this.targetClass = targetClass; - this.sessionFactory = sessionFactory; - } - - @SuppressWarnings("rawtypes") - public HibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory, boolean uniqueResult) { - this.targetClass = targetClass; - this.sessionFactory = sessionFactory; - this.uniqueResult = uniqueResult; - } - - public void setGrailsApplication(GrailsApplication grailsApplication) { - this.grailsApplication = grailsApplication; - } - - public void setConversionService(ConversionService conversionService) { - this.conversionService = conversionService; - } - - /** - * Returns the criteria instance - * @return The criteria instance - */ - public Criteria getInstance() { - return criteria; - } - - /** - * Set whether a unique result should be returned - * @param uniqueResult True if a unique result should be returned - */ - public void setUniqueResult(boolean uniqueResult) { - this.uniqueResult = uniqueResult; - } - - /** - * A projection that selects a property name - * @param propertyName The name of the property - */ - public org.grails.datastore.mapping.query.api.ProjectionList property(String propertyName) { - return property(propertyName, null); - } - - /** - * A projection that selects a property name - * @param propertyName The name of the property - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList property(String propertyName, String alias) { - final PropertyProjection propertyProjection = Projections.property(calculatePropertyName(propertyName)); - addProjectionToList(propertyProjection, alias); - return this; - } - - /** - * Adds a projection to the projectList for the given alias - * - * @param propertyProjection The projection - * @param alias The alias - */ - protected void addProjectionToList(Projection propertyProjection, String alias) { - if (alias != null) { - projectionList.add(propertyProjection,alias); - } - else { - projectionList.add(propertyProjection); - } - } - - /** - * Adds a sql projection to the criteria - * - * @param sql SQL projecting a single value - * @param columnAlias column alias for the projected value - * @param type the type of the projected value - */ - protected void sqlProjection(String sql, String columnAlias, Type type) { - sqlProjection(sql, CollectionUtils.newList(columnAlias), CollectionUtils.newList(type)); - } - - /** - * Adds a sql projection to the criteria - * - * @param sql SQL projecting - * @param columnAliases List of column aliases for the projected values - * @param types List of types for the projected values - */ - protected void sqlProjection(String sql, List columnAliases, List types) { - projectionList.add(Projections.sqlProjection(sql, columnAliases.toArray(new String[columnAliases.size()]), types.toArray(new Type[types.size()]))); - } - - /** - * Adds a sql projection to the criteria - * - * @param sql SQL projecting - * @param groupBy group by clause - * @param columnAliases List of column aliases for the projected values - * @param types List of types for the projected values - */ - protected void sqlGroupProjection(String sql, String groupBy, List columnAliases, List types) { - projectionList.add(Projections.sqlGroupProjection(sql, groupBy, columnAliases.toArray(new String[columnAliases.size()]), types.toArray(new Type[types.size()]))); - } - - /** - * A projection that selects a distince property name - * @param propertyName The property name - */ - public org.grails.datastore.mapping.query.api.ProjectionList distinct(String propertyName) { - distinct(propertyName, null); - return this; - } - - /** - * A projection that selects a distince property name - * @param propertyName The property name - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList distinct(String propertyName, String alias) { - final Projection proj = Projections.distinct(Projections.property(calculatePropertyName(propertyName))); - addProjectionToList(proj,alias); - return this; - } - - /** - * A distinct projection that takes a list - * - * @param propertyNames The list of distince property names - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.ProjectionList distinct(Collection propertyNames) { - return distinct(propertyNames, null); - } - - /** - * A distinct projection that takes a list - * - * @param propertyNames The list of distince property names - * @param alias The alias to use - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.ProjectionList distinct(Collection propertyNames, String alias) { - ProjectionList list = Projections.projectionList(); - for (Object o : propertyNames) { - list.add(Projections.property(calculatePropertyName(o.toString()))); - } - final Projection proj = Projections.distinct(list); - addProjectionToList(proj, alias); - return this; - } - - /** - * Adds a projection that allows the criteria to return the property average value - * - * @param propertyName The name of the property - */ - public org.grails.datastore.mapping.query.api.ProjectionList avg(String propertyName) { - return avg(propertyName, null); - } - - /** - * Adds a projection that allows the criteria to return the property average value - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList avg(String propertyName, String alias) { - final AggregateProjection aggregateProjection = Projections.avg(calculatePropertyName(propertyName)); - addProjectionToList(aggregateProjection, alias); - return this; - } - - /** - * Use a join query - * - * @param associationPath The path of the association - */ - public void join(String associationPath) { - criteria.setFetchMode(calculatePropertyName(associationPath), FetchMode.JOIN); - } - - /** - * Whether a pessimistic lock should be obtained. - * - * @param shouldLock True if it should - */ - public void lock(boolean shouldLock) { - String lastAlias = getLastAlias(); - - if (shouldLock) { - if (lastAlias != null) { - criteria.setLockMode(lastAlias, LockMode.PESSIMISTIC_WRITE); - } - else { - criteria.setLockMode(LockMode.PESSIMISTIC_WRITE); - } - } - else { - if (lastAlias != null) { - criteria.setLockMode(lastAlias, LockMode.NONE); - } - else { - criteria.setLockMode(LockMode.NONE); - } - } - } - - /** - * Use a select query - * - * @param associationPath The path of the association - */ - public void select(String associationPath) { - criteria.setFetchMode(calculatePropertyName(associationPath), FetchMode.SELECT); - } - - /** - * Whether to use the query cache - * @param shouldCache True if the query should be cached - */ - public void cache(boolean shouldCache) { - criteria.setCacheable(shouldCache); - } - - /** - * Calculates the property name including any alias paths - * - * @param propertyName The property name - * @return The calculated property name - */ - private String calculatePropertyName(String propertyName) { - String lastAlias = getLastAlias(); - if (lastAlias != null) { - return lastAlias +'.'+propertyName; - } - - return propertyName; - } - - private String getLastAlias() { - if (aliasStack.size() > 0) { - return aliasStack.get(aliasStack.size() - 1).toString(); - } - return null; - } - - public Class getTargetClass() { - return targetClass; - } - - /** - * Calculates the property value, converting GStrings if necessary - * - * @param propertyValue The property value - * @return The calculated property value - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - private Object calculatePropertyValue(Object propertyValue) { - if (propertyValue instanceof CharSequence) { - return propertyValue.toString(); - } - if (propertyValue instanceof QueryableCriteria) { - propertyValue = getHibernateDetachedCriteria((QueryableCriteria)propertyValue); - } - else if (propertyValue instanceof Closure) { - propertyValue = getHibernateDetachedCriteria( - new DetachedCriteria(targetClass).build((Closure)propertyValue)); - } - return propertyValue; - } - - public static org.hibernate.criterion.DetachedCriteria getHibernateDetachedCriteria(QueryableCriteria queryableCriteria) { - org.hibernate.criterion.DetachedCriteria detachedCriteria = org.hibernate.criterion.DetachedCriteria.forClass( - queryableCriteria.getPersistentEntity().getJavaClass()); - populateHibernateDetachedCriteria(detachedCriteria, queryableCriteria); - return detachedCriteria; - } - - private static void populateHibernateDetachedCriteria(org.hibernate.criterion.DetachedCriteria detachedCriteria, QueryableCriteria queryableCriteria) { - List criteriaList = queryableCriteria.getCriteria(); - for (Query.Criterion criterion : criteriaList) { - Criterion hibernateCriterion = new HibernateCriterionAdapter(criterion).toHibernateCriterion(null); - if (hibernateCriterion != null) { - detachedCriteria.add(hibernateCriterion); - } - } - - List projections = queryableCriteria.getProjections(); - ProjectionList projectionList = Projections.projectionList(); - for (Query.Projection projection : projections) { - Projection hibernateProjection = new HibernateProjectionAdapter(projection).toHibernateProjection(); - if (hibernateProjection != null) { - projectionList.add(hibernateProjection); - } - } - detachedCriteria.setProjection(projectionList); - } - - /** - * Adds a projection that allows the criteria to return the property count - * - * @param propertyName The name of the property - */ - public void count(String propertyName) { - count(propertyName, null); - } - - /** - * Adds a projection that allows the criteria to return the property count - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public void count(String propertyName, String alias) { - final CountProjection proj = Projections.count(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); - } - - public org.grails.datastore.mapping.query.api.ProjectionList id() { - final IdentifierProjection proj = Projections.id(); - addProjectionToList(proj, null); - return this; - } - - public org.grails.datastore.mapping.query.api.ProjectionList count() { - return rowCount(); - } - - /** - * Adds a projection that allows the criteria to return the distinct property count - * - * @param propertyName The name of the property - */ - public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(String propertyName) { - return countDistinct(propertyName, null); - } - - public org.grails.datastore.mapping.query.api.ProjectionList distinct() { - return this; - } - - /** - * Adds a projection that allows the criteria to return the distinct property count - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(String propertyName, String alias) { - final CountProjection proj = Projections.countDistinct(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); - return this; - } - - /** - * Adds a projection that allows the criteria's result to be grouped by a property - * - * @param propertyName The name of the property - */ - public void groupProperty(String propertyName) { - groupProperty(propertyName, null); - } - - /** - * Adds a projection that allows the criteria's result to be grouped by a property - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public void groupProperty(String propertyName, String alias) { - final PropertyProjection proj = Projections.groupProperty(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); - } - - /** - * Adds a projection that allows the criteria to retrieve a maximum property value - * - * @param propertyName The name of the property - */ - public org.grails.datastore.mapping.query.api.ProjectionList max(String propertyName) { - return max(propertyName, null); - } - - /** - * Adds a projection that allows the criteria to retrieve a maximum property value - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList max(String propertyName, String alias) { - final AggregateProjection proj = Projections.max(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); - return this; - } - - /** - * Adds a projection that allows the criteria to retrieve a minimum property value - * - * @param propertyName The name of the property - */ - public org.grails.datastore.mapping.query.api.ProjectionList min(String propertyName) { - return min(propertyName, null); - } - - /** - * Adds a projection that allows the criteria to retrieve a minimum property value - * - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList min(String propertyName, String alias) { - final AggregateProjection aggregateProjection = Projections.min(calculatePropertyName(propertyName)); - addProjectionToList(aggregateProjection, alias); - return this; - } - - /** - * Adds a projection that allows the criteria to return the row count - * - */ - public org.grails.datastore.mapping.query.api.ProjectionList rowCount() { - return rowCount(null); - } - - /** - * Adds a projection that allows the criteria to return the row count - * - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList rowCount(String alias) { - final Projection proj = Projections.rowCount(); - addProjectionToList(proj, alias); - return this; - } - - /** - * Adds a projection that allows the criteria to retrieve the sum of the results of a property - * - * @param propertyName The name of the property - */ - public org.grails.datastore.mapping.query.api.ProjectionList sum(String propertyName) { - return sum(propertyName, null); - } - - /** - * Adds a projection that allows the criteria to retrieve the sum of the results of a property - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public org.grails.datastore.mapping.query.api.ProjectionList sum(String propertyName, String alias) { - final AggregateProjection proj = Projections.sum(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); - return this; - } - - /** - * Sets the fetch mode of an associated path - * - * @param associationPath The name of the associated path - * @param fetchMode The fetch mode to set - */ - public void fetchMode(String associationPath, FetchMode fetchMode) { - if (criteria != null) { - criteria.setFetchMode(associationPath, fetchMode); - } - } - - /** - * Sets the resultTransformer. - * @param transformer The result transformer to use. - */ - public void resultTransformer(ResultTransformer transformer) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("Call to [resultTransformer] not supported here")); - } - resultTransformer = transformer; - } - - /** - * Join an association, assigning an alias to the joined association. - *

    - * Functionally equivalent to createAlias(String, String, int) using - * CriteriaSpecificationINNER_JOIN for the joinType. - * - * @param associationPath A dot-seperated property path - * @param alias The alias to assign to the joined association (for later reference). - * - * @return this (for method chaining) - * #see {@link #createAlias(String, String, int)} - * @throws HibernateException Indicates a problem creating the sub criteria - */ - public Criteria createAlias(String associationPath, String alias) { - return criteria.createAlias(associationPath, alias); - } - - /** - * Join an association using the specified join-type, assigning an alias - * to the joined association. - *

    - * The joinType is expected to be one of CriteriaSpecification.INNER_JOIN (the default), - * CriteriaSpecificationFULL_JOIN, or CriteriaSpecificationLEFT_JOIN. - * - * @param associationPath A dot-seperated property path - * @param alias The alias to assign to the joined association (for later reference). - * @param joinType The type of join to use. - * - * @return this (for method chaining) - * @see #createAlias(String, String) - * @throws HibernateException Indicates a problem creating the sub criteria - */ - public Criteria createAlias(String associationPath, String alias, int joinType) { - return criteria.createAlias(associationPath, alias, JoinType.parse(joinType)); - } - - /** - * Creates a Criterion that compares to class properties for equality - * @param propertyName The first property name - * @param otherPropertyName The second property name - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria eqProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [eqProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.eqProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Creates a Criterion that compares to class properties for !equality - * @param propertyName The first property name - * @param otherPropertyName The second property name - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria neProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [neProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.neProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Creates a Criterion that tests if the first property is greater than the second property - * @param propertyName The first property name - * @param otherPropertyName The second property name - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria gtProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [gtProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.gtProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Creates a Criterion that tests if the first property is greater than or equal to the second property - * @param propertyName The first property name - * @param otherPropertyName The second property name - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria geProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [geProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.geProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Creates a Criterion that tests if the first property is less than the second property - * @param propertyName The first property name - * @param otherPropertyName The second property name - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria ltProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [ltProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.ltProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Creates a Criterion that tests if the first property is less than or equal to the second property - * @param propertyName The first property name - * @param otherPropertyName The second property name - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria leProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [leProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.leProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Creates a subquery criterion that ensures the given property is equal to all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria eqAll(String propertyName, Closure propertyValue) { - return eqAll(propertyName, new DetachedCriteria(targetClass).build(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria gtAll(String propertyName, Closure propertyValue) { - return gtAll(propertyName, new DetachedCriteria(targetClass).build(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria ltAll(String propertyName, Closure propertyValue) { - return ltAll(propertyName, new DetachedCriteria(targetClass).build(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria geAll(String propertyName, Closure propertyValue) { - return geAll(propertyName, new DetachedCriteria(targetClass).build(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria leAll(String propertyName, Closure propertyValue) { - return leAll(propertyName, new DetachedCriteria(targetClass).build(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is equal to all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria eqAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).eqAll(getHibernateDetachedCriteria(propertyValue))); - return this; - } - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria gtAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).gtAll(getHibernateDetachedCriteria(propertyValue))); - return this; - } - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria ltAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).ltAll(getHibernateDetachedCriteria(propertyValue))); - return this; - - } - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria geAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).geAll(getHibernateDetachedCriteria(propertyValue))); - return this; - - } - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria leAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).leAll(getHibernateDetachedCriteria(propertyValue))); - return this; - - } - - /** - * Creates a "greater than" Criterion based on the specified property name and value - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria gt(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [gt] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - - Criterion gt; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - gt = Property.forName(propertyName).gt((org.hibernate.criterion.DetachedCriteria)propertyValue); - } - else { - gt = Restrictions.gt(propertyName, propertyValue); - } - addToCriteria(gt); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria lte(String s, Object o) { - return le(s,o); - } - - /** - * Creates a "greater than or equal to" Criterion based on the specified property name and value - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria ge(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [ge] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - - Criterion ge; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - ge = Property.forName(propertyName).ge((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - ge = Restrictions.ge(propertyName, propertyValue); - } - addToCriteria(ge); - return this; - } - - /** - * Creates a "less than" Criterion based on the specified property name and value - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria lt(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [lt] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - Criterion lt; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - lt = Property.forName(propertyName).lt((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - lt = Restrictions.lt(propertyName, propertyValue); - } - addToCriteria(lt); - return this; - } - - /** - * Creates a "less than or equal to" Criterion based on the specified property name and value - * @param propertyName The property name - * @param propertyValue The property value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria le(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [le] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - Criterion le; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - le = Property.forName(propertyName).le((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - le = Restrictions.le(propertyName, propertyValue); - } - addToCriteria(le); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria idEquals(Object o) { - return idEq(o); - } - - public org.grails.datastore.mapping.query.api.Criteria isEmpty(String property) { - String propertyName = calculatePropertyName(property); - addToCriteria(Restrictions.isEmpty(propertyName)); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria isNotEmpty(String property) { - String propertyName = calculatePropertyName(property); - addToCriteria(Restrictions.isNotEmpty(propertyName)); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria isNull(String property) { - String propertyName = calculatePropertyName(property); - addToCriteria(Restrictions.isNull(propertyName)); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria isNotNull(String property) { - String propertyName = calculatePropertyName(property); - addToCriteria(Restrictions.isNotNull(propertyName)); - return this; - } - - /** - * Creates an "equals" Criterion based on the specified property name and value. Case-sensitive. - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria eq(String propertyName, Object propertyValue) { - return eq(propertyName, propertyValue, Collections.emptyMap()); - } - - public org.grails.datastore.mapping.query.api.Criteria idEq(Object o) { - return eq("id", o); - } - - /** - * Groovy moves the map to the first parameter if using the idiomatic form, e.g. - * eq 'firstName', 'Fred', ignoreCase: true. - * @param params optional map with customization parameters; currently only 'ignoreCase' is supported. - * @param propertyName - * @param propertyValue - * @return A Criterion instance - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.Criteria eq(Map params, String propertyName, Object propertyValue) { - return eq(propertyName, propertyValue, params); - } - - /** - * Creates an "equals" Criterion based on the specified property name and value. - * Supports case-insensitive search if the params map contains true - * under the 'ignoreCase' key. - * @param propertyName The property name - * @param propertyValue The property value - * @param params optional map with customization parameters; currently only 'ignoreCase' is supported. - * - * @return A Criterion instance - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.Criteria eq(String propertyName, Object propertyValue, Map params) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [eq] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - Criterion eq; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - eq = Property.forName(propertyName).eq((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - eq = Restrictions.eq(propertyName, propertyValue); - } - if (params != null && (eq instanceof SimpleExpression)) { - Object ignoreCase = params.get("ignoreCase"); - if (ignoreCase instanceof Boolean && (Boolean)ignoreCase) { - eq = ((SimpleExpression)eq).ignoreCase(); - } - } - addToCriteria(eq); - return this; - } - - /** - * Applies a sql restriction to the results to allow something like: -

    -       def results = Person.withCriteria {
    -           sqlRestriction "char_length(first_name) <= 4"
    -       }
    -      
    - * - * @param sqlRestriction the sql restriction - * @return a Criteria instance - */ - public org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sqlRestriction) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sqlRestriction] with value [" + - sqlRestriction + "] not allowed here.")); - } - return sqlRestriction(sqlRestriction, Collections.EMPTY_LIST); - } - - /** - * Applies a sql restriction to the results to allow something like: -
    -       def results = Person.withCriteria {
    -           sqlRestriction "char_length(first_name) < ? AND char_length(first_name) > ?", [4, 9]
    -       }
    -      
    - * - * @param sqlRestriction the sql restriction - * @param values jdbc parameters - * @return a Criteria instance - */ - public org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sqlRestriction, List values) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sqlRestriction] with value [" + - sqlRestriction + "] not allowed here.")); - } - final int numberOfParameters = values.size(); - - final Type[] typesArray = new Type[numberOfParameters]; - final Object[] valuesArray = new Object[numberOfParameters]; - - if (numberOfParameters > 0) { - final TypeHelper typeHelper = sessionFactory.getTypeHelper(); - for (int i = 0; i < typesArray.length; i++) { - final Object value = values.get(i); - typesArray[i] = typeHelper.basic(value.getClass()); - valuesArray[i] = value; - } - } - addToCriteria(Restrictions.sqlRestriction(sqlRestriction, valuesArray, typesArray)); - return this; - } - - /** - * Creates a Criterion with from the specified property name and "like" expression - * @param propertyName The property name - * @param propertyValue The like value - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria like(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [like] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - addToCriteria(Restrictions.like(propertyName, propertyValue)); - return this; - } - - /** - * Creates a Criterion with from the specified property name and "rlike" (a regular expression version of "like") expression - * @param propertyName The property name - * @param propertyValue The ilike value - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria rlike(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [rlike] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - addToCriteria(new RlikeExpression(propertyName, propertyValue)); - return this; - } - - /** - * Creates a Criterion with from the specified property name and "ilike" (a case sensitive version of "like") expression - * @param propertyName The property name - * @param propertyValue The ilike value - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria ilike(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [ilike] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - addToCriteria(Restrictions.ilike(propertyName, propertyValue)); - return this; - } - - /** - * Applys a "in" contrain on the specified property - * @param propertyName The property name - * @param values A collection of values - * - * @return A Criterion instance - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.Criteria in(String propertyName, Collection values) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [in] with propertyName [" + - propertyName + "] and values [" + values + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.in(propertyName, values == null ? Collections.EMPTY_LIST : values)); - return this; - } - - /** - * Delegates to in as in is a Groovy keyword - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.Criteria inList(String propertyName, Collection values) { - return in(propertyName, values); - } - - /** - * Delegates to in as in is a Groovy keyword - */ - public org.grails.datastore.mapping.query.api.Criteria inList(String propertyName, Object[] values) { - return in(propertyName, values); - } - - /** - * Applys a "in" contrain on the specified property - * @param propertyName The property name - * @param values A collection of values - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria in(String propertyName, Object[] values) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [in] with propertyName [" + - propertyName + "] and values [" + values + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.in(propertyName, values)); - return this; - } - - /** - * Orders by the specified property name (defaults to ascending) - * - * @param propertyName The property name to order by - * @return A Order instance - */ - public org.grails.datastore.mapping.query.api.Criteria order(String propertyName) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("Call to [order] with propertyName [" + - propertyName + "]not allowed here.")); - } - propertyName = calculatePropertyName(propertyName); - Order o = Order.asc(propertyName); - if (paginationEnabledList) { - orderEntries.add(o); - } - else { - criteria.addOrder(o); - } - return this; - } - - /** - * Orders by the specified property name (defaults to ascending) - * - * @param o The property name to order by - * @return A Order instance - */ - public org.grails.datastore.mapping.query.api.Criteria order(Order o) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("Call to [order] not allowed here.")); - } - if (paginationEnabledList) { - orderEntries.add(o); - } - else { - criteria.addOrder(o); - } - return this; - } - - /** - * Orders by the specified property name and direction - * - * @param propertyName The property name to order by - * @param direction Either "asc" for ascending or "desc" for descending - * - * @return A Order instance - */ - public org.grails.datastore.mapping.query.api.Criteria order(String propertyName, String direction) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("Call to [order] with propertyName [" + - propertyName + "]not allowed here.")); - } - propertyName = calculatePropertyName(propertyName); - Order o; - if (direction.equals(ORDER_DESCENDING)) { - o = Order.desc(propertyName); - } - else { - o = Order.asc(propertyName); - } - if (paginationEnabledList) { - orderEntries.add(o); - } - else { - criteria.addOrder(o); - } - return this; - } - - /** - * Creates a Criterion that contrains a collection property by size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria sizeEq(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeEq] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeEq(propertyName, size)); - return this; - } - - /** - * Creates a Criterion that contrains a collection property to be greater than the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria sizeGt(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeGt] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeGt(propertyName, size)); - return this; - } - - /** - * Creates a Criterion that contrains a collection property to be greater than or equal to the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria sizeGe(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeGe] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeGe(propertyName, size)); - return this; - } - - /** - * Creates a Criterion that contrains a collection property to be less than or equal to the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria sizeLe(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeLe] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeLe(propertyName, size)); - return this; - } - - /** - * Creates a Criterion that contrains a collection property to be less than to the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria sizeLt(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeLt] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeLt(propertyName, size)); - return this; - } - - /** - * Creates a Criterion that contrains a collection property to be not equal to the given size - * - * @param propertyName The property name - * @param size The size to constrain by - * - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria sizeNe(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeNe] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeNe(propertyName, size)); - return this; - } - - /** - * Creates a "not equal" Criterion based on the specified property name and value - * @param propertyName The property name - * @param propertyValue The property value - * @return The criterion object - */ - public org.grails.datastore.mapping.query.api.Criteria ne(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [ne] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - addToCriteria(Restrictions.ne(propertyName, propertyValue)); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria notEqual(String propertyName, Object propertyValue) { - return ne(propertyName, propertyValue); - } - - /** - * Creates a "between" Criterion based on the property name and specified lo and hi values - * @param propertyName The property name - * @param lo The low value - * @param hi The high value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria between(String propertyName, Object lo, Object hi) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [between] with propertyName [" + - propertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.between(propertyName, lo, hi)); - return this; - } - - public org.grails.datastore.mapping.query.api.Criteria gte(String s, Object o) { - return ge(s, o); - } - - private boolean validateSimpleExpression() { - return criteria != null; - } - - @SuppressWarnings("rawtypes") - @Override - public Object invokeMethod(String name, Object obj) { - Object[] args = obj.getClass().isArray() ? (Object[])obj : new Object[]{obj}; - - if (paginationEnabledList && SET_RESULT_TRANSFORMER_CALL.equals(name) && args.length == 1 && - args[0] instanceof ResultTransformer) { - resultTransformer = (ResultTransformer) args[0]; - return null; - } - - if (isCriteriaConstructionMethod(name, args)) { - if (criteria != null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - - if (name.equals(GET_CALL)) { - uniqueResult = true; - } - else if (name.equals(SCROLL_CALL)) { - scroll = true; - } - else if (name.equals(COUNT_CALL)) { - count = true; - } - else if (name.equals(LIST_DISTINCT_CALL)) { - resultTransformer = CriteriaSpecification.DISTINCT_ROOT_ENTITY; - } - - createCriteriaInstance(); - - // Check for pagination params - if (name.equals(LIST_CALL) && args.length == 2) { - paginationEnabledList = true; - orderEntries = new ArrayList(); - invokeClosureNode(args[1]); - } - else { - invokeClosureNode(args[0]); - } - - if (resultTransformer != null) { - criteria.setResultTransformer(resultTransformer); - } - Object result; - if (!uniqueResult) { - if (scroll) { - result = criteria.scroll(); - } - else if (count) { - criteria.setProjection(Projections.rowCount()); - result = criteria.uniqueResult(); - } - else if (paginationEnabledList) { - // Calculate how many results there are in total. This has been - // moved to before the 'list()' invocation to avoid any "ORDER - // BY" clause added by 'populateArgumentsForCriteria()', otherwise - // an exception is thrown for non-string sort fields (GRAILS-2690). - criteria.setFirstResult(0); - criteria.setMaxResults(Integer.MAX_VALUE); - - // Restore the previous projection, add settings for the pagination parameters, - // and then execute the query. - if (projectionList != null && projectionList.getLength() > 0) { - criteria.setProjection(projectionList); - } else { - criteria.setProjection(null); - } - for (Order orderEntry : orderEntries) { - criteria.addOrder(orderEntry); - } - if (resultTransformer == null) { - criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY); - } - else if (paginationEnabledList) { - // relevant to GRAILS-5692 - criteria.setResultTransformer(resultTransformer); - } - // GRAILS-7324 look if we already have association to sort by - Map argMap = (Map)args[0]; - final String sort = (String) argMap.get(GrailsHibernateUtil.ARGUMENT_SORT); - if (sort != null) { - boolean ignoreCase = true; - Object caseArg = argMap.get(GrailsHibernateUtil.ARGUMENT_IGNORE_CASE); - if (caseArg instanceof Boolean) { - ignoreCase = (Boolean) caseArg; - } - final String orderParam = (String) argMap.get(GrailsHibernateUtil.ARGUMENT_ORDER); - final String order = GrailsHibernateUtil.ORDER_DESC.equalsIgnoreCase(orderParam) ? - GrailsHibernateUtil.ORDER_DESC : GrailsHibernateUtil.ORDER_ASC; - int lastPropertyPos = sort.lastIndexOf('.'); - String associationForOrdering = lastPropertyPos >= 0 ? sort.substring(0, lastPropertyPos) : null; - if (associationForOrdering != null && aliasMap.containsKey(associationForOrdering)) { - addOrder(criteria, aliasMap.get(associationForOrdering) + "." + sort.substring(lastPropertyPos + 1), - order, ignoreCase); - // remove sort from arguments map to exclude from default processing. - @SuppressWarnings("unchecked") Map argMap2 = new HashMap(argMap); - argMap2.remove(GrailsHibernateUtil.ARGUMENT_SORT); - argMap = argMap2; - } - } - GrailsHibernateUtil.populateArgumentsForCriteria(grailsApplication, targetClass, criteria, argMap, conversionService); - GrailsHibernateTemplate ght = new GrailsHibernateTemplate(sessionFactory, grailsApplication); - PagedResultList pagedRes = new PagedResultList(ght, criteria); - result = pagedRes; - } - else { - result = criteria.list(); - } - } - else { - result = GrailsHibernateUtil.unwrapIfProxy(criteria.uniqueResult()); - } - if (!participate) { - hibernateSession.close(); - } - return result; - } - - if (criteria == null) createCriteriaInstance(); - - MetaMethod metaMethod = getMetaClass().getMetaMethod(name, args); - if (metaMethod != null) { - return metaMethod.invoke(this, args); - } - - metaMethod = criteriaMetaClass.getMetaMethod(name, args); - if (metaMethod != null) { - return metaMethod.invoke(criteria, args); - } - metaMethod = criteriaMetaClass.getMetaMethod(GrailsClassUtils.getSetterName(name), args); - if (metaMethod != null) { - return metaMethod.invoke(criteria, args); - } - - if (isAssociationQueryMethod(args) || isAssociationQueryWithJoinSpecificationMethod(args)) { - final boolean hasMoreThanOneArg = args.length > 1; - Object callable = hasMoreThanOneArg ? args[1] : args[0]; - JoinType joinType = hasMoreThanOneArg ? JoinType.parse((Integer)args[0]) : JoinType.INNER_JOIN; - - if (name.equals(AND) || name.equals(OR) || name.equals(NOT)) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - - logicalExpressionStack.add(new LogicalExpression(name)); - invokeClosureNode(callable); - - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - addToCriteria(logicalExpression.toCriterion()); - - return name; - } - - if (name.equals(PROJECTIONS) && args.length == 1 && (args[0] instanceof Closure)) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - - projectionList = Projections.projectionList(); - invokeClosureNode(callable); - - if (projectionList != null && projectionList.getLength() > 0) { - criteria.setProjection(projectionList); - } - - return name; - } - - final PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(targetClass, name); - if (pd != null && pd.getReadMethod() != null) { - ClassMetadata meta = sessionFactory.getClassMetadata(targetClass); - Type type = meta.getPropertyType(name); - if (type.isAssociationType()) { - String otherSideEntityName = ((AssociationType) type).getAssociatedEntityName((SessionFactoryImplementor) sessionFactory); - Class oldTargetClass = targetClass; - targetClass = sessionFactory.getClassMetadata(otherSideEntityName).getMappedClass(); - if (targetClass.equals(oldTargetClass) && !hasMoreThanOneArg) { - joinType = JoinType.LEFT_OUTER_JOIN; // default to left join if joining on the same table - } - associationStack.add(name); - final String associationPath = getAssociationPath(); - createAliasIfNeccessary(name, associationPath,joinType); - // the criteria within an association node are grouped with an implicit AND - logicalExpressionStack.add(new LogicalExpression(AND)); - invokeClosureNode(callable); - aliasStack.remove(aliasStack.size() - 1); - if (!aliasInstanceStack.isEmpty()) { - aliasInstanceStack.remove(aliasInstanceStack.size() - 1); - } - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - if (!logicalExpression.args.isEmpty()) { - addToCriteria(logicalExpression.toCriterion()); - } - associationStack.remove(associationStack.size()-1); - targetClass = oldTargetClass; - - return name; - } - if (type instanceof EmbeddedComponentType) { - associationStack.add(name); - logicalExpressionStack.add(new LogicalExpression(AND)); - Class oldTargetClass = targetClass; - targetClass = pd.getPropertyType(); - invokeClosureNode(callable); - targetClass = oldTargetClass; - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - if (!logicalExpression.args.isEmpty()) { - addToCriteria(logicalExpression.toCriterion()); - } - associationStack.remove(associationStack.size()-1); - return name; - } - } - } - else if (args.length == 1 && args[0] != null) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - - Object value = args[0]; - Criterion c = null; - if (name.equals(ID_EQUALS)) { - return eq("id", value); - } - - if (name.equals(IS_NULL) || - name.equals(IS_NOT_NULL) || - name.equals(IS_EMPTY) || - name.equals(IS_NOT_EMPTY)) { - if (!(value instanceof String)) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] with value [" + - value + "] requires a String value.")); - } - String propertyName = calculatePropertyName((String)value); - if (name.equals(IS_NULL)) { - c = Restrictions.isNull(propertyName); - } - else if (name.equals(IS_NOT_NULL)) { - c = Restrictions.isNotNull(propertyName); - } - else if (name.equals(IS_EMPTY)) { - c = Restrictions.isEmpty(propertyName); - } - else if (name.equals(IS_NOT_EMPTY)) { - c = Restrictions.isNotEmpty(propertyName); - } - } - - if (c != null) { - return addToCriteria(c); - } - } - - throw new MissingMethodException(name, getClass(), args); - } - - private boolean isAssociationQueryMethod(Object[] args) { - return args.length == 1 && args[0] instanceof Closure; - } - - private boolean isAssociationQueryWithJoinSpecificationMethod(Object[] args) { - return args.length == 2 && (args[0] instanceof Number) && (args[1] instanceof Closure); - } - - @SuppressWarnings("unused") - private void addToCurrentOrAliasedCriteria(Criterion criterion) { - if (!aliasInstanceStack.isEmpty()) { - Criteria c = aliasInstanceStack.get(aliasInstanceStack.size()-1); - c.add(criterion); - } - else { - criteria.add(criterion); - } - } - - private void createAliasIfNeccessary(String associationName, String associationPath, JoinType joinType) { - String newAlias; - if (aliasMap.containsKey(associationPath)) { - newAlias = aliasMap.get(associationPath); - } - else { - aliasCount++; - newAlias = associationName + ALIAS + aliasCount; - aliasMap.put(associationPath, newAlias); - aliasInstanceStack.add(criteria.createAlias(associationPath, newAlias, joinType)); - } - aliasStack.add(newAlias); - } - - private String getAssociationPath() { - StringBuilder fullPath = new StringBuilder(); - for (Object anAssociationStack : associationStack) { - String propertyName = (String) anAssociationStack; - if (fullPath.length() > 0) fullPath.append("."); - fullPath.append(propertyName); - } - return fullPath.toString(); - } - - private boolean isCriteriaConstructionMethod(String name, Object[] args) { - return (name.equals(LIST_CALL) && args.length == 2 && args[0] instanceof Map && args[1] instanceof Closure) || - (name.equals(ROOT_CALL) || - name.equals(ROOT_DO_CALL) || - name.equals(LIST_CALL) || - name.equals(LIST_DISTINCT_CALL) || - name.equals(GET_CALL) || - name.equals(COUNT_CALL) || - name.equals(SCROLL_CALL) && args.length == 1 && args[0] instanceof Closure); - } - - public Criteria buildCriteria(Closure criteriaClosure) { - createCriteriaInstance(); - criteriaClosure.setDelegate(this); - criteriaClosure.call(); - return criteria; - } - - private void createCriteriaInstance() { - if (TransactionSynchronizationManager.hasResource(sessionFactory)) { - participate = true; - hibernateSession = ((SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory)).getSession(); - } - else { - hibernateSession = sessionFactory.openSession(); - } - - criteria = hibernateSession.createCriteria(targetClass); - GrailsHibernateUtil.cacheCriteriaByMapping(grailsApplication, targetClass, criteria); - criteriaMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(criteria.getClass()); - } - - private void invokeClosureNode(Object args) { - Closure callable = (Closure)args; - callable.setDelegate(this); - callable.setResolveStrategy(Closure.DELEGATE_FIRST); - callable.call(); - } - - /** - * Throws a runtime exception where necessary to ensure the session gets closed - */ - private void throwRuntimeException(RuntimeException t) { - closeSessionFollowingException(); - throw t; - } - - private void closeSessionFollowingException() { - if (hibernateSession != null && hibernateSession.isOpen() && !participate) { - hibernateSession.close(); - } - criteria = null; - } - - /** - * adds and returns the given criterion to the currently active criteria set. - * this might be either the root criteria or a currently open - * LogicalExpression. - */ - private Criterion addToCriteria(Criterion c) { - if (!logicalExpressionStack.isEmpty()) { - logicalExpressionStack.get(logicalExpressionStack.size() - 1).args.add(c); - } - else { - criteria.add(c); - } - return c; - } - - /** - * instances of this class are pushed onto the logicalExpressionStack - * to represent all the unfinished "and", "or", and "not" expressions. - */ - private class LogicalExpression { - final Object name; - final List args = new ArrayList(); - - LogicalExpression(Object name) { - this.name = name; - } - - Criterion toCriterion() { - if (name.equals(NOT)) { - switch (args.size()) { - case 0: - throwRuntimeException(new IllegalArgumentException("Logical expression [not] must contain at least 1 expression")); - return null; - - case 1: - return Restrictions.not(args.get(0)); - - default: - // treat multiple sub-criteria as an implicit "OR" - return Restrictions.not(buildJunction(Restrictions.disjunction(), args)); - } - } - - if (name.equals(AND)) { - return buildJunction(Restrictions.conjunction(), args); - } - - if (name.equals(OR)) { - return buildJunction(Restrictions.disjunction(), args); - } - - throwRuntimeException(new IllegalStateException("Logical expression [" + name + "] not handled!")); - return null; - } - - // add the Criterion objects in the given list to the given junction. - Junction buildJunction(Junction junction, List criterions) { - for (Criterion c : criterions) { - junction.add(c); - } - - return junction; - } - } - - /** - * Add order directly to criteria. - */ - private static void addOrder(Criteria c, String sort, String order, boolean ignoreCase) { - if (GrailsHibernateUtil.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) ); - } - } - - /* - * Define constants which may be used inside of criteria queries - * to refer to standard Hibernate Type instances. - */ - public static final Type BOOLEAN = StandardBasicTypes.BOOLEAN; - public static final Type YES_NO = StandardBasicTypes.YES_NO; - public static final Type BYTE = StandardBasicTypes.BYTE; - public static final Type CHARACTER = StandardBasicTypes.CHARACTER; - public static final Type SHORT = StandardBasicTypes.SHORT; - public static final Type INTEGER = StandardBasicTypes.INTEGER; - public static final Type LONG = StandardBasicTypes.LONG; - public static final Type FLOAT = StandardBasicTypes.FLOAT; - public static final Type DOUBLE = StandardBasicTypes.DOUBLE; - public static final Type BIG_DECIMAL = StandardBasicTypes.BIG_DECIMAL; - public static final Type BIG_INTEGER = StandardBasicTypes.BIG_INTEGER; - public static final Type STRING = StandardBasicTypes.STRING; - public static final Type NUMERIC_BOOLEAN = StandardBasicTypes.NUMERIC_BOOLEAN; - public static final Type TRUE_FALSE = StandardBasicTypes.TRUE_FALSE; - public static final Type URL = StandardBasicTypes.URL; - public static final Type TIME = StandardBasicTypes.TIME; - public static final Type DATE = StandardBasicTypes.DATE; - public static final Type TIMESTAMP = StandardBasicTypes.TIMESTAMP; - public static final Type CALENDAR = StandardBasicTypes.CALENDAR; - public static final Type CALENDAR_DATE = StandardBasicTypes.CALENDAR_DATE; - public static final Type CLASS = StandardBasicTypes.CLASS; - public static final Type LOCALE = StandardBasicTypes.LOCALE; - public static final Type CURRENCY = StandardBasicTypes.CURRENCY; - public static final Type TIMEZONE = StandardBasicTypes.TIMEZONE; - public static final Type UUID_BINARY = StandardBasicTypes.UUID_BINARY; - public static final Type UUID_CHAR = StandardBasicTypes.UUID_CHAR; - public static final Type BINARY = StandardBasicTypes.BINARY; - public static final Type WRAPPER_BINARY = StandardBasicTypes.WRAPPER_BINARY; - public static final Type IMAGE = StandardBasicTypes.IMAGE; - public static final Type BLOB = StandardBasicTypes.BLOB; - public static final Type MATERIALIZED_BLOB = StandardBasicTypes.MATERIALIZED_BLOB; - public static final Type CHAR_ARRAY = StandardBasicTypes.CHAR_ARRAY; - public static final Type CHARACTER_ARRAY = StandardBasicTypes.CHARACTER_ARRAY; - public static final Type TEXT = StandardBasicTypes.TEXT; - public static final Type CLOB = StandardBasicTypes.CLOB; - public static final Type MATERIALIZED_CLOB = StandardBasicTypes.MATERIALIZED_CLOB; - public static final Type SERIALIZABLE = StandardBasicTypes.SERIALIZABLE; -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/PagedResultList.java b/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/PagedResultList.java deleted file mode 100644 index 225cbb960..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/PagedResultList.java +++ /dev/null @@ -1,200 +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 grails.orm; - -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.sql.SQLException; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.criterion.Projections; -import org.hibernate.internal.CriteriaImpl; - -/** - * A result list for Criteria list calls, which is aware of the totalCount for - * the paged result. - * - * @author Siegfried Puchbauer - * @since 1.0 - */ -@SuppressWarnings({"unchecked","rawtypes"}) -public class PagedResultList implements List, Serializable { - - private static final long serialVersionUID = -5820655628956173929L; - - protected List list; - - protected int totalCount = Integer.MIN_VALUE; - - private transient GrailsHibernateTemplate hibernateTemplate; - private final Criteria criteria; - - public PagedResultList(GrailsHibernateTemplate template, Criteria crit) { - list = crit.list(); - criteria = crit; - hibernateTemplate = template; - } - - public int size() { - return list.size(); - } - - public boolean isEmpty() { - return list.isEmpty(); - } - - public boolean contains(Object o) { - return list.contains(o); - } - - public Iterator iterator() { - return list.iterator(); - } - - public Object[] toArray() { - return list.toArray(); - } - - public Object[] toArray(Object[] objects) { - return list.toArray(objects); - } - - public boolean add(Object o) { - return list.add(o); - } - - public boolean remove(Object o) { - return list.remove(o); - } - - public boolean containsAll(Collection collection) { - return list.containsAll(collection); - } - - public boolean addAll(Collection collection) { - return list.addAll(collection); - } - - public boolean addAll(int i, Collection collection) { - return list.addAll(i, collection); - } - - public boolean removeAll(Collection collection) { - return list.removeAll(collection); - } - - public boolean retainAll(Collection collection) { - return list.retainAll(collection); - } - - public void clear() { - list.clear(); - } - - @Override - public boolean equals(Object o) { - return list.equals(o); - } - - @Override - public int hashCode() { - return list.hashCode(); - } - - public Object get(int i) { - return list.get(i); - } - - public Object set(int i, Object o) { - return list.set(i, o); - } - - public void add(int i, Object o) { - list.add(i, o); - } - - public Object remove(int i) { - return list.remove(i); - } - - public int indexOf(Object o) { - return list.indexOf(o); - } - - public int lastIndexOf(Object o) { - return list.lastIndexOf(o); - } - - public ListIterator listIterator() { - return list.listIterator(); - } - - public ListIterator listIterator(int i) { - return list.listIterator(i); - } - - public List subList(int i, int i1) { - return list.subList(i, i1); - } - - public int getTotalCount() { - if (totalCount == Integer.MIN_VALUE) { - totalCount = hibernateTemplate.execute(new GrailsHibernateTemplate.HibernateCallback() { - public Integer doInHibernate(Session session) throws HibernateException, SQLException { - CriteriaImpl impl = (CriteriaImpl) criteria; - Criteria totalCriteria = session.createCriteria(impl.getEntityOrClassName()); - hibernateTemplate.applySettings(totalCriteria); - - Iterator iterator = impl.iterateExpressionEntries(); - while (iterator.hasNext()) { - CriteriaImpl.CriterionEntry entry = (CriteriaImpl.CriterionEntry) iterator.next(); - totalCriteria.add(entry.getCriterion()); - } - Iterator subcriteriaIterator = impl.iterateSubcriteria(); - while (subcriteriaIterator.hasNext()) { - CriteriaImpl.Subcriteria sub = (CriteriaImpl.Subcriteria) subcriteriaIterator.next(); - totalCriteria.createAlias(sub.getPath(), sub.getAlias(), sub.getJoinType(), sub.getWithClause()); - } - totalCriteria.setProjection(impl.getProjection()); - totalCriteria.setProjection(Projections.rowCount()); - return ((Number)totalCriteria.uniqueResult()).intValue(); - } - }); - } - return totalCount; - } - - public void setTotalCount(int totalCount) { - this.totalCount = totalCount; - } - - private void writeObject(ObjectOutputStream out) throws IOException { - - // find the total count if it hasn't been done yet so when this is deserialized - // the null GrailsHibernateTemplate won't be an issue - getTotalCount(); - - out.defaultWriteObject(); - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/RlikeExpression.java b/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/RlikeExpression.java deleted file mode 100644 index 76eed0581..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/grails/orm/RlikeExpression.java +++ /dev/null @@ -1,80 +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 grails.orm; - -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.criterion.CriteriaQuery; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.MatchMode; -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.MySQLDialect; -import org.hibernate.dialect.Oracle8iDialect; -import org.hibernate.engine.spi.TypedValue; - -/** - * Adds support for rlike to Hibernate in supported dialects. - * - * @author Graeme Rocher - * @since 1.1.1 - */ -public class RlikeExpression implements Criterion { - - private static final long serialVersionUID = -214329918050957956L; - - private final String propertyName; - private final Object value; - - public RlikeExpression(String propertyName, Object value) { - this.propertyName = propertyName; - this.value = value; - } - - public RlikeExpression(String propertyName, String value, MatchMode matchMode) { - this(propertyName, matchMode.toMatchString(value)); - } - - public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { - Dialect dialect = criteriaQuery.getFactory().getDialect(); - String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName); - if (columns.length != 1) { - throw new HibernateException("ilike may only be used with single-column properties"); - } - - if (dialect instanceof MySQLDialect) { - return columns[0] + " rlike ?"; - } - - if (isOracleDialect(dialect)) { - return " REGEXP_LIKE (" + columns[0] + ", ?)"; - } - - return columns[0] + " like ?"; - } - - private boolean isOracleDialect(Dialect dialect) { - return (dialect instanceof Oracle8iDialect); - } - - public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { - return new TypedValue[] { criteriaQuery.getTypedValue(criteria, propertyName, value.toString().toLowerCase()) }; - } - - @Override - public String toString() { - return propertyName + " rlike " + value; - } -} 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 deleted file mode 100644 index a6c0047b4..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/ConfigurableLocalSessionFactoryBean.java +++ /dev/null @@ -1,598 +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; - -import groovy.lang.GroovySystem; -import groovy.lang.MetaClassRegistry; - -import java.io.File; -import java.lang.reflect.InvocationTargetException; -import java.util.Map; -import java.util.Properties; - -import javax.naming.NameNotFoundException; -import javax.sql.DataSource; - -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.hibernate.HibernateException; -import org.hibernate.Interceptor; -import org.hibernate.SessionFactory; -import org.hibernate.cache.CacheException; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.metadata.ClassMetadata; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanClassLoaderAware; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ResourceLoaderAware; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternUtils; -import org.springframework.orm.hibernate4.HibernateExceptionTranslator; -import org.springframework.util.Assert; - -/** - * A SessionFactory bean that allows the configuration class to - * be changed and customise for usage within Grails. - * - * @author Graeme Rocher - * @since 07-Jul-2005 - */ -public class ConfigurableLocalSessionFactoryBean extends HibernateExceptionTranslator - implements FactoryBean, ResourceLoaderAware, InitializingBean, DisposableBean, - ApplicationContextAware, BeanClassLoaderAware { - - private DataSource dataSource; - private Resource[] configLocations; - private String[] mappingResources; - private Resource[] mappingLocations; - private Resource[] cacheableMappingLocations; - private Resource[] mappingJarLocations; - private Resource[] mappingDirectoryLocations; - private Interceptor entityInterceptor; - private NamingStrategy namingStrategy; - private Properties hibernateProperties; - private Class[] annotatedClasses; - private String[] annotatedPackages; - private String[] packagesToScan; - private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); - private GrailsAnnotationConfiguration configuration; - private SessionFactory sessionFactory; - - protected Logger log = LoggerFactory.getLogger(getClass()); - protected GrailsApplication grailsApplication; - protected ClassLoader classLoader; - protected Class configClass; - protected Class currentSessionContextClass; - protected Map eventListeners; - protected HibernateEventListeners hibernateEventListeners; - protected ApplicationContext applicationContext; - protected boolean proxyIfReloadEnabled = true; - protected String sessionFactoryBeanName = "sessionFactory"; - protected String dataSourceName = GrailsDomainClassProperty.DEFAULT_DATA_SOURCE; - - /** - * Set the DataSource to be used by the SessionFactory. - * If set, this will override corresponding settings in Hibernate properties. - *

    If this is set, the Hibernate settings should not define - * a connection provider to avoid meaningless double configuration. - */ - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - } - public DataSource getDataSource() { - return dataSource; - } - - /** - * Set the location of a single Hibernate XML config file, for example as - * classpath resource "classpath:hibernate.cfg.xml". - *

    Note: Can be omitted when all necessary properties and mapping - * resources are specified locally via this bean. - * @see org.hibernate.cfg.Configuration#configure(java.net.URL) - */ - public void setConfigLocation(Resource configLocation) { - configLocations = new Resource[] {configLocation}; - } - - /** - * Set the locations of multiple Hibernate XML config files, for example as - * classpath resources "classpath:hibernate.cfg.xml,classpath:extension.cfg.xml". - *

    Note: Can be omitted when all necessary properties and mapping - * resources are specified locally via this bean. - * @see org.hibernate.cfg.Configuration#configure(java.net.URL) - */ - public void setConfigLocations(Resource[] configLocations) { - this.configLocations = configLocations; - } - public Resource[] getConfigLocations() { - return configLocations; - } - - /** - * Set Hibernate mapping resources to be found in the class path, - * like "example.hbm.xml" or "mypackage/example.hbm.xml". - * Analogous to mapping entries in a Hibernate XML config file. - * Alternative to the more generic setMappingLocations method. - *

    Can be used to add to mappings from a Hibernate XML config file, - * or to specify all mappings locally. - * @see #setMappingLocations - * @see org.hibernate.cfg.Configuration#addResource - */ - public void setMappingResources(String[] mappingResources) { - this.mappingResources = mappingResources; - } - public String[] getMappingResources() { - return mappingResources; - } - - /** - * Set locations of Hibernate mapping files, for example as classpath - * resource "classpath:example.hbm.xml". Supports any resource location - * via Spring's resource abstraction, for example relative paths like - * "WEB-INF/mappings/example.hbm.xml" when running in an application context. - *

    Can be used to add to mappings from a Hibernate XML config file, - * or to specify all mappings locally. - * @see org.hibernate.cfg.Configuration#addInputStream - */ - public void setMappingLocations(Resource[] mappingLocations) { - this.mappingLocations = mappingLocations; - } - public Resource[] getMappingLocations() { - return mappingLocations; - } - - /** - * Set locations of cacheable Hibernate mapping files, for example as web app - * resource "/WEB-INF/mapping/example.hbm.xml". Supports any resource location - * via Spring's resource abstraction, as long as the resource can be resolved - * in the file system. - *

    Can be used to add to mappings from a Hibernate XML config file, - * or to specify all mappings locally. - * @see org.hibernate.cfg.Configuration#addCacheableFile(java.io.File) - */ - public void setCacheableMappingLocations(Resource[] cacheableMappingLocations) { - this.cacheableMappingLocations = cacheableMappingLocations; - } - public Resource[] getCacheableMappingLocations() { - return cacheableMappingLocations; - } - - /** - * Set locations of jar files that contain Hibernate mapping resources, - * like "WEB-INF/lib/example.hbm.jar". - *

    Can be used to add to mappings from a Hibernate XML config file, - * or to specify all mappings locally. - * @see org.hibernate.cfg.Configuration#addJar(java.io.File) - */ - public void setMappingJarLocations(Resource[] mappingJarLocations) { - this.mappingJarLocations = mappingJarLocations; - } - public Resource[] getMappingJarLocations() { - return mappingJarLocations; - } - - /** - * Set locations of directories that contain Hibernate mapping resources, - * like "WEB-INF/mappings". - *

    Can be used to add to mappings from a Hibernate XML config file, - * or to specify all mappings locally. - * @see org.hibernate.cfg.Configuration#addDirectory(java.io.File) - */ - public void setMappingDirectoryLocations(Resource[] mappingDirectoryLocations) { - this.mappingDirectoryLocations = mappingDirectoryLocations; - } - public Resource[] getMappingDirectoryLocations() { - return mappingDirectoryLocations; - } - - /** - * Set a Hibernate entity interceptor that allows to inspect and change - * property values before writing to and reading from the database. - * Will get applied to any new Session created by this factory. - * @see org.hibernate.cfg.Configuration#setInterceptor - */ - public void setEntityInterceptor(Interceptor entityInterceptor) { - this.entityInterceptor = entityInterceptor; - } - public Interceptor getEntityInterceptor() { - return entityInterceptor; - } - - /** - * Set a Hibernate NamingStrategy for the SessionFactory, determining the - * physical column and table names given the info in the mapping document. - * @see org.hibernate.cfg.Configuration#setNamingStrategy - */ - public void setNamingStrategy(NamingStrategy namingStrategy) { - this.namingStrategy = namingStrategy; - } - public NamingStrategy getNamingStrategy() { - return namingStrategy; - } - - /** - * Set Hibernate properties, such as "hibernate.dialect". - *

    Note: Do not specify a transaction provider here when using - * Spring-driven transactions. It is also advisable to omit connection - * provider settings and use a Spring-set DataSource instead. - * @see #setDataSource - */ - public void setHibernateProperties(Properties hibernateProperties) { - this.hibernateProperties = hibernateProperties; - } - - /** - * Return the Hibernate properties, if any. Mainly available for - * configuration through property paths that specify individual keys. - */ - public Properties getHibernateProperties() { - if (hibernateProperties == null) { - hibernateProperties = new Properties(); - } - return hibernateProperties; - } - - /** - * Specify annotated entity classes to register with this Hibernate SessionFactory. - * @see org.hibernate.cfg.Configuration#addAnnotatedClass(Class) - */ - public void setAnnotatedClasses(Class[] annotatedClasses) { - this.annotatedClasses = annotatedClasses; - } - public Class[] getAnnotatedClasses() { - return annotatedClasses; - } - - /** - * Specify the names of annotated packages, for which package-level - * annotation metadata will be read. - * @see org.hibernate.cfg.Configuration#addPackage(String) - */ - public void setAnnotatedPackages(String[] annotatedPackages) { - this.annotatedPackages = annotatedPackages; - } - public String[] getAnnotatedPackages() { - return annotatedPackages; - } - - /** - * Specify packages to search for autodetection of your entity classes in the - * classpath. This is analogous to Spring's component-scan feature - * ({@link org.springframework.context.annotation.ClassPathBeanDefinitionScanner}). - */ - public void setPackagesToScan(String... packagesToScan) { - this.packagesToScan = packagesToScan; - } - public String[] getPackagesToScan() { - return packagesToScan; - } - - public void setResourceLoader(ResourceLoader resourceLoader) { - resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader); - } - - /** - * @param proxyIfReloadEnabled Sets whether a proxy should be created if reload is enabled - */ - public void setProxyIfReloadEnabled(boolean proxyIfReloadEnabled) { - this.proxyIfReloadEnabled = proxyIfReloadEnabled; - } - public boolean isProxyIfReloadEnabled() { - return proxyIfReloadEnabled; - } - - /** - * Sets class to be used for the Hibernate CurrentSessionContext. - * - * @param currentSessionContextClass An implementation of the CurrentSessionContext interface - */ - public void setCurrentSessionContextClass(Class currentSessionContextClass) { - this.currentSessionContextClass = currentSessionContextClass; - } - public Class getCurrentSessionContextClass() { - return currentSessionContextClass; - } - - /** - * Sets the class to be used for Hibernate Configuration. - * @param configClass A subclass of the Hibernate Configuration class - */ - public void setConfigClass(Class configClass) { - this.configClass = configClass; - } - public Class getConfigClass() { - return configClass; - } - - /** - * @param grailsApplication The grailsApplication to set. - */ - public void setGrailsApplication(GrailsApplication grailsApplication) { - this.grailsApplication = grailsApplication; - } - public GrailsApplication getGrailsApplication() { - return grailsApplication; - } - - public void setHibernateEventListeners(final HibernateEventListeners listeners) { - hibernateEventListeners = listeners; - } - public HibernateEventListeners getHibernateEventListeners() { - return hibernateEventListeners; - } - - public void setSessionFactoryBeanName(String name) { - sessionFactoryBeanName = name; - } - public String getSessionFactoryBeanName() { - return sessionFactoryBeanName; - } - - public void setDataSourceName(String name) { - dataSourceName = name; - } - public String getDataSourceName() { - return dataSourceName; - } - - /** - * Specify the Hibernate event listeners to register, with listener types - * as keys and listener objects as values. Instead of a single listener object, - * you can also pass in a list or set of listeners objects as value. - *

    See the Hibernate documentation for further details on listener types - * and associated listener interfaces. - * @param eventListeners Map with listener type Strings as keys and - * listener objects as values - * @see org.hibernate.cfg.Configuration#setListener(String, Object) - */ - public void setEventListeners(Map eventListeners) { - this.eventListeners = eventListeners; - } - public Map getEventListeners() { - return eventListeners; - } - - public void afterPropertiesSet() throws Exception { - Thread thread = Thread.currentThread(); - ClassLoader cl = thread.getContextClassLoader(); - try { - thread.setContextClassLoader(classLoader); - buildSessionFactory(); - } - finally { - thread.setContextClassLoader(cl); - } - } - - protected void buildSessionFactory() throws Exception { - - configuration = newConfiguration(); - - if (configLocations != null) { - for (Resource resource : configLocations) { - // Load Hibernate configuration from given location. - configuration.configure(resource.getURL()); - } - } - - if (mappingResources != null) { - // Register given Hibernate mapping definitions, contained in resource files. - for (String mapping : mappingResources) { - Resource mr = new ClassPathResource(mapping.trim(), resourcePatternResolver.getClassLoader()); - configuration.addInputStream(mr.getInputStream()); - } - } - - if (mappingLocations != null) { - // Register given Hibernate mapping definitions, contained in resource files. - for (Resource resource : mappingLocations) { - configuration.addInputStream(resource.getInputStream()); - } - } - - if (cacheableMappingLocations != null) { - // Register given cacheable Hibernate mapping definitions, read from the file system. - for (Resource resource : cacheableMappingLocations) { - configuration.addCacheableFile(resource.getFile()); - } - } - - if (mappingJarLocations != null) { - // Register given Hibernate mapping definitions, contained in jar files. - for (Resource resource : mappingJarLocations) { - configuration.addJar(resource.getFile()); - } - } - - if (mappingDirectoryLocations != null) { - // Register all Hibernate mapping definitions in the given directories. - for (Resource resource : mappingDirectoryLocations) { - File file = resource.getFile(); - if (!file.isDirectory()) { - throw new IllegalArgumentException("Mapping directory location [" + resource + "] does not denote a directory"); - } - configuration.addDirectory(file); - } - } - - if (entityInterceptor != null) { - configuration.setInterceptor(entityInterceptor); - } - - if (namingStrategy != null) { - configuration.setNamingStrategy(namingStrategy); - } - - if (hibernateProperties != null) { - configuration.addProperties(hibernateProperties); - } - - if (annotatedClasses != null) { - configuration.addAnnotatedClasses(annotatedClasses); - } - - if (annotatedPackages != null) { - configuration.addPackages(annotatedPackages); - } - - if (packagesToScan != null) { - configuration.scanPackages(packagesToScan); - } - - if (eventListeners != null) { - configuration.setEventListeners(eventListeners); - } - - sessionFactory = doBuildSessionFactory(); - - buildSessionFactoryProxy(); - } - - protected SessionFactory doBuildSessionFactory() { - return configuration.buildSessionFactory(); - } - - protected void buildSessionFactoryProxy() { - try { - if (!grails.util.Environment.getCurrent().isReloadEnabled() || !proxyIfReloadEnabled) { - return; - } - - // if reloading is enabled in this environment then we need to use a SessionFactoryProxy instance - SessionFactoryProxy sfp = new SessionFactoryProxy(); - String suffix = dataSourceName.equals(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE) ? "" : '_' + dataSourceName; - SessionFactoryHolder sessionFactoryHolder = applicationContext.getBean( - SessionFactoryHolder.BEAN_ID + suffix, SessionFactoryHolder.class); - sessionFactoryHolder.setSessionFactory(sessionFactory); - sfp.setApplicationContext(applicationContext); - sfp.setCurrentSessionContextClass(currentSessionContextClass); - sfp.setTargetBean(SessionFactoryHolder.BEAN_ID + suffix); - sfp.afterPropertiesSet(); - sessionFactory = sfp; - } - catch (HibernateException e) { - Throwable cause = e.getCause(); - if (isCacheConfigurationError(cause)) { - log.error("There was an error configuring the Hibernate second level cache: " + getCauseMessage(e)); - log.error("This is normally due to one of two reasons. Either you have incorrectly specified the cache " + - "provider class name in [DataSource.groovy] or you do not have the cache provider on your classpath " + - "(eg. runtime (\"net.sf.ehcache:ehcache:1.6.1\"))"); - if (grails.util.Environment.isDevelopmentMode()) { - System.exit(1); - } - } - throw e; - } - } - - /** - * Return the Hibernate Configuration object used to build the SessionFactory. - * Allows for access to configuration metadata stored there (rarely needed). - * @throws IllegalStateException if the Configuration object has not been initialized yet - */ - public final Configuration getConfiguration() { - Assert.state(configuration != null, "Configuration not initialized yet"); - return configuration; - } - - public SessionFactory getObject() { - return sessionFactory; - } - - public Class getObjectType() { - return sessionFactory == null ? SessionFactory.class : sessionFactory.getClass(); - } - - public boolean isSingleton() { - return true; - } - - public void destroy() { - if (grailsApplication.isWarDeployed()) { - MetaClassRegistry registry = GroovySystem.getMetaClassRegistry(); - Map classMetaData = sessionFactory.getAllClassMetadata(); - for (Object o : classMetaData.values()) { - registry.removeMetaClass(((ClassMetadata)o).getMappedClass()); - } - } - - try { - sessionFactory.close(); - } - catch (HibernateException e) { - if (e.getCause() instanceof NameNotFoundException) { - log.debug(e.getCause().getMessage(), e); - } - else { - throw e; - } - } - } - - protected GrailsAnnotationConfiguration newConfiguration() throws Exception { - if (configClass == null) { - configClass = GrailsAnnotationConfiguration.class; - } - GrailsAnnotationConfiguration config = (GrailsAnnotationConfiguration) BeanUtils.instantiateClass(configClass); - config.setGrailsApplication(grailsApplication); - config.setSessionFactoryBeanName(sessionFactoryBeanName); - config.setDataSourceName(dataSourceName); - config.setHibernateEventListeners(hibernateEventListeners); - if (currentSessionContextClass != null) { - config.setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS, currentSessionContextClass.getName()); - } - config.afterPropertiesSet(); - - return config; - } - - public void setBeanClassLoader(ClassLoader beanClassLoader) { - classLoader = beanClassLoader; - } - - protected String getCauseMessage(HibernateException e) { - Throwable cause = e.getCause(); - if (cause instanceof InvocationTargetException) { - cause = ((InvocationTargetException)cause).getTargetException(); - } - return cause.getMessage(); - } - - protected boolean isCacheConfigurationError(Throwable cause) { - if (cause instanceof InvocationTargetException) { - cause = ((InvocationTargetException)cause).getTargetException(); - } - return cause != null && (cause instanceof CacheException); - } - - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventListenerIntegrator.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventListenerIntegrator.java deleted file mode 100644 index 000878eb8..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventListenerIntegrator.java +++ /dev/null @@ -1,140 +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; - -import grails.util.CollectionUtils; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor; -import org.hibernate.cfg.Configuration; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.event.service.spi.EventListenerGroup; -import org.hibernate.event.service.spi.EventListenerRegistry; -import org.hibernate.event.spi.EventType; -import org.hibernate.integrator.spi.Integrator; -import org.hibernate.metamodel.source.MetadataImplementor; -import org.hibernate.service.spi.SessionFactoryServiceRegistry; - -public class EventListenerIntegrator implements Integrator { - - protected HibernateEventListeners hibernateEventListeners; - protected Map eventListeners; - - public EventListenerIntegrator(HibernateEventListeners hibernateEventListeners, Map eventListeners) { - this.hibernateEventListeners = hibernateEventListeners; - this.eventListeners = eventListeners; - } - - @SuppressWarnings("unchecked") - protected static final List> TYPES = CollectionUtils.newList( - EventType.AUTO_FLUSH, - EventType.MERGE, - EventType.PERSIST, - EventType.PERSIST_ONFLUSH, - EventType.DELETE, - EventType.DIRTY_CHECK, - EventType.EVICT, - EventType.FLUSH, - EventType.FLUSH_ENTITY, - EventType.LOAD, - EventType.INIT_COLLECTION, - EventType.LOCK, - EventType.REFRESH, - EventType.REPLICATE, - EventType.SAVE_UPDATE, - EventType.SAVE, - EventType.UPDATE, - EventType.PRE_LOAD, - EventType.PRE_UPDATE, - EventType.PRE_DELETE, - EventType.PRE_INSERT, - EventType.PRE_COLLECTION_RECREATE, - EventType.PRE_COLLECTION_REMOVE, - EventType.PRE_COLLECTION_UPDATE, - EventType.POST_LOAD, - EventType.POST_UPDATE, - EventType.POST_DELETE, - EventType.POST_INSERT, - EventType.POST_COMMIT_UPDATE, - EventType.POST_COMMIT_DELETE, - EventType.POST_COMMIT_INSERT, - EventType.POST_COLLECTION_RECREATE, - EventType.POST_COLLECTION_REMOVE, - EventType.POST_COLLECTION_UPDATE); - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void integrate(Configuration config, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { - - EventListenerRegistry listenerRegistry = serviceRegistry.getService(EventListenerRegistry.class); - - if (eventListeners != null) { - for (Map.Entry entry : eventListeners.entrySet()) { - EventType type = EventType.resolveEventTypeByName(entry.getKey()); - Object listenerObject = entry.getValue(); - if (listenerObject instanceof Collection) { - appendListeners(listenerRegistry, type, (Collection)listenerObject); - } - else if (listenerObject != null) { - appendListeners(listenerRegistry, type, Collections.singleton(listenerObject)); - } - } - } - - if (hibernateEventListeners != null && hibernateEventListeners.getListenerMap() != null) { - Map listenerMap = hibernateEventListeners.getListenerMap(); - for (EventType type : TYPES) { - appendListeners(listenerRegistry, type, listenerMap); - } - } - - // register workaround for GRAILS-8988 (do nullability checks for inserts in last PreInsertEventListener) - ClosureEventTriggeringInterceptor.addNullabilityCheckerPreInsertEventListener(listenerRegistry); - } - - protected void appendListeners(EventListenerRegistry listenerRegistry, - EventType eventType, Collection listeners) { - - EventListenerGroup group = listenerRegistry.getEventListenerGroup(eventType); - for (T listener : listeners) { - if (listener != null) { - group.appendListener(listener); - } - } - } - - @SuppressWarnings("unchecked") - protected void appendListeners(final EventListenerRegistry listenerRegistry, - final EventType eventType, final Map listeners) { - - Object listener = listeners.get(eventType.eventName()); - if (listener != null) { - listenerRegistry.appendListeners(eventType, (T)listener); - } - } - - public void integrate(MetadataImplementor metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { - // nothing to do - } - - public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { - // nothing to do - } -} 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 deleted file mode 100644 index a49329d20..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/EventTriggeringInterceptor.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 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.codehaus.groovy.grails.orm.hibernate; - -import groovy.lang.GroovySystem; -import groovy.util.ConfigObject; - -import java.util.List; -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.datastore.mapping.engine.event.AbstractPersistenceEvent; -import org.grails.datastore.mapping.engine.event.ValidationEvent; -import org.hibernate.HibernateException; -import org.hibernate.event.spi.PostDeleteEvent; -import org.hibernate.event.spi.PostInsertEvent; -import org.hibernate.event.spi.PostLoadEvent; -import org.hibernate.event.spi.PostUpdateEvent; -import org.hibernate.event.spi.PreDeleteEvent; -import org.hibernate.event.spi.PreInsertEvent; -import org.hibernate.event.spi.PreLoadEvent; -import org.hibernate.event.spi.PreUpdateEvent; -import org.hibernate.event.spi.SaveOrUpdateEvent; -import org.springframework.context.ApplicationEvent; - -/** - *

    Invokes closure events on domain entities such as beforeInsert, beforeUpdate and beforeDelete. - * - * @author Graeme Rocher - * @author Lari Hotari - * @author Burt Beckwith - * @since 2.0 - */ -public class EventTriggeringInterceptor extends AbstractEventTriggeringInterceptor { - - protected transient ConcurrentMap>, ClosureEventListener> eventListeners = - new ConcurrentHashMap>, ClosureEventListener>(); - - protected final GrailsDomainBinder domainBinder = new GrailsDomainBinder(); - - public EventTriggeringInterceptor(HibernateDatastore datastore, ConfigObject co) { - super(datastore); - - Object failOnErrorConfig = co.flatten().get("grails.gorm.failOnError"); - if (failOnErrorConfig instanceof List) { - failOnError = true; - failOnErrorPackages = (List)failOnErrorConfig; - } - else { - failOnError = DefaultTypeTransformation.castToBoolean(failOnErrorConfig); - } - } - - @Override - protected void onPersistenceEvent(final AbstractPersistenceEvent event) { - switch (event.getEventType()) { - case PreInsert: - if (onPreInsert((PreInsertEvent)event.getNativeEvent())) { - event.cancel(); - } - break; - case PostInsert: - onPostInsert((PostInsertEvent)event.getNativeEvent()); - break; - case PreUpdate: - if (onPreUpdate((PreUpdateEvent)event.getNativeEvent())) { - event.cancel(); - } - break; - case PostUpdate: - onPostUpdate((PostUpdateEvent)event.getNativeEvent()); - break; - case PreDelete: - if (onPreDelete((PreDeleteEvent)event.getNativeEvent())) { - event.cancel(); - } - break; - case PostDelete: - onPostDelete((PostDeleteEvent)event.getNativeEvent()); - break; - case PreLoad: - onPreLoad((PreLoadEvent)event.getNativeEvent()); - break; - case PostLoad: - onPostLoad((PostLoadEvent)event.getNativeEvent()); - break; - case SaveOrUpdate: - onSaveOrUpdate((SaveOrUpdateEvent)event.getNativeEvent()); - break; - case Validation: - onValidate((ValidationEvent)event); - break; - default: - throw new IllegalStateException("Unexpected EventType: " + event.getEventType()); - } - } - - public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException { - ClosureEventListener eventListener = findEventListener(event.getObject()); - if (eventListener != null) { - eventListener.onSaveOrUpdate(event); - } - } - - public void onPreLoad(PreLoadEvent event) { - Object entity = event.getEntity(); - GrailsHibernateUtil.ensureCorrectGroovyMetaClass(entity, entity.getClass()); - ClosureEventListener eventListener = findEventListener(entity); - if (eventListener != null) { - eventListener.onPreLoad(event); - } - } - - public void onPostLoad(PostLoadEvent event) { - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - eventListener.onPostLoad(event); - } - } - - public void onPostInsert(PostInsertEvent event) { - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - eventListener.onPostInsert(event); - } - } - - public boolean onPreInsert(PreInsertEvent event) { - boolean evict = false; - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - evict = eventListener.onPreInsert(event); - } - return evict; - } - - public boolean onPreUpdate(PreUpdateEvent event) { - boolean evict = false; - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - evict = eventListener.onPreUpdate(event); - } - return evict; - } - - public void onPostUpdate(PostUpdateEvent event) { - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - eventListener.onPostUpdate(event); - } - } - - public boolean onPreDelete(PreDeleteEvent event) { - boolean evict = false; - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - evict = eventListener.onPreDelete(event); - } - return evict; - } - - public void onPostDelete(PostDeleteEvent event) { - ClosureEventListener eventListener = findEventListener(event.getEntity()); - if (eventListener != null) { - eventListener.onPostDelete(event); - } - } - - public void onValidate(ValidationEvent event) { - ClosureEventListener eventListener = findEventListener(event.getEntityObject()); - if (eventListener != null) { - eventListener.onValidate(event); - } - } - - protected ClosureEventListener findEventListener(Object entity) { - if (entity == null) return null; - Class clazz = entity.getClass(); - - SoftKey> key = new SoftKey>(clazz); - ClosureEventListener eventListener = eventListeners.get(key); - if (eventListener != null) { - return eventListener; - } - - Boolean shouldTrigger = cachedShouldTrigger.get(key); - if (shouldTrigger == null || shouldTrigger) { - synchronized(clazz) { - eventListener = eventListeners.get(key); - if (eventListener == null) { - shouldTrigger = (GroovySystem.getMetaClassRegistry().getMetaClass(entity.getClass()) != null && - (DomainClassArtefactHandler.isDomainClass(clazz) || AnnotationDomainClassArtefactHandler.isJPADomainClass(clazz)) && - isDefinedByCurrentDataStore(entity, domainBinder)); - if (shouldTrigger) { - eventListener = new ClosureEventListener(clazz, failOnError, failOnErrorPackages); - ClosureEventListener previous = eventListeners.putIfAbsent(key, eventListener); - if (previous != null) { - eventListener = previous; - } - } - cachedShouldTrigger.put(key, shouldTrigger); - } - } - } - return eventListener; - } - - /** - * {@inheritDoc} - * @see org.springframework.context.event.SmartApplicationListener#supportsEventType(java.lang.Class) - */ - public boolean supportsEventType(Class eventType) { - return AbstractPersistenceEvent.class.isAssignableFrom(eventType); - } - - protected List getDatasourceNames(GrailsDomainClass dc) { - return GrailsHibernateUtil.getDatasourceNames(dc); - } -} 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 deleted file mode 100644 index c6bfb47b6..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateDomainClass.java +++ /dev/null @@ -1,67 +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; - -import java.util.Collection; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.hibernate.MappingException; -import org.hibernate.SessionFactory; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.metadata.ClassMetadata; -import org.hibernate.type.AssociationType; -import org.hibernate.type.Type; - -/** - * An implementation of the GrailsDomainClass interface that allows Classes - * mapped in Hibernate to integrate with Grails' validation, dynamic methods - * etc. seamlessly. - * - * @author Graeme Rocher - * @since 0.1 - */ -@SuppressWarnings("unchecked") -public class GrailsHibernateDomainClass extends AbstractGrailsHibernateDomainClass { - - /** - * Contructor to be used by all child classes to create a new instance - * and get the name right. - * - * @param clazz the Grails class - * @param sessionFactory The Hibernate SessionFactory instance - * @param sessionFactoryName - * @param application - * @param metaData The ClassMetaData for this class retrieved from the SF - */ - public GrailsHibernateDomainClass(Class clazz, SessionFactory sessionFactory, String sessionFactoryName, - GrailsApplication application, ClassMetadata metaData) { - super(clazz, sessionFactory, sessionFactoryName, application, metaData); - } - - protected void setRelatedClassType(GrailsHibernateDomainClassProperty prop, AssociationType assType, Type hibernateType) { - try { - String associatedEntity = assType.getAssociatedEntityName((SessionFactoryImplementor) getSessionFactory()); - ClassMetadata associatedMetaData = getSessionFactory().getClassMetadata(associatedEntity); - prop.setRelatedClassType(associatedMetaData.getMappedClass()); - } - catch (MappingException me) { - // other side must be a value object - if (hibernateType.isCollectionType()) { - prop.setRelatedClassType(Collection.class); - } - } - } -} 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 deleted file mode 100644 index 8baa57d7e..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTemplate.java +++ /dev/null @@ -1,645 +0,0 @@ -/* - * Copyright 2011-2013 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.codehaus.groovy.grails.orm.hibernate; - -import java.io.Serializable; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import javax.sql.DataSource; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.hibernate.Criteria; -import org.hibernate.FlushMode; -import org.hibernate.HibernateException; -import org.hibernate.JDBCException; -import org.hibernate.LockMode; -import org.hibernate.LockOptions; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.event.spi.EventSource; -import org.hibernate.exception.GenericJDBCException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.dao.DataAccessException; -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator; -import org.springframework.jdbc.support.SQLExceptionTranslator; -import org.springframework.orm.hibernate4.SessionFactoryUtils; -import org.springframework.orm.hibernate4.SessionHolder; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.util.Assert; - -public class GrailsHibernateTemplate implements IHibernateTemplate { - - protected final Logger logger = LoggerFactory.getLogger(getClass()); - - private boolean osivReadOnly; - protected boolean exposeNativeSession = true; - protected boolean cacheQueries = false; - -protected boolean allowCreate = true; -protected boolean checkWriteOperations = true; - - protected SessionFactory sessionFactory; - protected SQLExceptionTranslator jdbcExceptionTranslator; - protected int flushMode = FLUSH_AUTO; - - public static interface HibernateCallback { - T doInHibernate(Session session) throws HibernateException, SQLException; - } - - protected GrailsHibernateTemplate() { - // for testing - } - - public GrailsHibernateTemplate(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - - public GrailsHibernateTemplate(SessionFactory sessionFactory, GrailsApplication application) { - Assert.notNull(sessionFactory, "Property 'sessionFactory' is required"); - this.sessionFactory = sessionFactory; - - DataSource ds = application.getMainContext().getBean("dataSource", DataSource.class); - jdbcExceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(ds); - - cacheQueries = GrailsHibernateUtil.isCacheQueriesByDefault(application); - this.osivReadOnly = GrailsHibernateUtil.isOsivReadonly(application); - } - - public SessionFactory getSessionFactory() { - return sessionFactory; - } - - public void applySettings(Query query) { - if (exposeNativeSession) { - prepareQuery(query); - } - } - - public void applySettings(Criteria criteria) { - if (exposeNativeSession) { - prepareCriteria(criteria); - } - } - - public void setCacheQueries(boolean cacheQueries) { - this.cacheQueries = cacheQueries; - } - public boolean isCacheQueries() { - return cacheQueries; - } - - public T execute(HibernateCallback action) throws DataAccessException { - return doExecute(action, false); - } - - public List executeFind(HibernateCallback action) throws DataAccessException { - Object result = doExecute(action, false); - if (result != null && !(result instanceof List)) { - throw new InvalidDataAccessApiUsageException("Result object returned from HibernateCallback isn't a List: [" + result + "]"); - } - return (List)result; - } - - protected boolean isCurrentTransactionReadOnly() { - if (!TransactionSynchronizationManager.hasResource(sessionFactory)) { - return false; - } - - if (TransactionSynchronizationManager.isActualTransactionActive()) { - return TransactionSynchronizationManager.isCurrentTransactionReadOnly(); - } - return osivReadOnly; - } - - public boolean isOsivReadOnly() { - return osivReadOnly; - } - - public void setOsivReadOnly(boolean osivReadOnly) { - this.osivReadOnly = osivReadOnly; - } - - /** - * Execute the action specified by the given action object within a Session. - * - * @param action callback object that specifies the Hibernate action - * @param enforceNativeSession whether to enforce exposure of the native Hibernate Session to callback code - * @return a result object returned by the action, or null - * @throws org.springframework.dao.DataAccessException in case of Hibernate errors - */ - protected T doExecute(HibernateCallback action, boolean enforceNativeSession) throws DataAccessException { - - Assert.notNull(action, "Callback object must not be null"); - - Session session = getSession(); - boolean existingTransaction = isSessionTransactional(session); - if (existingTransaction) { - logger.debug("Found thread-bound Session for HibernateTemplate"); - } - - FlushMode previousFlushMode = null; - try { - previousFlushMode = applyFlushMode(session, existingTransaction); - if(isCurrentTransactionReadOnly()) { - session.setDefaultReadOnly(true); - } - Session sessionToExpose = (enforceNativeSession || exposeNativeSession ? session : createSessionProxy(session)); - T result = action.doInHibernate(sessionToExpose); - flushIfNecessary(session, existingTransaction); - return result; - } - catch (HibernateException ex) { - throw convertHibernateAccessException(ex); - } - catch (SQLException ex) { - throw jdbcExceptionTranslator.translate("Hibernate-related JDBC operation", null, ex); - } - catch (RuntimeException ex) { - // Callback code threw application exception... - throw ex; - } - finally { - if (existingTransaction) { - logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate"); - if (previousFlushMode != null) { - session.setFlushMode(previousFlushMode); - } - } - else { - SessionFactoryUtils.closeSession(session); - } - } - } - - protected boolean isSessionTransactional(Session session) { - SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); - return sessionHolder != null && sessionHolder.getSession() == session; - } - - protected Session getSession() { - try { - return sessionFactory.getCurrentSession(); - } - catch (HibernateException ex) { - throw new DataAccessResourceFailureException("Could not obtain current Hibernate Session", ex); - } - } - - /** - * Create a close-suppressing proxy for the given Hibernate Session. The - * proxy also prepares returned Query and Criteria objects. - * - * @param session the Hibernate Session to create a proxy for - * @return the Session proxy - * @see org.hibernate.Session#close() - * @see #prepareQuery - * @see #prepareCriteria - */ - protected Session createSessionProxy(Session session) { - Class[] sessionIfcs = null; - Class mainIfc = Session.class; - if (session instanceof EventSource) { - sessionIfcs = new Class[] { mainIfc, EventSource.class }; - } - else if (session instanceof SessionImplementor) { - sessionIfcs = new Class[] { mainIfc, SessionImplementor.class }; - } - else { - sessionIfcs = new Class[] { mainIfc }; - } - return (Session) Proxy.newProxyInstance(session.getClass().getClassLoader(), sessionIfcs, - new CloseSuppressingInvocationHandler(session)); - } - - public T get(final Class entityClass, final Serializable id) throws DataAccessException { - return doExecute(new HibernateCallback() { - @SuppressWarnings("unchecked") - public T doInHibernate(Session session) throws HibernateException { - return (T) session.get(entityClass, id); - } - }, true); - } - - public T get(final Class entityClass, final Serializable id, final LockMode mode) { - return lock(entityClass, id, mode); - } - - public void delete(final Object entity) throws DataAccessException { - doExecute(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { - session.delete(entity); - return null; - } - }, true); - } - - public void flush(final Object entity) throws DataAccessException { - doExecute(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { - session.flush(); - return null; - } - }, true); - } - - public T load(final Class entityClass, final Serializable id) throws DataAccessException { - return doExecute(new HibernateCallback() { - @SuppressWarnings("unchecked") - public T doInHibernate(Session session) throws HibernateException { - return (T) session.load(entityClass, id); - } - }, true); - } - - public T lock(final Class entityClass, final Serializable id, final LockMode lockMode) throws DataAccessException { - return doExecute(new HibernateCallback() { - @SuppressWarnings("unchecked") - public T doInHibernate(Session session) throws HibernateException { - return (T) session.get(entityClass, id, new LockOptions(lockMode)); - } - }, true); - } - - public List loadAll(final Class entityClass) throws DataAccessException { - return doExecute(new HibernateCallback>() { - @SuppressWarnings("unchecked") - public List doInHibernate(Session session) throws HibernateException { - Criteria criteria = session.createCriteria(entityClass); - criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - prepareCriteria(criteria); - return criteria.list(); - } - }, true); - } - - public boolean contains(final Object entity) throws DataAccessException { - return doExecute(new HibernateCallback() { - public Boolean doInHibernate(Session session) { - return session.contains(entity); - } - }, true); - } - - public void evict(final Object entity) throws DataAccessException { - doExecute(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { - session.evict(entity); - return null; - } - }, true); - } - - public void lock(final Object entity, final LockMode lockMode) throws DataAccessException { - doExecute(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { - session.buildLockRequest(new LockOptions(lockMode)).lock(entity);//LockMode.PESSIMISTIC_WRITE - return null; - } - }, true); - } - - public void refresh(final Object entity) throws DataAccessException { - refresh(entity, null); - } - - public void refresh(final Object entity, final LockMode lockMode) throws DataAccessException { - doExecute(new HibernateCallback() { - public Object doInHibernate(Session session) throws HibernateException { - if (lockMode == null) { - session.refresh(entity); - } - else { - session.refresh(entity, new LockOptions(lockMode)); - } - return null; - } - }, true); - } - - public void setExposeNativeSession(boolean exposeNativeSession) { - this.exposeNativeSession = exposeNativeSession; - } - public boolean isExposeNativeSession() { - return exposeNativeSession; - } - - /** - * Prepare the given Query object, applying cache settings and/or a - * transaction timeout. - * - * @param query the Query object to prepare - * @see SessionFactoryUtils#applyTransactionTimeout - */ - protected void prepareQuery(Query query) { - if (cacheQueries) { - query.setCacheable(true); - } - if(isCurrentTransactionReadOnly()) { - query.setReadOnly(true); - } - SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); - if (sessionHolder != null && sessionHolder.hasTimeout()) { - query.setTimeout(sessionHolder.getTimeToLiveInSeconds()); - } - } - - /** - * Prepare the given Criteria object, applying cache settings and/or a - * transaction timeout. - * - * @param criteria the Criteria object to prepare - * @see SessionFactoryUtils#applyTransactionTimeout - */ - protected void prepareCriteria(Criteria criteria) { - if (cacheQueries) { - criteria.setCacheable(true); - } - if(isCurrentTransactionReadOnly()) { - criteria.setReadOnly(true); - } - SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); - if (sessionHolder != null && sessionHolder.hasTimeout()) { - criteria.setTimeout(sessionHolder.getTimeToLiveInSeconds()); - } - } - - /** - * Invocation handler that suppresses close calls on Hibernate Sessions. - * Also prepares returned Query and Criteria objects. - * - * @see org.hibernate.Session#close - */ - protected class CloseSuppressingInvocationHandler implements InvocationHandler { - - protected final Session target; - - protected CloseSuppressingInvocationHandler(Session target) { - this.target = target; - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - // Invocation on Session interface coming in... - - if (method.getName().equals("equals")) { - // Only consider equal when proxies are identical. - return (proxy == args[0]); - } - if (method.getName().equals("hashCode")) { - // Use hashCode of Session proxy. - return System.identityHashCode(proxy); - } - if (method.getName().equals("close")) { - // Handle close method: suppress, not valid. - return null; - } - - // Invoke method on target Session. - try { - Object retVal = method.invoke(target, args); - - // If return value is a Query or Criteria, apply transaction timeout. - // Applies to createQuery, getNamedQuery, createCriteria. - if (retVal instanceof Query) { - prepareQuery(((Query) retVal)); - } - if (retVal instanceof Criteria) { - prepareCriteria(((Criteria) retVal)); - } - - return retVal; - } - catch (InvocationTargetException ex) { - throw ex.getTargetException(); - } - } - } - - /** - * Never flush is a good strategy for read-only units of work. - * Hibernate will not track and look for changes in this case, - * avoiding any overhead of modification detection. - *

    In case of an existing Session, FLUSH_NEVER will turn the flush mode - * to NEVER for the scope of the current operation, resetting the previous - * flush mode afterwards. - * @see #setFlushMode - */ - public static final int FLUSH_NEVER = 0; - - /** - * Automatic flushing is the default mode for a Hibernate Session. - * A session will get flushed on transaction commit, and on certain find - * operations that might involve already modified instances, but not - * after each unit of work like with eager flushing. - *

    In case of an existing Session, FLUSH_AUTO will participate in the - * existing flush mode, not modifying it for the current operation. - * This in particular means that this setting will not modify an existing - * flush mode NEVER, in contrast to FLUSH_EAGER. - * @see #setFlushMode - */ - public static final int FLUSH_AUTO = 1; - - /** - * Eager flushing leads to immediate synchronization with the database, - * even if in a transaction. This causes inconsistencies to show up and throw - * a respective exception immediately, and JDBC access code that participates - * in the same transaction will see the changes as the database is already - * aware of them then. But the drawbacks are: - *

      - *
    • additional communication roundtrips with the database, instead of a - * single batch at transaction commit; - *
    • the fact that an actual database rollback is needed if the Hibernate - * transaction rolls back (due to already submitted SQL statements). - *
    - *

    In case of an existing Session, FLUSH_EAGER will turn the flush mode - * to AUTO for the scope of the current operation and issue a flush at the - * end, resetting the previous flush mode afterwards. - * @see #setFlushMode - */ - public static final int FLUSH_EAGER = 2; - - /** - * Flushing at commit only is intended for units of work where no - * intermediate flushing is desired, not even for find operations - * that might involve already modified instances. - *

    In case of an existing Session, FLUSH_COMMIT will turn the flush mode - * to COMMIT for the scope of the current operation, resetting the previous - * flush mode afterwards. The only exception is an existing flush mode - * NEVER, which will not be modified through this setting. - * @see #setFlushMode - */ - public static final int FLUSH_COMMIT = 3; - - /** - * Flushing before every query statement is rarely necessary. - * It is only available for special needs. - *

    In case of an existing Session, FLUSH_ALWAYS will turn the flush mode - * to ALWAYS for the scope of the current operation, resetting the previous - * flush mode afterwards. - * @see #setFlushMode - */ - public static final int FLUSH_ALWAYS = 4; - - /** - * Set the flush behavior to one of the constants in this class. Default is - * FLUSH_AUTO. - * - * @see #setFlushModeName - * @see #FLUSH_AUTO - */ - public void setFlushMode(int flushMode) { - this.flushMode = flushMode; - } - - /** - * Return if a flush should be forced after executing the callback code. - */ - public int getFlushMode() { - return flushMode; - } - - /** - * Apply the flush mode that's been specified for this accessor to the given Session. - * - * @param session the current Hibernate Session - * @param existingTransaction if executing within an existing transaction - * @return the previous flush mode to restore after the operation, or null if none - * @see #setFlushMode - * @see org.hibernate.Session#setFlushMode - */ - protected FlushMode applyFlushMode(Session session, boolean existingTransaction) { - if (getFlushMode() == FLUSH_NEVER) { - if (existingTransaction) { - FlushMode previousFlushMode = session.getFlushMode(); - if (!previousFlushMode.lessThan(FlushMode.COMMIT)) { - session.setFlushMode(FlushMode.MANUAL); - return previousFlushMode; - } - } - else { - session.setFlushMode(FlushMode.MANUAL); - } - } - else if (getFlushMode() == FLUSH_EAGER) { - if (existingTransaction) { - FlushMode previousFlushMode = session.getFlushMode(); - if (!previousFlushMode.equals(FlushMode.AUTO)) { - session.setFlushMode(FlushMode.AUTO); - return previousFlushMode; - } - } - else { - // rely on default FlushMode.AUTO - } - } - else if (getFlushMode() == FLUSH_COMMIT) { - if (existingTransaction) { - FlushMode previousFlushMode = session.getFlushMode(); - if (previousFlushMode.equals(FlushMode.AUTO) || previousFlushMode.equals(FlushMode.ALWAYS)) { - session.setFlushMode(FlushMode.COMMIT); - return previousFlushMode; - } - } - else { - session.setFlushMode(FlushMode.COMMIT); - } - } - else if (getFlushMode() == FLUSH_ALWAYS) { - if (existingTransaction) { - FlushMode previousFlushMode = session.getFlushMode(); - if (!previousFlushMode.equals(FlushMode.ALWAYS)) { - session.setFlushMode(FlushMode.ALWAYS); - return previousFlushMode; - } - } - else { - session.setFlushMode(FlushMode.ALWAYS); - } - } - return null; - } - - protected void flushIfNecessary(Session session, boolean existingTransaction) throws HibernateException { - if (getFlushMode() == FLUSH_EAGER || (!existingTransaction && getFlushMode() != FLUSH_NEVER)) { - logger.debug("Eagerly flushing Hibernate session"); - session.flush(); - } - } - - protected DataAccessException convertHibernateAccessException(HibernateException ex) { - if (ex instanceof JDBCException) { - return convertJdbcAccessException((JDBCException) ex, jdbcExceptionTranslator); - } - if (GenericJDBCException.class.equals(ex.getClass())) { - return convertJdbcAccessException((GenericJDBCException) ex, jdbcExceptionTranslator); - } - return SessionFactoryUtils.convertHibernateAccessException(ex); - } - - protected DataAccessException convertJdbcAccessException(JDBCException ex, SQLExceptionTranslator translator) { - return translator.translate("Hibernate operation: " + ex.getMessage(), ex.getSQL(), ex.getSQLException()); - } - - public Serializable save(Object o) { - return sessionFactory.getCurrentSession().save(o); - } - - public void flush() { - sessionFactory.getCurrentSession().flush(); - } - - public void clear() { - sessionFactory.getCurrentSession().clear(); - } - - public void deleteAll(final Collection objects) { - execute(new GrailsHibernateTemplate.HibernateCallback() { - public Void doInHibernate(Session session) throws HibernateException { - for (Object entity : getIterableAsCollection(objects)) { - session.delete(entity); - } - return null; - } - }); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - protected Collection getIterableAsCollection(Iterable objects) { - Collection list; - if (objects instanceof Collection) { - list = (Collection)objects; - } - else { - list = new ArrayList(); - for (Object object : objects) { - list.add(object); - } - } - return list; - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy deleted file mode 100644 index 48bc49a08..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2004-2010 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 - -import org.hibernate.FlushMode -import org.springframework.orm.hibernate4.HibernateTransactionManager -import org.springframework.transaction.TransactionDefinition - -/** - * Extends the standard class to always set the flush mode to manual when in a read-only transaction. - * - * @author Burt Beckwith - */ -class GrailsHibernateTransactionManager extends HibernateTransactionManager { - - @Override - protected void doBegin(Object transaction, TransactionDefinition definition) { - super.doBegin transaction, definition - - if (definition.isReadOnly()) { - // transaction is HibernateTransactionManager.HibernateTransactionObject private class instance - transaction.sessionHolder?.session?.with { - // always set to manual; the base class doesn't because the OSIVI has already registered a session - flushMode = FlushMode.MANUAL - // set session to load entities in read-only mode - defaultReadOnly = true - } - } - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsSessionContext.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsSessionContext.java deleted file mode 100644 index 2f2e820e3..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/GrailsSessionContext.java +++ /dev/null @@ -1,284 +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; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; - -import javax.transaction.Status; -import javax.transaction.Transaction; -import javax.transaction.TransactionManager; - -import org.hibernate.FlushMode; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.context.spi.CurrentSessionContext; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.service.jta.platform.spi.JtaPlatform; -import org.hibernate.service.spi.ServiceBinding; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.orm.hibernate4.SessionHolder; -import org.springframework.orm.hibernate4.SpringJtaSessionContext; -import org.springframework.transaction.jta.SpringJtaSynchronizationAdapter; -import org.springframework.transaction.support.TransactionSynchronization; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.util.ReflectionUtils; - -/** - * Based on org.springframework.orm.hibernate4.SpringSessionContext. - * - * @author Juergen Hoeller - * @author Burt Beckwith - */ -public class GrailsSessionContext implements CurrentSessionContext { - - private static final long serialVersionUID = 1; - - protected final Logger log = LoggerFactory.getLogger(getClass()); - - protected final SessionFactoryImplementor sessionFactory; - protected CurrentSessionContext jtaSessionContext; - protected Constructor springFlushSynchronizationConstructor; - protected Constructor springSessionSynchronizationConstructor; - - // TODO make configurable? - protected boolean allowCreate = true; - - /** - * Constructor. - * @param sessionFactory the SessionFactory to provide current Sessions for - */ - public GrailsSessionContext(SessionFactoryImplementor sessionFactory) { - this.sessionFactory = sessionFactory; - lookupConstructors(); - } - - public void initJta() { - JtaPlatform jtaPlatform = sessionFactory.getServiceRegistry().getService(JtaPlatform.class); - TransactionManager transactionManager = jtaPlatform.retrieveTransactionManager(); - jtaSessionContext = transactionManager == null ? null : new SpringJtaSessionContext(sessionFactory); - } - - /** - * Retrieve the Spring-managed Session for the current thread, if any. - */ - public Session currentSession() throws HibernateException { - Object value = TransactionSynchronizationManager.getResource(sessionFactory); - if (value instanceof Session) { - return (Session) value; - } - - if (value instanceof SessionHolder) { - SessionHolder sessionHolder = (SessionHolder) value; - Session session = sessionHolder.getSession(); - if (TransactionSynchronizationManager.isSynchronizationActive() && !sessionHolder.isSynchronizedWithTransaction()) { - TransactionSynchronizationManager.registerSynchronization(createSpringSessionSynchronization(sessionHolder)); - sessionHolder.setSynchronizedWithTransaction(true); - // Switch to FlushMode.AUTO, as we have to assume a thread-bound Session - // with FlushMode.MANUAL, which needs to allow flushing within the transaction. - FlushMode flushMode = session.getFlushMode(); - if (FlushMode.isManualFlushMode(flushMode) && !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { - session.setFlushMode(FlushMode.AUTO); - sessionHolder.setPreviousFlushMode(flushMode); - } - } - return session; - } - - if (jtaSessionContext != null) { - Session session = jtaSessionContext.currentSession(); - if (TransactionSynchronizationManager.isSynchronizationActive()) { - TransactionSynchronizationManager.registerSynchronization(createSpringFlushSynchronization(session)); - } - return session; - } - - if (allowCreate) { - // be consistent with older HibernateTemplate behavior - return createSession(value); - } - - throw new HibernateException("No Session found for current thread"); - } - - private Session createSession(Object resource) { - log.debug("Opening Hibernate Session"); - - SessionHolder sessionHolder = (SessionHolder) resource; - - Session session = sessionFactory.openSession(); - - // Use same Session for further Hibernate actions within the transaction. - // Thread object will get removed by synchronization at transaction completion. - if (TransactionSynchronizationManager.isSynchronizationActive()) { - // We're within a Spring-managed transaction, possibly from JtaTransactionManager. - log.debug("Registering Spring transaction synchronization for new Hibernate Session"); - SessionHolder holderToUse = sessionHolder; - if (holderToUse == null) { - holderToUse = new SessionHolder(session); - } - else { - // it's up to the caller to manage concurrent sessions - // holderToUse.addSession(session); - } - if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { - session.setFlushMode(FlushMode.MANUAL); - } - TransactionSynchronizationManager.registerSynchronization(createSpringSessionSynchronization(sessionHolder)); - holderToUse.setSynchronizedWithTransaction(true); - if (holderToUse != sessionHolder) { - TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse); - } - } - else { - // No Spring transaction management active -> try JTA transaction synchronization. - registerJtaSynchronization(session, sessionHolder); - } - -/* // Check whether we are allowed to return the Session. - if (!allowCreate && !isSessionTransactional(session, sessionFactory)) { - closeSession(session); - throw new IllegalStateException("No Hibernate Session bound to thread, " + - "and configuration does not allow creation of non-transactional one here"); - } -*/ - return session; - } - - protected void registerJtaSynchronization(Session session, SessionHolder sessionHolder) { - - // JTA synchronization is only possible with a javax.transaction.TransactionManager. - // We'll check the Hibernate SessionFactory: If a TransactionManagerLookup is specified - // in Hibernate configuration, it will contain a TransactionManager reference. - TransactionManager jtaTm = getJtaTransactionManager(session); - if (jtaTm == null) { - return; - } - - try { - Transaction jtaTx = jtaTm.getTransaction(); - if (jtaTx == null) { - return; - } - - int jtaStatus = jtaTx.getStatus(); - if (jtaStatus != Status.STATUS_ACTIVE && jtaStatus != Status.STATUS_MARKED_ROLLBACK) { - return; - } - - log.debug("Registering JTA transaction synchronization for new Hibernate Session"); - SessionHolder holderToUse = sessionHolder; - // Register JTA Transaction with existing SessionHolder. - // Create a new SessionHolder if none existed before. - if (holderToUse == null) { - holderToUse = new SessionHolder(session); - } - else { - // it's up to the caller to manage concurrent sessions - // holderToUse.addSession(session); - } - jtaTx.registerSynchronization(new SpringJtaSynchronizationAdapter(createSpringSessionSynchronization(holderToUse), jtaTm)); - holderToUse.setSynchronizedWithTransaction(true); - if (holderToUse != sessionHolder) { - TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse); - } - } - catch (Throwable ex) { - throw new DataAccessResourceFailureException("Could not register synchronization with JTA TransactionManager", ex); - } - } - - protected TransactionManager getJtaTransactionManager(Session session) { - SessionFactoryImplementor sessionFactoryImpl = null; - if (sessionFactory instanceof SessionFactoryImplementor) { - sessionFactoryImpl = ((SessionFactoryImplementor) sessionFactory); - } - else if (session != null) { - SessionFactory internalFactory = session.getSessionFactory(); - if (internalFactory instanceof SessionFactoryImplementor) { - sessionFactoryImpl = (SessionFactoryImplementor) internalFactory; - } - } - - if (sessionFactoryImpl == null) { - return null; - } - - ServiceBinding sb = sessionFactory.getServiceRegistry().locateServiceBinding(JtaPlatform.class); - if (sb == null) { - return null; - } - - return sb.getService().retrieveTransactionManager(); - } - - protected void lookupConstructors() { - springFlushSynchronizationConstructor = lookupConstructor( - "org.springframework.orm.hibernate4.SpringFlushSynchronization", Session.class); - springSessionSynchronizationConstructor = lookupConstructor( - "org.springframework.orm.hibernate4.SpringSessionSynchronization", SessionHolder.class, SessionFactory.class); - } - - protected Constructor lookupConstructor(String className, Class... argTypes) { - try { - Class clazz = ReflectHelper.classForName(className); - Constructor constructor = clazz.getConstructor(argTypes); - constructor.setAccessible(true); - return constructor; - } - catch (ClassNotFoundException e) { - ReflectionUtils.handleReflectionException(e); - } - catch (NoSuchMethodException e) { - ReflectionUtils.handleReflectionException(e); - } - catch (SecurityException e) { - ReflectionUtils.handleReflectionException(e); - } - return null; - } - - protected TransactionSynchronization createSpringFlushSynchronization(Session session) { - return (TransactionSynchronization)create(springFlushSynchronizationConstructor, session); - } - - protected TransactionSynchronization createSpringSessionSynchronization(SessionHolder sessionHolder) { - return (TransactionSynchronization)create(springSessionSynchronizationConstructor, sessionHolder, sessionFactory); - } - - protected Object create(Constructor constructor, Object... args) { - try { - return constructor.newInstance(args); - } - catch (InstantiationException e) { - ReflectionUtils.handleReflectionException(e); - } - catch (IllegalAccessException e) { - ReflectionUtils.handleReflectionException(e); - } - catch (IllegalArgumentException e) { - ReflectionUtils.handleReflectionException(e); - } - catch (InvocationTargetException e) { - ReflectionUtils.handleInvocationTargetException(e); - } - return null; - } -} 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 deleted file mode 100644 index f25d4f4c8..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateDatastore.java +++ /dev/null @@ -1,58 +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.codehaus.groovy.grails.orm.hibernate; - -import groovy.util.ConfigObject; - -import java.util.Map; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.model.MappingContext; -import org.hibernate.SessionFactory; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ConfigurableApplicationContext; - -/** - * Datastore implementation that uses a Hibernate SessionFactory underneath. - * - * @author Graeme Rocher - * @since 2.0 - */ -public class HibernateDatastore extends AbstractHibernateDatastore { - - public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config) { - super(mappingContext, sessionFactory, config); - } - - public HibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, ConfigObject config, ApplicationContext applicationContext) { - super(mappingContext, sessionFactory, config, applicationContext); - } - - @Override - protected Session createSession(Map connectionDetails) { - return new HibernateSession(this, sessionFactory); - } - - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - super.setApplicationContext(applicationContext); - - if (applicationContext != null) { - // support for callbacks in domain classes - eventTriggeringInterceptor = new EventTriggeringInterceptor(this, config); - ((ConfigurableApplicationContext)applicationContext).addApplicationListener(eventTriggeringInterceptor); - } - } -} 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 deleted file mode 100644 index a79f98d27..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormEnhancer.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.codehaus.groovy.grails.orm.hibernate - -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 - -/** - * Extended GORM Enhancer that fills out the remaining GORM for Hibernate methods - * and implements string-based query support via HQL. - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class HibernateGormEnhancer extends AbstractHibernateGormEnhancer { - - HibernateGormEnhancer(HibernateDatastore datastore, PlatformTransactionManager transactionManager, GrailsApplication grailsApplication) { - super(datastore, transactionManager, grailsApplication) - } - - protected List 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 GormValidationApi getValidationApi(Class cls) { - new HibernateGormValidationApi(cls, (HibernateDatastore)datastore, classLoader) - } - - @Override - protected GormStaticApi getStaticApi(Class cls) { - new HibernateGormStaticApi(cls, (HibernateDatastore)datastore, getFinders(), classLoader, transactionManager) - } - - @Override - protected GormInstanceApi getInstanceApi(Class cls) { - new HibernateGormInstanceApi(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 deleted file mode 100644 index 5c38fbbcb..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormInstanceApi.groovy +++ /dev/null @@ -1,277 +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 - -import groovy.transform.CompileStatic - -import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.domain.GrailsDomainClassMappingContext -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.hibernate.SessionFactory -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. - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class HibernateGormInstanceApi extends AbstractHibernateGormInstanceApi { - - protected SavePersistentMethod saveMethod - protected MergePersistentMethod mergeMethod - protected GrailsHibernateTemplate hibernateTemplate - protected InstanceApiHelper instanceApiHelper - - HibernateGormInstanceApi(Class persistentClass, HibernateDatastore datastore, ClassLoader classLoader) { - super(persistentClass, datastore, classLoader) - - def mappingContext = datastore.mappingContext - if (mappingContext instanceof GrailsDomainClassMappingContext) { - GrailsDomainClassMappingContext domainClassMappingContext = (GrailsDomainClassMappingContext)mappingContext - def grailsApplication = domainClassMappingContext.getGrailsApplication() - 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) - cacheQueriesByDefault = GrailsHibernateUtil.isCacheQueriesByDefault(grailsApplication) - } - else { - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory) - } - instanceApiHelper = new InstanceApiHelper(hibernateTemplate) - } - - /** - * Checks whether a field is dirty - * - * @param instance The instance - * @param fieldName The name of the field - * - * @return true if the field is dirty - */ - boolean isDirty(D instance, String fieldName) { - SessionImplementor session = (SessionImplementor)sessionFactory.currentSession - def entry = findEntityEntry(instance, session) - if (!entry || !entry.loadedState) { - return false - } - - Object[] values = entry.persister.getPropertyValues(instance) - int[] dirtyProperties = entry.persister.findDirty(values, entry.loadedState, instance, session) - if(!dirtyProperties) return false - int fieldIndex = entry.persister.propertyNames.findIndexOf { fieldName == it } - return fieldIndex in dirtyProperties - } - - /** - * Checks whether an entity is dirty - * - * @param instance The instance - * @return true if it is dirty - */ - boolean isDirty(D instance) { - SessionImplementor session = (SessionImplementor)sessionFactory.currentSession - def entry = findEntityEntry(instance, session) - if (!entry || !entry.loadedState) { - return false - } - - Object[] values = entry.persister.getPropertyValues(instance) - def dirtyProperties = entry.persister.findDirty(values, entry.loadedState, instance, session) - return dirtyProperties != null - } - - /** - * Obtains a list of property names that are dirty - * - * @param instance The instance - * @return A list of property names that are dirty - */ - List getDirtyPropertyNames(D instance) { - SessionImplementor session = (SessionImplementor)sessionFactory.currentSession - def entry = findEntityEntry(instance, session) - if (!entry || !entry.loadedState) { - return [] - } - - Object[] values = entry.persister.getPropertyValues(instance) - int[] dirtyProperties = entry.persister.findDirty(values, entry.loadedState, instance, session) - def names = [] - for (index in dirtyProperties) { - names << entry.persister.propertyNames[index] - } - names - } - - /** - * Gets the original persisted value of a field. - * - * @param fieldName The field name - * @return The original persisted value - */ - Object getPersistentValue(D instance, String fieldName) { - SessionImplementor session = (SessionImplementor)sessionFactory.currentSession - def entry = findEntityEntry(instance, session, false) - if (!entry || !entry.loadedState) { - return null - } - - int fieldIndex = entry.persister.propertyNames.findIndexOf { fieldName == it } - 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 saveMethod.invoke(instance, "save", EMPTY_ARRAY) - } - return super.save(instance) - } - - D save(D instance, boolean validate) { - if (saveMethod) { - return saveMethod.invoke(instance, "save", [validate] as Object[]) - } - return super.save(instance, validate) - } - - @Override - D merge(D instance) { - if (mergeMethod) { - mergeMethod.invoke(instance, "merge", EMPTY_ARRAY) - } - else { - return super.merge(instance) - } - } - - @Override - D merge(D instance, Map params) { - if (mergeMethod) { - mergeMethod.invoke(instance, "merge", [params] as Object[]) - } - else { - return super.merge(instance, params) - } - } - - @Override - D save(D instance, Map params) { - if (saveMethod) { - return 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) { - def entry = session.persistenceContext.getEntry(instance) - if (!entry) { - return null - } - - if (forDirtyCheck && !entry.requiresDirtyCheck(instance) && entry.loadedState) { - return null - } - - 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 - } -} 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 deleted file mode 100644 index 8e2367fbb..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormStaticApi.groovy +++ /dev/null @@ -1,636 +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 - -import grails.orm.HibernateCriteriaBuilder -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.domain.GrailsDomainClassMappingContext -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.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.query.api.Criteria 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 -import org.springframework.transaction.PlatformTransactionManager -import org.springframework.transaction.support.TransactionSynchronizationManager - -/** - * The implementation of the GORM static method contract for Hibernate - * - * @author Graeme Rocher - * @since 1.0 - */ -//@CompileStatic -class HibernateGormStaticApi extends GormStaticApi { - protected static final EMPTY_ARRAY = [] as Object[] - - 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 boolean cacheQueriesByDefault = false - protected GrailsDomainBinder grailsDomainBinder = new GrailsDomainBinder() - - HibernateGormStaticApi(Class persistentClass, HibernateDatastore datastore, List finders, - ClassLoader classLoader, PlatformTransactionManager transactionManager) { - super(persistentClass, datastore, finders) - - super.transactionManager = transactionManager - this.classLoader = classLoader - sessionFactory = datastore.getSessionFactory() - conversionService = datastore.mappingContext.conversionService - - identityType = persistentEntity.identity?.type - - def mappingContext = datastore.mappingContext - if (mappingContext instanceof GrailsDomainClassMappingContext) { - GrailsDomainClassMappingContext domainClassMappingContext = (GrailsDomainClassMappingContext)mappingContext - grailsApplication = domainClassMappingContext.getGrailsApplication() - - 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) - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, grailsApplication) - hibernateTemplate.setCacheQueries(cacheQueriesByDefault) - } else { - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory) - } - - executeQueryMethod = new ExecuteQueryPersistentMethod(sessionFactory, classLoader, grailsApplication, conversionService) - executeUpdateMethod = new ExecuteUpdatePersistentMethod(sessionFactory, classLoader, grailsApplication) - findMethod = new FindPersistentMethod(sessionFactory, classLoader, grailsApplication, conversionService) - findAllMethod = new FindAllPersistentMethod(sessionFactory, classLoader, grailsApplication, conversionService) - } - - @Override - D get(Serializable id) { - doGetInstance(id) - } - - 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 - } - } - - Serializable convertIdentifier(Object id) { - (Serializable)HibernateUtils.convertValueToType(id, identityType, conversionService) - } - - @Override - D read(Serializable id) { - if (id == null) { - return null - } - - hibernateTemplate.execute new GrailsHibernateTemplate.HibernateCallback() { - def doInHibernate(Session session) { - D o = doGetInstance((Serializable)id) - if (o && session.contains(o)) { - session.setReadOnly(o, true) - } - return o - } - } - } - - @Override - D load(Serializable id) { - id = convertIdentifier(id) - if (id != null) { - return hibernateTemplate.load((Class)persistentClass, id) - } - } - - @Override - List getAll() { - (List)hibernateTemplate.execute(new GrailsHibernateTemplate.HibernateCallback() { - def doInHibernate(Session session) { - Criteria criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings criteria - criteria.list() - } - }) - } - - List getAll(List ids) { - getAllInternal(ids) - } - - List getAll(Long... ids) { - getAllInternal(ids as List) - } - - @Override - List 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 - } - }) - } - - @Override - GrailsCriteria createCriteria() { - def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory) - builder.grailsApplication = grailsApplication - builder.conversionService = conversionService - builder - } - - @Override - D lock(Serializable id) { - (D)hibernateTemplate.lock((Class)persistentClass, convertIdentifier(id), LockMode.PESSIMISTIC_WRITE) - } - - @Override - D merge(o) { - mergeMethod.invoke(o, "merge", [] as Object[]) - } - - @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 - } - }) - } - - @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() - } - } - } - - @Override - List list(Map params) { - (List)listMethod.invoke(persistentClass, "list", [params] as Object[]) - } - - @Override - List list() { - (List)listMethod.invoke(persistentClass, "list", EMPTY_ARRAY) - } - - @Override - List findAll(example, Map args) { - (List)findAllMethod.invoke(persistentClass, "findAll", [example, args] as Object[]) - } - - @Override - D find(example, Map args) { - 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) { - 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) { - 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) { - 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) { - 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 findAll(String query, Map args, Integer max) { - (List)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 findAll(String query, Map args, Integer max, Integer offset) { - (List)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 findAll(String query, Integer max) { - (List)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 findAll(String query, Integer max, Integer offset) { - (List)findAllMethod.invoke(persistentClass, "findAll", [query, max, offset] as Object[]) - } - - @Override - List findAllWhere(Map queryMap, Map args) { - if (!queryMap) return null - - (List)hibernateTemplate.execute(new GrailsHibernateTemplate.HibernateCallback() { - def doInHibernate(Session session) { - Map queryArgs = filterQueryArgumentMap(queryMap) - List 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(CriteriaSpecification.DISTINCT_ROOT_ENTITY) - criteria.list() - } - }) - } - - @Override - D findWhere(Map queryMap, Map args) { - if (!queryMap) return null - - (D)hibernateTemplate.execute(new GrailsHibernateTemplate.HibernateCallback() { - def doInHibernate(Session session) { - Map queryArgs = filterQueryArgumentMap(queryMap) - List 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()) - } - }) - } - - 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 - } - } - return queryArgs - } - - private List removeNullNames(Map query) { - List nullNames = [] - Set allNames = new HashSet(query.keySet()) - for (String name in allNames) { - if (query[name] == null) { - query.remove name - nullNames << name - } - } - nullNames - } - - @Override - Object withSession(Closure callable) { - GrailsHibernateTemplate template = new GrailsHibernateTemplate(sessionFactory, grailsApplication) - template.setExposeNativeSession(false) - hibernateTemplate.execute new GrailsHibernateTemplate.HibernateCallback() { - def doInHibernate(Session session) { - callable(session) - } - } - } - - @Override - @CompileStatic(TypeCheckingMode.SKIP) - def withNewSession(Closure callable) { - GrailsHibernateTemplate template = new GrailsHibernateTemplate(sessionFactory, grailsApplication) - template.setExposeNativeSession(false) - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory) - Session previousSession = sessionHolder?.session - Session newSession - boolean newBind = false - try { - template.allowCreate = true - newSession = sessionFactory.openSession() - if (sessionHolder == null) { - sessionHolder = new SessionHolder(newSession) - TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder) - newBind = true - } - else { - sessionHolder.@session = newSession - } - - hibernateTemplate.execute new GrailsHibernateTemplate.HibernateCallback() { - def doInHibernate(Session session) { - callable(session) - } - } - } - finally { - try { - if (newSession) { - SessionFactoryUtils.closeSession(newSession) - } - if (newBind) { - TransactionSynchronizationManager.unbindResource(sessionFactory) - } - } - finally { - if (previousSession) { - sessionHolder.@session = previousSession - } - } - } - } - - @Override - List executeQuery(String query) { - (List)executeQueryMethod.invoke(persistentClass, "executeQuery", [query] as Object[]) - } - - List executeQuery(String query, arg) { - (List)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, arg] as Object[]) - } - - @Override - List executeQuery(String query, Map args) { - (List)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, args] as Object[]) - } - - @Override - List executeQuery(String query, Map params, Map args) { - (List)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, params, args] as Object[]) - } - - @Override - List executeQuery(String query, Collection params) { - (List)executeQueryMethod.invoke(persistentClass, "executeQuery", [query, params] as Object[]) - } - - @Override - List executeQuery(String query, Collection params, Map args) { - (List)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) { - findMethod.invoke(persistentClass, "find", [query] as Object[]) - } - - D find(String query, Object[] params) { - findMethod.invoke(persistentClass, "find", [query, params] as Object[]) - } - - @Override - D find(String query, Map args) { - findMethod.invoke(persistentClass, "find", [query, args] as Object[]) - } - - @Override - D find(String query, Map params, Map args) { - 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) { - findMethod.invoke(persistentClass, "find", [query, params, args] as Object[]) - } - - @Override - List findAll(String query) { - (List)findAllMethod.invoke(persistentClass, "findAll", [query] as Object[]) - } - - @Override - List findAll(String query, Map args) { - (List)findAllMethod.invoke(persistentClass, "findAll", [query, args] as Object[]) - } - - @Override - List findAll(String query, Map params, Map args) { - (List)findAllMethod.invoke(persistentClass, "findAll", [query, params, args] as Object[]) - } - - @Override - List findAll(String query, Collection params) { - (List)findAllMethod.invoke(persistentClass, "findAll", [query, params] as Object[]) - } - - @Override - List findAll(String query, Collection params, Map args) { - (List)findAllMethod.invoke(persistentClass, "findAll", [query, params, args] as Object[]) - } - - @Override - D create() { - return 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 deleted file mode 100644 index 5e1590c65..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateGormValidationApi.groovy +++ /dev/null @@ -1,39 +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 - -import groovy.transform.CompileStatic - -import org.codehaus.groovy.grails.domain.GrailsDomainClassMappingContext -import org.codehaus.groovy.grails.orm.hibernate.metaclass.ValidatePersistentMethod - -@CompileStatic -class HibernateGormValidationApi extends AbstractHibernateGormValidationApi { - - ValidatePersistentMethod validateMethod - - HibernateGormValidationApi(Class persistentClass, HibernateDatastore datastore, ClassLoader classLoader) { - super(persistentClass, datastore, classLoader) - - def mappingContext = datastore.mappingContext - if (mappingContext instanceof GrailsDomainClassMappingContext) { - GrailsDomainClassMappingContext domainClassMappingContext = (GrailsDomainClassMappingContext)mappingContext - def validator = mappingContext.getEntityValidator(mappingContext.getPersistentEntity(persistentClass.name)) - validateMethod = new ValidatePersistentMethod(datastore.getSessionFactory(), - classLoader, domainClassMappingContext.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 deleted file mode 100644 index dff494451..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/HibernateSession.java +++ /dev/null @@ -1,175 +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.codehaus.groovy.grails.orm.hibernate; - -import java.io.Serializable; -import java.sql.SQLException; -import java.util.List; -import java.util.Map; - -import javax.persistence.FlushModeType; - -import org.codehaus.groovy.grails.commons.GrailsApplication; -import org.codehaus.groovy.grails.domain.GrailsDomainClassMappingContext; -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; -import org.grails.datastore.mapping.query.jpa.JpaQueryBuilder; -import org.grails.datastore.mapping.query.jpa.JpaQueryInfo; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Restrictions; -import org.hibernate.proxy.HibernateProxy; - -/** - * Session implementation that wraps a Hibernate {@link org.hibernate.Session}. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class HibernateSession extends AbstractHibernateSession { - - ProxyHandler proxyHandler = new HibernateProxyHandler(); - public HibernateSession(HibernateDatastore hibernateDatastore, SessionFactory sessionFactory) { - super(hibernateDatastore, sessionFactory); - - if (datastore.getMappingContext() instanceof GrailsDomainClassMappingContext) { - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, - ((GrailsDomainClassMappingContext)datastore.getMappingContext()).getGrailsApplication()); - } - else { - GrailsApplication app = hibernateDatastore.getApplicationContext().getBean("grailsApplication", GrailsApplication.class); - hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, app); - } - } - - @Override - public Serializable getObjectIdentifier(Object instance) { - if(instance == null) return null; - if(proxyHandler.isProxy(instance)) { - return ((HibernateProxy)instance).getHibernateLazyInitializer().getIdentifier(); - } - Class type = instance.getClass(); - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(type); - final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(type.getName()); - if(persistentEntity != null) { - return (Serializable) cpf.getPropertyValue(instance, persistentEntity.getIdentity().getName()); - } - return null; - } - - /** - * Deletes all objects matching the given criteria. - * - * @param criteria The criteria - * @return The total number of records deleted - */ - public int deleteAll(final QueryableCriteria criteria) { - return getHibernateTemplate().execute(new GrailsHibernateTemplate.HibernateCallback() { - public Integer doInHibernate(Session session) throws HibernateException, SQLException { - JpaQueryBuilder builder = new JpaQueryBuilder(criteria); - builder.setHibernateCompatible(true); - JpaQueryInfo jpaQueryInfo = builder.buildDelete(); - - org.hibernate.Query query = session.createQuery(jpaQueryInfo.getQuery()); - getHibernateTemplate().applySettings(query); - - List parameters = jpaQueryInfo.getParameters(); - if (parameters != null) { - for (int i = 0, count = parameters.size(); i < count; i++) { - query.setParameter(i, parameters.get(i)); - } - } - return query.executeUpdate(); - } - }); - } - - /** - * Updates all objects matching the given criteria and property values. - * - * @param criteria The criteria - * @param properties The properties - * @return The total number of records updated - */ - public int updateAll(final QueryableCriteria criteria, final Map properties) { - return getHibernateTemplate().execute(new GrailsHibernateTemplate.HibernateCallback() { - public Integer doInHibernate(Session session) throws HibernateException, SQLException { - JpaQueryBuilder builder = new JpaQueryBuilder(criteria); - builder.setHibernateCompatible(true); - JpaQueryInfo jpaQueryInfo = builder.buildUpdate(properties); - - org.hibernate.Query query = session.createQuery(jpaQueryInfo.getQuery()); - getHibernateTemplate().applySettings(query); - List parameters = jpaQueryInfo.getParameters(); - if (parameters != null) { - for (int i = 0, count = parameters.size(); i < count; i++) { - query.setParameter(i, parameters.get(i)); - } - } - return query.executeUpdate(); - } - }); - } - - public List retrieveAll(final Class type, final Iterable keys) { - final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(type.getName()); - return getHibernateTemplate().execute(new GrailsHibernateTemplate.HibernateCallback() { - public List doInHibernate(org.hibernate.Session session) throws HibernateException, SQLException { - Criteria criteria = session.createCriteria(type); - getHibernateTemplate().applySettings(criteria); - return criteria.add( - Restrictions.in(persistentEntity.getIdentity().getName(), getIterableAsCollection(keys))) - .list(); - } - }); - } - - public Query createQuery(Class type) { - final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(type.getName()); - final Criteria criteria = getHibernateTemplate().getSessionFactory().getCurrentSession().createCriteria(type); - getHibernateTemplate().applySettings(criteria); - return new HibernateQuery(criteria, this, persistentEntity); - } - - protected GrailsHibernateTemplate getHibernateTemplate() { - return (GrailsHibernateTemplate)getNativeInterface(); - } - - public void setFlushMode(FlushModeType flushMode) { - if (flushMode == FlushModeType.AUTO) { - hibernateTemplate.setFlushMode(GrailsHibernateTemplate.FLUSH_AUTO); - } - else if (flushMode == FlushModeType.COMMIT) { - hibernateTemplate.setFlushMode(GrailsHibernateTemplate.FLUSH_COMMIT); - } - } - - public FlushModeType getFlushMode() { - switch (hibernateTemplate.getFlushMode()) { - case GrailsHibernateTemplate.FLUSH_AUTO: return FlushModeType.AUTO; - case GrailsHibernateTemplate.FLUSH_COMMIT: return FlushModeType.COMMIT; - case GrailsHibernateTemplate.FLUSH_ALWAYS: return FlushModeType.AUTO; - default: return FlushModeType.AUTO; - } - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/InstanceApiHelper.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/InstanceApiHelper.java deleted file mode 100644 index 242038d1d..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/InstanceApiHelper.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2013 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.codehaus.groovy.grails.orm.hibernate; - -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate.HibernateCallback; -import org.hibernate.FlushMode; -import org.hibernate.Session; - -/** - * Workaround for VerifyErrors in Groovy when using a HibernateCallback. - * - * @author Burt Beckwith - */ -public class InstanceApiHelper { - - protected GrailsHibernateTemplate hibernateTemplate; - - public InstanceApiHelper(final GrailsHibernateTemplate hibernateTemplate) { - this.hibernateTemplate = hibernateTemplate; - } - - public void delete(final Object obj, final boolean flush) { - hibernateTemplate.execute(new HibernateCallback() { - public Void doInHibernate(Session session) { - session.delete(obj); - if (flush) { - session.flush(); - } - return null; - } - }); - } - - public void setFlushModeManual() { - hibernateTemplate.execute(new HibernateCallback() { - public Void doInHibernate(Session session) { - session.setFlushMode(FlushMode.MANUAL); - return null; - } - }); - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/SessionFactoryProxy.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/SessionFactoryProxy.java deleted file mode 100644 index 1ebe0946b..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/SessionFactoryProxy.java +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Copyright 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.codehaus.groovy.grails.orm.hibernate; - -import groovy.lang.GroovyObjectSupport; -import groovy.lang.MissingPropertyException; - -import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.sql.Connection; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import javax.naming.NamingException; -import javax.naming.Reference; - -import org.codehaus.groovy.runtime.InvokerHelper; -import org.hibernate.Cache; -import org.hibernate.CustomEntityDirtinessStrategy; -import org.hibernate.HibernateException; -import org.hibernate.Interceptor; -import org.hibernate.MappingException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.SessionFactoryObserver; -import org.hibernate.StatelessSession; -import org.hibernate.StatelessSessionBuilder; -import org.hibernate.TypeHelper; -import org.hibernate.cache.spi.QueryCache; -import org.hibernate.cache.spi.Region; -import org.hibernate.cache.spi.UpdateTimestampsCache; -import org.hibernate.cfg.Settings; -import org.hibernate.context.spi.CurrentSessionContext; -import org.hibernate.context.spi.CurrentTenantIdentifierResolver; -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.function.SQLFunctionRegistry; -import org.hibernate.engine.ResultSetMappingDefinition; -import org.hibernate.engine.jdbc.spi.JdbcServices; -import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; -import org.hibernate.engine.profile.FetchProfile; -import org.hibernate.engine.query.spi.QueryPlanCache; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.engine.spi.NamedQueryDefinition; -import org.hibernate.engine.spi.NamedSQLQueryDefinition; -import org.hibernate.engine.spi.SessionBuilderImplementor; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.exception.spi.SQLExceptionConverter; -import org.hibernate.id.IdentifierGenerator; -import org.hibernate.id.factory.IdentifierGeneratorFactory; -import org.hibernate.metadata.ClassMetadata; -import org.hibernate.metadata.CollectionMetadata; -import org.hibernate.persister.collection.CollectionPersister; -import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.proxy.EntityNotFoundDelegate; -import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; -import org.hibernate.service.spi.ServiceRegistryImplementor; -import org.hibernate.stat.Statistics; -import org.hibernate.stat.spi.StatisticsImplementor; -import org.hibernate.type.Type; -import org.hibernate.type.TypeResolver; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.core.InfrastructureProxy; -import org.springframework.util.ReflectionUtils; - -/** - *

    Proxies the SessionFactory allowing for the underlying SessionFactory instance to be replaced at runtime. - * Used to enable rebuilding of the SessionFactory at development time

    - * - *

    NOTE: This class is not for production use and is development time only!

    - * - * @since 2.0 - * @author Graeme Rocher - */ -@SuppressWarnings("rawtypes") -public class SessionFactoryProxy extends GroovyObjectSupport implements SessionFactoryImplementor, ApplicationContextAware, InitializingBean, InfrastructureProxy { - - private static final long serialVersionUID = 1; - - private String targetBean; - private ApplicationContext applicationContext; - private Class currentSessionContextClass = GrailsSessionContext.class; - private SessionFactory currentSessionFactory; - - /** - * The target bean to proxy - * - * @param targetBean The name of the target bean - */ - public void setTargetBean(String targetBean) { - this.targetBean = targetBean; - } - - @Override - public Object getProperty(String property) { - try { - return super.getProperty(property); - } catch (MissingPropertyException e) { - return InvokerHelper.getProperty(getCurrentSessionFactory(), property); - } - } - - /** - * The class to use for the current session context - * - * @param currentSessionContextClass The current session context class - */ - public void setCurrentSessionContextClass(Class currentSessionContextClass) { - this.currentSessionContextClass = currentSessionContextClass; - } - - /** - * @return The current SessionFactory being proxied - */ - public SessionFactory getCurrentSessionFactory() { - - SessionFactory sf = applicationContext.getBean(targetBean, SessionFactoryHolder.class).getSessionFactory(); - - if (!sf.equals(currentSessionFactory)) { - currentSessionFactory = sf; - updateCurrentSessionContext(sf); - } - - return currentSessionFactory; - } - - /** - * @return The current SessionFactoryImplementor being proxied - */ - public SessionFactoryImplementor getCurrentSessionFactoryImplementor() { - return (SessionFactoryImplementor) getCurrentSessionFactory(); - } - - public Session openSession() throws HibernateException { - return getCurrentSessionFactory().openSession(); - } - - public Session getCurrentSession() throws HibernateException { - return getCurrentSessionFactory().getCurrentSession(); - } - - public StatelessSession openStatelessSession() { - return getCurrentSessionFactory().openStatelessSession(); - } - - public StatelessSession openStatelessSession(Connection connection) { - return getCurrentSessionFactory().openStatelessSession(connection); - } - - public ClassMetadata getClassMetadata(Class entityClass) { - return getCurrentSessionFactory().getClassMetadata(entityClass); - } - - public ClassMetadata getClassMetadata(String entityName) { - return getCurrentSessionFactory().getClassMetadata(entityName); - } - - public CollectionMetadata getCollectionMetadata(String roleName) { - return getCurrentSessionFactory().getCollectionMetadata(roleName); - } - - public Map getAllClassMetadata() { - return getCurrentSessionFactory().getAllClassMetadata(); - } - - public Map getAllCollectionMetadata() { - return getCurrentSessionFactory().getAllCollectionMetadata(); - } - - public Statistics getStatistics() { - return getCurrentSessionFactory().getStatistics(); - } - - public void close() throws HibernateException { - getCurrentSessionFactory().close(); - } - - public boolean isClosed() { - return getCurrentSessionFactory().isClosed(); - } - - public Cache getCache() { - return getCurrentSessionFactory().getCache(); - } - - @Deprecated - public void evict(Class persistentClass) throws HibernateException { - getCurrentSessionFactory().evict(persistentClass); - } - - @Deprecated - public void evict(Class persistentClass, Serializable id) throws HibernateException { - getCurrentSessionFactory().evict(persistentClass, id); - } - - @Deprecated - public void evictEntity(String entityName) throws HibernateException { - getCurrentSessionFactory().evictEntity(entityName); - } - - @Deprecated - public void evictEntity(String entityName, Serializable id) throws HibernateException { - getCurrentSessionFactory().evictEntity(entityName, id); - } - - @Deprecated - public void evictCollection(String roleName) throws HibernateException { - getCurrentSessionFactory().evictCollection(roleName); - } - - @Deprecated - public void evictCollection(String roleName, Serializable id) throws HibernateException { - getCurrentSessionFactory().evictCollection(roleName, id); - } - - @Deprecated - public void evictQueries(String cacheRegion) throws HibernateException { - getCurrentSessionFactory().evictQueries(cacheRegion); - } - - @Deprecated - public void evictQueries() throws HibernateException { - getCurrentSessionFactory().evictQueries(); - } - - public Set getDefinedFilterNames() { - return getCurrentSessionFactory().getDefinedFilterNames(); - } - - public FilterDefinition getFilterDefinition(String filterName) throws HibernateException { - return getCurrentSessionFactory().getFilterDefinition(filterName); - } - - public boolean containsFetchProfileDefinition(String name) { - return getCurrentSessionFactory().containsFetchProfileDefinition(name); - } - - public TypeHelper getTypeHelper() { - return getCurrentSessionFactory().getTypeHelper(); - } - - public Reference getReference() throws NamingException { - return getCurrentSessionFactory().getReference(); - } - - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - public TypeResolver getTypeResolver() { - return getCurrentSessionFactoryImplementor().getTypeResolver(); - } - - public Properties getProperties() { - return getCurrentSessionFactoryImplementor().getProperties(); - } - - public EntityPersister getEntityPersister(String entityName) throws MappingException { - return getCurrentSessionFactoryImplementor().getEntityPersister(entityName); - } - - public CollectionPersister getCollectionPersister(String role) throws MappingException { - return getCurrentSessionFactoryImplementor().getCollectionPersister(role); - } - - public Dialect getDialect() { - return getCurrentSessionFactoryImplementor().getDialect(); - } - - public Interceptor getInterceptor() { - return getCurrentSessionFactoryImplementor().getInterceptor(); - } - - public QueryPlanCache getQueryPlanCache() { - return getCurrentSessionFactoryImplementor().getQueryPlanCache(); - } - - public Type[] getReturnTypes(String queryString) throws HibernateException { - return getCurrentSessionFactoryImplementor().getReturnTypes(queryString); - } - - public String[] getReturnAliases(String queryString) throws HibernateException { - return getCurrentSessionFactoryImplementor().getReturnAliases(queryString); - } - - @SuppressWarnings("deprecation") - public ConnectionProvider getConnectionProvider() { - return getCurrentSessionFactoryImplementor().getConnectionProvider(); - } - - public String[] getImplementors(String className) throws MappingException { - return getCurrentSessionFactoryImplementor().getImplementors(className); - } - - public String getImportedClassName(String name) { - return getCurrentSessionFactoryImplementor().getImportedClassName(name); - } - - public QueryCache getQueryCache() { - return getCurrentSessionFactoryImplementor().getQueryCache(); - } - - public QueryCache getQueryCache(String regionName) throws HibernateException { - return getCurrentSessionFactoryImplementor().getQueryCache(regionName); - } - - public UpdateTimestampsCache getUpdateTimestampsCache() { - return getCurrentSessionFactoryImplementor().getUpdateTimestampsCache(); - } - - public StatisticsImplementor getStatisticsImplementor() { - return getCurrentSessionFactoryImplementor().getStatisticsImplementor(); - } - - public NamedQueryDefinition getNamedQuery(String queryName) { - return getCurrentSessionFactoryImplementor().getNamedQuery(queryName); - } - - public NamedSQLQueryDefinition getNamedSQLQuery(String queryName) { - return getCurrentSessionFactoryImplementor().getNamedSQLQuery(queryName); - } - - public ResultSetMappingDefinition getResultSetMapping(String name) { - return getCurrentSessionFactoryImplementor().getResultSetMapping(name); - } - - public IdentifierGenerator getIdentifierGenerator(String rootEntityName) { - return getCurrentSessionFactoryImplementor().getIdentifierGenerator(rootEntityName); - } - - public Region getSecondLevelCacheRegion(String regionName) { - return getCurrentSessionFactoryImplementor().getSecondLevelCacheRegion(regionName); - } - - public Map getAllSecondLevelCacheRegions() { - return getCurrentSessionFactoryImplementor().getAllSecondLevelCacheRegions(); - } - - public SQLExceptionConverter getSQLExceptionConverter() { - return getCurrentSessionFactoryImplementor().getSQLExceptionConverter(); - } - - public Settings getSettings() { - return getCurrentSessionFactoryImplementor().getSettings(); - } - - public Session openTemporarySession() throws HibernateException { - return getCurrentSessionFactoryImplementor().openTemporarySession(); - } - - public Set getCollectionRolesByEntityParticipant(String entityName) { - return getCurrentSessionFactoryImplementor().getCollectionRolesByEntityParticipant(entityName); - } - - public EntityNotFoundDelegate getEntityNotFoundDelegate() { - return getCurrentSessionFactoryImplementor().getEntityNotFoundDelegate(); - } - - public SQLFunctionRegistry getSqlFunctionRegistry() { - return getCurrentSessionFactoryImplementor().getSqlFunctionRegistry(); - } - - public FetchProfile getFetchProfile(String name) { - return getCurrentSessionFactoryImplementor().getFetchProfile(name); - } - - @Deprecated - public IdentifierGeneratorFactory getIdentifierGeneratorFactory() { - return getCurrentSessionFactoryImplementor().getIdentifierGeneratorFactory(); - } - - public Type getIdentifierType(String className) throws MappingException { - return getCurrentSessionFactoryImplementor().getIdentifierType(className); - } - - public String getIdentifierPropertyName(String className) throws MappingException { - return getCurrentSessionFactoryImplementor().getIdentifierPropertyName(className); - } - - public Type getReferencedPropertyType(String className, String propertyName) throws MappingException { - return getCurrentSessionFactoryImplementor().getReferencedPropertyType(className,propertyName); - } - - public void afterPropertiesSet() { - getCurrentSessionFactoryImplementor(); - } - - private void updateCurrentSessionContext(SessionFactory sessionFactory) { - // patch the currentSessionContext variable of SessionFactoryImpl to use this proxy as the key - CurrentSessionContext ssc = createCurrentSessionContext(); - if (ssc instanceof GrailsSessionContext) { - ((GrailsSessionContext)ssc).initJta(); - } - - try { - Class sessionFactoryClass = sessionFactory.getClass(); - Field currentSessionContextField = sessionFactoryClass.getDeclaredField("currentSessionContext"); - if (currentSessionContextField != null) { - ReflectionUtils.makeAccessible(currentSessionContextField); - currentSessionContextField.set(sessionFactory, ssc); - } - } catch (NoSuchFieldException e) { - // ignore - } catch (SecurityException e) { - // ignore - } catch (IllegalArgumentException e) { - // ignore - } catch (IllegalAccessException e) { - // ignore - } - } - - @SuppressWarnings("unchecked") - protected CurrentSessionContext createCurrentSessionContext() { - Class sessionContextClass = currentSessionContextClass; - if (sessionContextClass == null) { - sessionContextClass = GrailsSessionContext.class; - } - try { - Constructor constructor = sessionContextClass.getConstructor(SessionFactoryImplementor.class); - return BeanUtils.instantiateClass(constructor, this); - } catch (NoSuchMethodException e) { - return new GrailsSessionContext(this); - } - } - - public Object getWrappedObject() { - return getCurrentSessionFactory(); - } - - public SessionFactoryOptions getSessionFactoryOptions() { - return getCurrentSessionFactoryImplementor().getSessionFactoryOptions(); - } - - public StatelessSessionBuilder withStatelessOptions() { - return getCurrentSessionFactoryImplementor().withStatelessOptions(); - } - - public SessionBuilderImplementor withOptions() { - return getCurrentSessionFactoryImplementor().withOptions(); - } - - public Map getEntityPersisters() { - return getCurrentSessionFactoryImplementor().getEntityPersisters(); - } - - public Map getCollectionPersisters() { - return getCurrentSessionFactoryImplementor().getCollectionPersisters(); - } - - public JdbcServices getJdbcServices() { - return getCurrentSessionFactoryImplementor().getJdbcServices(); - } - - public Region getNaturalIdCacheRegion(String regionName) { - return getCurrentSessionFactoryImplementor().getNaturalIdCacheRegion(regionName); - } - - public SqlExceptionHelper getSQLExceptionHelper() { - return getCurrentSessionFactoryImplementor().getSQLExceptionHelper(); - } - - public ServiceRegistryImplementor getServiceRegistry() { - return getCurrentSessionFactoryImplementor().getServiceRegistry(); - } - - public void addObserver(SessionFactoryObserver observer) { - getCurrentSessionFactoryImplementor().addObserver(observer); - } - - public CustomEntityDirtinessStrategy getCustomEntityDirtinessStrategy() { - return getCurrentSessionFactoryImplementor().getCustomEntityDirtinessStrategy(); - } - - public CurrentTenantIdentifierResolver getCurrentTenantIdentifierResolver() { - return getCurrentSessionFactoryImplementor().getCurrentTenantIdentifierResolver(); - } -} 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 deleted file mode 100644 index bbdf105d7..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/DefaultGrailsDomainConfiguration.java +++ /dev/null @@ -1,126 +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.cfg; - -import groovy.lang.Closure; -import groovy.util.Eval; - -import java.util.HashSet; -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.hibernate.MappingException; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Mappings; - -/** - * Creates runtime configuration mapping for the Grails domain classes - * based on the work done in the Hibernate Annotations project - * - * @author Graeme Rocher - * @since 06-Jul-2005 - */ -public class DefaultGrailsDomainConfiguration extends Configuration implements GrailsDomainConfiguration { - - private static final long serialVersionUID = -7115087342689305517L; - private GrailsApplication grailsApplication; - private Set domainClasses = new HashSet(); - private boolean configLocked; - private String sessionFactoryBeanName = "sessionFactory"; - private String dataSourceName = GrailsDomainClassProperty.DEFAULT_DATA_SOURCE; - - protected static GrailsDomainBinder binder = new GrailsDomainBinder(); - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainConfiguration#addDomainClass(org.codehaus.groovy.grails.commons.GrailsDomainClass) - */ - public GrailsDomainConfiguration addDomainClass(GrailsDomainClass domainClass) { - if (domainClass.getMappingStrategy().equalsIgnoreCase(GrailsDomainClass.GORM)) { - domainClasses.add(domainClass); - } - - return this; - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainConfiguration#setGrailsApplication(org.codehaus.groovy.grails.commons.GrailsApplication) - */ - public void setGrailsApplication(GrailsApplication application) { - grailsApplication = application; - if (grailsApplication == null) { - return; - } - - GrailsClass[] existingDomainClasses = grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE); - for (GrailsClass existingDomainClass : existingDomainClasses) { - addDomainClass((GrailsDomainClass) existingDomainClass); - } - } - - public void setSessionFactoryBeanName(String name) { - sessionFactoryBeanName = name; - } - - public void setDataSourceName(String name) { - dataSourceName = name; - } - - /** - * Overrides the default behaviour to including binding of Grails domain classes. - */ - @Override - protected void secondPassCompile() throws MappingException { - if (configLocked) { - return; - } - - // set the class loader to load Groovy classes - if (grailsApplication != null) { - Thread.currentThread().setContextClassLoader(grailsApplication.getClassLoader()); - } - - configureDomainBinder(grailsApplication, domainClasses); - - for (GrailsDomainClass domainClass : domainClasses) { - if (!GrailsHibernateUtil.usesDatasource(domainClass, dataSourceName)) { - continue; - } - final Mappings mappings = super.createMappings(); - Mapping m = binder.getMapping(domainClass); - mappings.setAutoImport(m == null || m.getAutoImport()); - binder.bindClass(domainClass, mappings, sessionFactoryBeanName); - } - - super.secondPassCompile(); - configLocked = true; - } - - public static void configureDomainBinder(GrailsApplication grailsApplication, Set domainClasses) { - Object defaultMapping = Eval.x(grailsApplication, "x.config?.grails?.gorm?.default?.mapping"); - // do Grails class configuration - for (GrailsDomainClass domainClass : domainClasses) { - if (defaultMapping instanceof Closure) { - binder.evaluateMapping(domainClass, (Closure)defaultMapping); - } - else { - binder.evaluateMapping(domainClass); - } - } - } -} 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 deleted file mode 100644 index 1be009656..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsAnnotationConfiguration.java +++ /dev/null @@ -1,401 +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.cfg; - -import java.io.IOException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import javax.persistence.Embeddable; -import javax.persistence.Entity; -import javax.persistence.MappedSuperclass; - -import org.codehaus.groovy.grails.commons.AnnotationDomainClassArtefactHandler; -import org.codehaus.groovy.grails.commons.ArtefactHandler; -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.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.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.cfg.ImprovedNamingStrategy; -import org.hibernate.cfg.Mappings; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.service.BootstrapServiceRegistry; -import org.hibernate.service.BootstrapServiceRegistryBuilder; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.service.ServiceRegistryBuilder; -import org.hibernate.service.spi.ServiceRegistryImplementor; -import org.hibernate.type.Type; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.ResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternUtils; -import org.springframework.core.type.classreading.CachingMetadataReaderFactory; -import org.springframework.core.type.classreading.MetadataReader; -import org.springframework.core.type.classreading.MetadataReaderFactory; -import org.springframework.core.type.filter.AnnotationTypeFilter; -import org.springframework.core.type.filter.TypeFilter; -import org.springframework.util.ClassUtils; - -/** - * Allows configuring Grails' hibernate support to work in conjuntion with Hibernate's annotation - * support. - * - * @author Graeme Rocher - * @since 18-Feb-2006 - */ -public class GrailsAnnotationConfiguration extends Configuration implements GrailsDomainConfiguration, InitializingBean { - - private static final long serialVersionUID = -7115087342689305517L; - - protected Logger log = LoggerFactory.getLogger(getClass()); - - private GrailsApplication grailsApplication; - private Set domainClasses = new HashSet(); - private boolean configLocked; - private String sessionFactoryBeanName = "sessionFactory"; - private String dataSourceName = GrailsDomainClassProperty.DEFAULT_DATA_SOURCE; - - private static final String RESOURCE_PATTERN = "/**/*.class"; - - private static final TypeFilter[] ENTITY_TYPE_FILTERS = new TypeFilter[] { - new AnnotationTypeFilter(Entity.class, false), - new AnnotationTypeFilter(Embeddable.class, false), - new AnnotationTypeFilter(MappedSuperclass.class, false)}; - - private ResourcePatternResolver resourcePatternResolver; - private ServiceRegistry serviceRegistry; - private HibernateEventListeners hibernateEventListeners; - private Map eventListeners; - - protected GrailsDomainBinder binder = new GrailsDomainBinder(); - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainConfiguration#addDomainClass(org.codehaus.groovy.grails.commons.GrailsDomainClass) - */ - public GrailsDomainConfiguration addDomainClass(GrailsDomainClass domainClass) { - if (shouldMapWithGorm(domainClass)) { - domainClasses.add(domainClass); - } - - return this; - } - - private boolean shouldMapWithGorm(GrailsDomainClass domainClass) { - return !AnnotationDomainClassArtefactHandler.isJPADomainClass(domainClass.getClazz()) && - domainClass.getMappingStrategy().equalsIgnoreCase(GrailsDomainClass.GORM); - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainConfiguration#setGrailsApplication(org.codehaus.groovy.grails.commons.GrailsApplication) - */ - public void setGrailsApplication(GrailsApplication application) { - grailsApplication = application; - if (grailsApplication == null) { - return; - } - - GrailsClass[] existingDomainClasses = grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE); - for (GrailsClass existingDomainClass : existingDomainClasses) { - addDomainClass((GrailsDomainClass) existingDomainClass); - } - } - - public void setSessionFactoryBeanName(String name) { - sessionFactoryBeanName = name; - } - - public void setDataSourceName(String name) { - dataSourceName = name; - } - - /** - * Overrides the default behaviour to including binding of Grails domain classes. - */ - @Override - protected void secondPassCompile() throws MappingException { - final Thread currentThread = Thread.currentThread(); - final ClassLoader originalContextLoader = currentThread.getContextClassLoader(); - if (!configLocked) { - log.debug("[GrailsAnnotationConfiguration] [{}] Grails domain classes to bind to persistence runtime", domainClasses.size()); - - // do Grails class configuration - DefaultGrailsDomainConfiguration.configureDomainBinder(grailsApplication, domainClasses); - - for (GrailsDomainClass domainClass : domainClasses) { - - final String fullClassName = domainClass.getFullName(); - - String hibernateConfig = fullClassName.replace('.', '/') + ".hbm.xml"; - final ClassLoader loader = originalContextLoader; - // don't configure Hibernate mapped classes - if (loader.getResource(hibernateConfig) != null) continue; - - final Mappings mappings = super.createMappings(); - if (!GrailsHibernateUtil.usesDatasource(domainClass, dataSourceName)) { - continue; - } - - log.debug("[GrailsAnnotationConfiguration] Binding persistent class [{}]", fullClassName); - - Mapping m = binder.getMapping(domainClass); - mappings.setAutoImport(m == null || m.getAutoImport()); - binder.bindClass(domainClass, mappings, sessionFactoryBeanName); - } - } - - try { - currentThread.setContextClassLoader(grailsApplication.getClassLoader()); - super.secondPassCompile(); - } finally { - currentThread.setContextClassLoader(originalContextLoader); - } - - configLocked = true; - } - - /** - * Sets custom naming strategy specified in configuration or the default {@link ImprovedNamingStrategy}. - */ - private void configureNamingStrategy() { - NamingStrategy strategy = null; - Object customStrategy = grailsApplication.getFlatConfig().get("hibernate.naming_strategy"); - if (customStrategy != null) { - Class namingStrategyClass = null; - if (customStrategy instanceof Class) { - namingStrategyClass = (Class)customStrategy; - } else { - try { - namingStrategyClass = grailsApplication.getClassLoader().loadClass(customStrategy.toString()); - } catch (ClassNotFoundException e) { - // ignore - } - } - - if (namingStrategyClass != null) { - try { - strategy = (NamingStrategy)namingStrategyClass.newInstance(); - } catch (InstantiationException e) { - // ignore - } catch (IllegalAccessException e) { - // ignore - } - } - } - - if (strategy == null) { - strategy = ImprovedNamingStrategy.INSTANCE; - } - - setNamingStrategy(strategy); - } - - /** - * Add the given annotated classes in a batch. - * @see #addAnnotatedClass - * @see #scanPackages - */ - public void addAnnotatedClasses(Class... annotatedClasses) { - for (Class annotatedClass : annotatedClasses) { - addAnnotatedClass(annotatedClass); - } - } - - /** - * Add the given annotated packages in a batch. - * @see #addPackage - * @see #scanPackages - */ - public void addPackages(String... annotatedPackages) { - for (String annotatedPackage :annotatedPackages) { - addPackage(annotatedPackage); - } - } - - /** - * Default listeners. - * @param listeners the listeners - */ - public void setEventListeners(Map listeners) { - eventListeners = listeners; - } - - /** - * User-specifiable extra listeners. - * @param listeners the listeners - */ - public void setHibernateEventListeners(HibernateEventListeners listeners) { - hibernateEventListeners = listeners; - } - - /** - * Perform Spring-based scanning for entity classes, registering them - * as annotated classes with this {@code Configuration}. - * @param packagesToScan one or more Java package names - * @throws HibernateException if scanning fails for any reason - */ - public void scanPackages(String... packagesToScan) throws HibernateException { - try { - for (String pkg : packagesToScan) { - String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + - ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN; - Resource[] resources = resourcePatternResolver.getResources(pattern); - MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver); - for (Resource resource : resources) { - if (resource.isReadable()) { - MetadataReader reader = readerFactory.getMetadataReader(resource); - String className = reader.getClassMetadata().getClassName(); - if (matchesFilter(reader, readerFactory)) { - addAnnotatedClasses(resourcePatternResolver.getClassLoader().loadClass(className)); - } - } - } - } - } - catch (IOException ex) { - throw new MappingException("Failed to scan classpath for unlisted classes", ex); - } - catch (ClassNotFoundException ex) { - throw new MappingException("Failed to load annotated classes from classpath", ex); - } - } - - /** - * Check whether any of the configured entity type filters matches - * the current class descriptor contained in the metadata reader. - */ - protected boolean matchesFilter(MetadataReader reader, MetadataReaderFactory readerFactory) throws IOException { - for (TypeFilter filter : ENTITY_TYPE_FILTERS) { - if (filter.match(reader, readerFactory)) { - return true; - } - } - return false; - } - - @Override - public SessionFactory buildSessionFactory() throws HibernateException { - - // set the class loader to load Groovy classes - if (grailsApplication != null) { - log.debug("[GrailsAnnotationConfiguration] Setting context class loader to Grails GroovyClassLoader"); - Thread.currentThread().setContextClassLoader(grailsApplication.getClassLoader()); - } - - // work around for HHH-2624 - Map empty = new HashMap(); - addFilterDefinition(new FilterDefinition("dynamicFilterEnabler", "1=1", empty)); - - SessionFactory sessionFactory = null; - - ClassLoader appClassLoader = (ClassLoader) getProperties().get(AvailableSettings.APP_CLASSLOADER); - Thread currentThread = Thread.currentThread(); - ClassLoader threadContextClassLoader = currentThread.getContextClassLoader(); - boolean overrideClassLoader = (appClassLoader != null && !appClassLoader.equals(threadContextClassLoader)); - if (overrideClassLoader) { - currentThread.setContextClassLoader(appClassLoader); - } - - try { - ConfigurationHelper.resolvePlaceHolders(getProperties()); - - EventListenerIntegrator eventListenerIntegrator = new EventListenerIntegrator(hibernateEventListeners, eventListeners); - BootstrapServiceRegistry bootstrapServiceRegistry = new BootstrapServiceRegistryBuilder().with(eventListenerIntegrator).build(); - - setSessionFactoryObserver(new SessionFactoryObserver() { - private static final long serialVersionUID = 1; - public void sessionFactoryCreated(SessionFactory factory) {} - public void sessionFactoryClosed(SessionFactory factory) { - ((ServiceRegistryImplementor)serviceRegistry).destroy(); - } - }); - - sessionFactory = super.buildSessionFactory(new ServiceRegistryBuilder(bootstrapServiceRegistry).applySettings(getProperties()).buildServiceRegistry()); - serviceRegistry = ((SessionFactoryImplementor)sessionFactory).getServiceRegistry(); - } - finally { - if (overrideClassLoader) { - currentThread.setContextClassLoader(threadContextClassLoader); - } - } - - if (grailsApplication != null) { - GrailsHibernateUtil.configureHibernateDomainClasses( - sessionFactory, sessionFactoryBeanName, grailsApplication); - } - - return sessionFactory; - } - - public ServiceRegistry getServiceRegistry() { - return serviceRegistry; - } - - public void afterPropertiesSet() throws Exception { - if (grailsApplication == null) { - return; - } - - String dsName = GrailsDomainClassProperty.DEFAULT_DATA_SOURCE.equals(dataSourceName) ? "dataSource" : "dataSource_" + dataSourceName; - getProperties().put(Environment.DATASOURCE, grailsApplication.getMainContext().getBean(dsName)); - getProperties().put(Environment.CURRENT_SESSION_CONTEXT_CLASS, GrailsSessionContext.class.getName()); - getProperties().put(AvailableSettings.APP_CLASSLOADER, grailsApplication.getClassLoader()); - resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(grailsApplication.getMainContext()); - - configureNamingStrategy(); - GrailsClass[] existingDomainClasses = grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE); - for (GrailsClass existingDomainClass : existingDomainClasses) { - addDomainClass((GrailsDomainClass) existingDomainClass); - } - - ArtefactHandler handler = grailsApplication.getArtefactHandler(DomainClassArtefactHandler.TYPE); - if (!(handler instanceof AnnotationDomainClassArtefactHandler)) { - return; - } - - Set jpaDomainNames = ((AnnotationDomainClassArtefactHandler)handler).getJpaClassNames(); - if (jpaDomainNames == null) { - return; - } - - final ClassLoader loader = grailsApplication.getClassLoader(); - for (String jpaDomainName : jpaDomainNames) { - try { - addAnnotatedClass(loader.loadClass(jpaDomainName)); - } - catch (ClassNotFoundException e) { - // impossible condition - } - } - } -} 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 deleted file mode 100644 index a6c4dc0c1..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsDomainBinder.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.cfg; - -import java.util.Arrays; -import java.util.List; - -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -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; - -/** - * Handles the binding Grails domain classes and properties to the Hibernate runtime meta model. - * Based on the HbmBinder code in Hibernate core and influenced by AnnotationsBinder. - * - * @author Graeme Rocher - * @since 0.1 - */ -public class GrailsDomainBinder extends AbstractGrailsDomainBinder { - - protected Class getGroovyAwareJoinedSubclassEntityPersisterClass() { - return GroovyAwareJoinedSubclassEntityPersister.class; - } - - protected Class getGroovyAwareSingleTableEntityPersisterClass() { - return GroovyAwareSingleTableEntityPersister.class; - } - - protected void handleLazyProxy(GrailsDomainClass domainClass, GrailsDomainClassProperty grailsProperty) { - HibernateUtils.handleLazyProxy(domainClass, grailsProperty); - } - - protected void handleUniqueConstraint(GrailsDomainClassProperty property, Column column, String path, Table table, String columnName, String sessionFactoryBeanName) { - ConstrainedProperty cp = getConstrainedProperty(property); - if (cp != null && cp.hasAppliedConstraint(UniqueConstraint.UNIQUE_CONSTRAINT)) { - Constraint appliedConstraint = cp.getAppliedConstraint(UniqueConstraint.UNIQUE_CONSTRAINT); - if (appliedConstraint instanceof UniqueConstraint) { - UniqueConstraint uc = (UniqueConstraint) appliedConstraint; - if (uc != null && uc.isUnique()) { - if (!uc.isUniqueWithinGroup()) { - column.setUnique(true); - } - else if (uc.getUniquenessGroup().size() > 0) { - createKeyForProps(property, path, table, columnName, uc.getUniquenessGroup(), sessionFactoryBeanName); - } - } - } - } - else { - Object val = cp != null ? cp.getMetaConstraintValue(UniqueConstraint.UNIQUE_CONSTRAINT) : null; - if (val instanceof Boolean) { - column.setUnique((Boolean)val); - } - else if (val instanceof String) { - createKeyForProps(property, path, table, columnName, Arrays.asList((String) val), sessionFactoryBeanName); - } - else if (val instanceof List && ((List)val).size() > 0) { - createKeyForProps(property, path, table, columnName, (List)val, sessionFactoryBeanName); - } - } - } - - protected boolean identityEnumTypeSupports(Class propertyType) { - return IdentityEnumType.supports(propertyType); - } - - protected boolean isNotEmpty(String s) { - return GrailsHibernateUtil.isNotEmpty(s); - } - - protected String qualify(String prefix, String name) { - return GrailsHibernateUtil.qualify(prefix, name); - } - - protected String unqualify(String qualifiedName) { - return GrailsHibernateUtil.unqualify(qualifiedName); - } -} 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 deleted file mode 100644 index 63a5b5343..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/GrailsHibernateUtil.java +++ /dev/null @@ -1,611 +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.cfg; - -import grails.util.CollectionUtils; -import grails.util.GrailsWebUtil; -import groovy.lang.GroovyObject; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.lang.StringUtils; -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.GrailsClass; -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.GrailsHibernateDomainClass; -import org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwareJavassistProxyFactory; -import org.codehaus.groovy.grails.orm.hibernate.proxy.HibernateProxyHandler; -import org.codehaus.groovy.grails.web.context.GrailsConfigUtils; -import org.hibernate.Criteria; -import org.hibernate.FetchMode; -import org.hibernate.FlushMode; -import org.hibernate.Hibernate; -import org.hibernate.HibernateException; -import org.hibernate.LockMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Order; -import org.hibernate.engine.spi.EntityEntry; -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.engine.spi.Status; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.Property; -import org.hibernate.metadata.ClassMetadata; -import org.hibernate.property.Getter; -import org.hibernate.property.Setter; -import org.hibernate.proxy.HibernateProxy; -import org.hibernate.type.CompositeType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.core.convert.ConversionService; - -/** - * Utility methods for configuring Hibernate inside Grails. - * - * @author Graeme Rocher - * @since 0.4 - */ -public class GrailsHibernateUtil { - private static final Logger LOG = LoggerFactory.getLogger(GrailsHibernateUtil.class); - - private static final String DYNAMIC_FILTER_ENABLER = "dynamicFilterEnabler"; - - 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"; - public static final String ARGUMENT_SORT = "sort"; - public static final String ORDER_DESC = "desc"; - public static final String ORDER_ASC = "asc"; - public static final String ARGUMENT_FETCH = "fetch"; - public static final String ARGUMENT_IGNORE_CASE = "ignoreCase"; - public static final String ARGUMENT_CACHE = "cache"; - public static final String ARGUMENT_LOCK = "lock"; - public static final String CONFIG_PROPERTY_CACHE_QUERIES="grails.hibernate.cache.queries"; - public static final String CONFIG_PROPERTY_OSIV_READONLY="grails.hibernate.osiv.readonly"; - public static final Class[] EMPTY_CLASS_ARRAY = {}; - - private static HibernateProxyHandler proxyHandler = new HibernateProxyHandler(); - - private static GrailsDomainBinder binder = new GrailsDomainBinder(); - - @SuppressWarnings("rawtypes") - public static void enableDynamicFilterEnablerIfPresent(SessionFactory sessionFactory, Session session) { - if (sessionFactory != null && session != null) { - final Set definedFilterNames = sessionFactory.getDefinedFilterNames(); - if (definedFilterNames != null && definedFilterNames.contains(DYNAMIC_FILTER_ENABLER)) - session.enableFilter(DYNAMIC_FILTER_ENABLER); // work around for HHH-2624 - } - } - - public static void configureHibernateDomainClasses(SessionFactory sessionFactory, - String sessionFactoryName, GrailsApplication application) { - Map hibernateDomainClassMap = new HashMap(); - for (Object o : sessionFactory.getAllClassMetadata().values()) { - ClassMetadata classMetadata = (ClassMetadata) o; - configureDomainClass(sessionFactory, sessionFactoryName, application, classMetadata, - classMetadata.getMappedClass(), hibernateDomainClassMap); - } - configureInheritanceMappings(hibernateDomainClassMap); - } - - @SuppressWarnings("rawtypes") - public static void configureInheritanceMappings(Map hibernateDomainClassMap) { - // now get through all domainclasses, and add all subclasses to root class - for (Object o : hibernateDomainClassMap.values()) { - GrailsDomainClass baseClass = (GrailsDomainClass) o; - if (!baseClass.isRoot()) { - Class superClass = baseClass.getClazz().getSuperclass(); - - while (!superClass.equals(Object.class) && !superClass.equals(GroovyObject.class)) { - GrailsDomainClass gdc = (GrailsDomainClass) hibernateDomainClassMap.get(superClass.getName()); - - if (gdc == null || gdc.getSubClasses() == null) { - LOG.debug("did not find superclass names when mapping inheritance...."); - break; - } - gdc.getSubClasses().add(baseClass); - superClass = superClass.getSuperclass(); - } - } - } - } - - private static void configureDomainClass(SessionFactory sessionFactory, String sessionFactoryName, - GrailsApplication application, ClassMetadata cmd, Class persistentClass, - Map hibernateDomainClassMap) { - LOG.trace("Configuring domain class [" + persistentClass + "]"); - GrailsDomainClass dc = (GrailsDomainClass) application.getArtefact(DomainClassArtefactHandler.TYPE, persistentClass.getName()); - if (dc == null && sessionFactory.getClassMetadata(persistentClass) != null) { - // a patch to add inheritance to this system - GrailsHibernateDomainClass ghdc = new GrailsHibernateDomainClass( - persistentClass, sessionFactory, sessionFactoryName, application, cmd); - - hibernateDomainClassMap.put(persistentClass.getName(), ghdc); - dc = (GrailsDomainClass) application.addArtefact(DomainClassArtefactHandler.TYPE, ghdc); - } - } - - public static void populateArgumentsForCriteria(GrailsApplication grailsApplication, Class targetClass, Criteria c, Map argMap, ConversionService conversionService) { - populateArgumentsForCriteria(grailsApplication, targetClass, c, argMap, conversionService, true); - } - - /** - * Populates criteria arguments for the given target class and arguments map - * - * @param grailsApplication the GrailsApplication instance - * @param targetClass The target class - * @param c The criteria instance - * @param argMap The arguments map - */ - @SuppressWarnings("rawtypes") - public static void populateArgumentsForCriteria(GrailsApplication grailsApplication, Class targetClass, Criteria c, Map argMap, ConversionService conversionService, boolean useDefaultMapping) { - Integer maxParam = null; - Integer offsetParam = null; - if (argMap.containsKey(ARGUMENT_MAX)) { - maxParam = conversionService.convert(argMap.get(ARGUMENT_MAX),Integer.class); - } - if (argMap.containsKey(ARGUMENT_OFFSET)) { - offsetParam = conversionService.convert(argMap.get(ARGUMENT_OFFSET),Integer.class); - } - if (argMap.containsKey(ARGUMENT_FETCH_SIZE)) { - c.setFetchSize(conversionService.convert(argMap.get(ARGUMENT_FETCH_SIZE),Integer.class)); - } - if (argMap.containsKey(ARGUMENT_TIMEOUT)) { - c.setTimeout(conversionService.convert(argMap.get(ARGUMENT_TIMEOUT),Integer.class)); - } - if (argMap.containsKey(ARGUMENT_FLUSH_MODE)) { - c.setFlushMode(convertFlushMode(argMap.get(ARGUMENT_FLUSH_MODE))); - } - if (argMap.containsKey(ARGUMENT_READ_ONLY)) { - c.setReadOnly(GrailsClassUtils.getBooleanFromMap(ARGUMENT_READ_ONLY, argMap)); - } - String orderParam = (String)argMap.get(ARGUMENT_ORDER); - Object fetchObj = argMap.get(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(ARGUMENT_LOCK, argMap)) { - c.setLockMode(LockMode.PESSIMISTIC_WRITE); - c.setCacheable(false); - } - else { - if (argMap.containsKey(ARGUMENT_CACHE)) { - c.setCacheable(GrailsClassUtils.getBooleanFromMap(ARGUMENT_CACHE, argMap)); - } else { - cacheCriteriaByMapping(targetClass, c); - } - } - - final Object sortObj = argMap.get(ARGUMENT_SORT); - if (sortObj != null) { - boolean ignoreCase = true; - Object caseArg = argMap.get(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 = ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? ORDER_DESC : ORDER_ASC; - addOrderPossiblyNested(grailsApplication, c, targetClass, (String) sort, order, ignoreCase); - } - } else { - final String sort = (String) sortObj; - final String order = ORDER_DESC.equalsIgnoreCase(orderParam) ? ORDER_DESC : ORDER_ASC; - addOrderPossiblyNested(grailsApplication, c, targetClass, sort, order, ignoreCase); - } - } - Mapping m = binder.getMapping(targetClass); - if (m != null) { - Map sortMap = m.getSort().getNamesAndDirections(); - for (Object sort : sortMap.keySet()) { - final String order = ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? ORDER_DESC : ORDER_ASC; - addOrderPossiblyNested(grailsApplication, c, targetClass, (String) sort, order, true); - } - } - } - - private static FlushMode convertFlushMode(Object object) { - if (object == null) { - return null; - } - if (object instanceof FlushMode) { - return (FlushMode)object; - } - return FlushMode.valueOf(String.valueOf(object)); - } - - /** - * Populates criteria arguments for the given target class and arguments map - * - * @param targetClass The target class - * @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 - @SuppressWarnings("rawtypes") - public static void populateArgumentsForCriteria(Class targetClass, Criteria c, Map argMap, ConversionService conversionService) { - populateArgumentsForCriteria(null, targetClass, c, argMap, conversionService); - } - - /** - * Add order to criteria, creating necessary subCriteria if nested sort property (ie. sort:'nested.property'). - */ - private static void addOrderPossiblyNested(GrailsApplication grailsApplication, Criteria c, Class targetClass, 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); - GrailsDomainClassProperty property = getGrailsDomainClassProperty(grailsApplication, targetClass, sortHead); - if (property.isEmbedded()) { - // embedded objects cannot reference entities (at time of writing), so no more recursion needed - addOrder(c, sort, order, ignoreCase); - } else { - Criteria subCriteria = c.createCriteria(sortHead); - Class propertyTargetClass = property.getReferencedDomainClass().getClazz(); - GrailsHibernateUtil.cacheCriteriaByMapping(grailsApplication, propertyTargetClass, subCriteria); - addOrderPossiblyNested(grailsApplication, subCriteria, propertyTargetClass, sortTail, order, ignoreCase); // Recurse on nested sort - } - } - } - - /** - * Add order directly to criteria. - */ - private static void addOrder(Criteria c, String sort, String order, boolean ignoreCase) { - if (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)); - } - } - - /** - * Get hold of the GrailsDomainClassProperty represented by the targetClass' propertyName, - * assuming targetClass corresponds to a GrailsDomainClass. - */ - private static GrailsDomainClassProperty getGrailsDomainClassProperty(GrailsApplication grailsApplication, Class targetClass, String propertyName) { - GrailsClass grailsClass = grailsApplication != null ? grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, targetClass.getName()) : null; - if (!(grailsClass instanceof GrailsDomainClass)) { - throw new IllegalArgumentException("Unexpected: class is not a domain class:"+targetClass.getName()); - } - GrailsDomainClass domainClass = (GrailsDomainClass) grailsClass; - return domainClass.getPropertyByName(propertyName); - } - - /** - * Configures the criteria instance to cache based on the configured mapping. - * - * @param targetClass The target class - * @param criteria The criteria - */ - public static void cacheCriteriaByMapping(Class targetClass, Criteria criteria) { - Mapping m = binder.getMapping(targetClass); - if (m != null && m.getCache() != null && m.getCache().getEnabled()) { - criteria.setCacheable(true); - } - } - - public static void cacheCriteriaByMapping(GrailsApplication grailsApplication, - Class targetClass, Criteria criteria) { - cacheCriteriaByMapping(targetClass, criteria); - } - - @SuppressWarnings("rawtypes") - public static void populateArgumentsForCriteria(Criteria c, Map argMap, ConversionService conversionService) { - populateArgumentsForCriteria(null,null, c, argMap, conversionService); - } - - /** - * 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; - } - - /** - * Sets the target object to read-only using the given SessionFactory instance. This - * avoids Hibernate performing any dirty checking on the object - * - * @see #setObjectToReadWrite(Object, org.hibernate.SessionFactory) - * - * @param target The target object - * @param sessionFactory The SessionFactory instance - */ - public static void setObjectToReadyOnly(Object target, SessionFactory sessionFactory) { - Session session = sessionFactory.getCurrentSession(); - if (canModifyReadWriteState(session, target)) { - if (target instanceof HibernateProxy) { - target = ((HibernateProxy)target).getHibernateLazyInitializer().getImplementation(); - } - session.setReadOnly(target, true); - session.setFlushMode(FlushMode.MANUAL); - } - } - - private static boolean canModifyReadWriteState(Session session, Object target) { - return session.contains(target) && Hibernate.isInitialized(target); - } - - /** - * Sets the target object to read-write, allowing Hibernate to dirty check it and auto-flush changes. - * - * @see #setObjectToReadyOnly(Object, org.hibernate.SessionFactory) - * - * @param target The target object - * @param sessionFactory The SessionFactory instance - */ - public static void setObjectToReadWrite(final Object target, SessionFactory sessionFactory) { - Session session = sessionFactory.getCurrentSession(); - if (!canModifyReadWriteState(session, target)) { - return; - } - - SessionImplementor sessionImpl = (SessionImplementor) session; - EntityEntry ee = sessionImpl.getPersistenceContext().getEntry(target); - - if (ee == null || ee.getStatus() != Status.READ_ONLY) { - return; - } - - Object actualTarget = target; - if (target instanceof HibernateProxy) { - actualTarget = ((HibernateProxy)target).getHibernateLazyInitializer().getImplementation(); - } - - session.setReadOnly(actualTarget, false); - session.setFlushMode(FlushMode.AUTO); - incrementVersion(target); - } - - /** - * Increments the entities version number in order to force an update - * @param target The target entity - */ - public static void incrementVersion(Object target) { - MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(target.getClass()); - if (metaClass.hasProperty(target, GrailsDomainClassProperty.VERSION)!=null) { - Object version = metaClass.getProperty(target, GrailsDomainClassProperty.VERSION); - if (version instanceof Long) { - Long newVersion = (Long) version + 1; - metaClass.setProperty(target, GrailsDomainClassProperty.VERSION, newVersion); - } - } - } - - /** - * Ensures the meta class is correct for a given class - * - * @param target The GroovyObject - * @param persistentClass The persistent class - */ - public 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)); - } - } - } - - /** - * Unwraps and initializes a HibernateProxy. - * @param proxy The proxy - * @return the unproxied instance - */ - public static Object unwrapProxy(HibernateProxy proxy) { - return proxyHandler.unwrapProxy(proxy); - } - - /** - * Returns the proxy for a given association or null if it is not proxied - * - * @param obj The object - * @param associationName The named assoication - * @return A proxy - */ - public static HibernateProxy getAssociationProxy(Object obj, String associationName) { - return proxyHandler.getAssociationProxy(obj, associationName); - } - - /** - * Checks whether an associated property is initialized and returns true if it is - * - * @param obj The name of the object - * @param associationName The name of the association - * @return true if is initialized - */ - public static boolean isInitialized(Object obj, String associationName) { - return proxyHandler.isInitialized(obj, associationName); - } - - public static boolean isCacheQueriesByDefault() { - return isCacheQueriesByDefault(GrailsWebUtil.currentApplication()); - } - - public static boolean isCacheQueriesByDefault(GrailsApplication grailsApplication) { - return GrailsConfigUtils.isConfigTrue(grailsApplication, CONFIG_PROPERTY_CACHE_QUERIES); - } - - public static boolean isOsivReadonly(GrailsApplication grailsApplication) { - return GrailsConfigUtils.isConfigTrue(grailsApplication, CONFIG_PROPERTY_OSIV_READONLY); - } - - public static GroovyAwareJavassistProxyFactory buildProxyFactory(PersistentClass persistentClass) { - GroovyAwareJavassistProxyFactory proxyFactory = new GroovyAwareJavassistProxyFactory(); - - @SuppressWarnings("unchecked") - Set> proxyInterfaces = CollectionUtils.newSet(HibernateProxy.class); - - final Class javaClass = persistentClass.getMappedClass(); - final Property identifierProperty = persistentClass.getIdentifierProperty(); - final Getter idGetter = identifierProperty!=null? identifierProperty.getGetter(javaClass) : null; - final Setter idSetter = identifierProperty!=null? identifierProperty.getSetter(javaClass) : null; - - if (idGetter == null || idSetter == null) return null; - - try { - proxyFactory.postInstantiate(persistentClass.getEntityName(), javaClass, proxyInterfaces, - idGetter.getMethod(), idSetter.getMethod(), - persistentClass.hasEmbeddedIdentifier() ? - (CompositeType) persistentClass.getIdentifier().getType() : - null); - } - catch (HibernateException e) { - LOG.warn("Cannot instantiate proxy factory: " + e.getMessage()); - return null; - } - - return proxyFactory; - } - - public static Object unwrapIfProxy(Object instance) { - return proxyHandler.unwrapIfProxy(instance); - } - - public static boolean usesDatasource(GrailsDomainClass domainClass, String dataSourceName) { - if (domainClass instanceof GrailsHibernateDomainClass) { - GrailsHibernateDomainClass hibernateDomainClass = (GrailsHibernateDomainClass)domainClass; - String sessionFactoryName = hibernateDomainClass.getSessionFactoryName(); - if (dataSourceName.equals(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE)) { - return "sessionFactory".equals(sessionFactoryName); - } - return sessionFactoryName.endsWith("_" + dataSourceName); - } - - List names = getDatasourceNames(domainClass); - return names.contains(dataSourceName) || - names.contains(GrailsDomainClassProperty.ALL_DATA_SOURCES); - } - - /** - * If a domain class uses more than one datasource, we need to know which one to use - * when calling a method without a namespace qualifier. - * - * @param domainClass the domain class - * @return the default datasource name - */ - public static String getDefaultDataSource(GrailsDomainClass domainClass) { - if (domainClass instanceof GrailsHibernateDomainClass) { - GrailsHibernateDomainClass hibernateDomainClass = (GrailsHibernateDomainClass)domainClass; - String sessionFactoryName = hibernateDomainClass.getSessionFactoryName(); - if ("sessionFactory".equals(sessionFactoryName)) { - return GrailsDomainClassProperty.DEFAULT_DATA_SOURCE; - } - return sessionFactoryName.substring("sessionFactory_".length()); - } - - List names = getDatasourceNames(domainClass); - if (names.size() == 1 && GrailsDomainClassProperty.ALL_DATA_SOURCES.equals(names.get(0))) { - return GrailsDomainClassProperty.DEFAULT_DATA_SOURCE; - } - return names.get(0); - } - - public static List getDatasourceNames(GrailsDomainClass domainClass) { - // Mappings won't have been built yet when this is called from - // HibernatePluginSupport.doWithSpring so do a temporary evaluation but don't cache it - Mapping mapping = isMappedWithHibernate(domainClass) ? binder.evaluateMapping(domainClass, null, false) : null; - if (mapping == null) { - mapping = new Mapping(); - } - return mapping.getDatasources(); - } - - public static boolean isMappedWithHibernate(GrailsDomainClass domainClass) { - return domainClass instanceof GrailsHibernateDomainClass || domainClass.getMappingStrategy().equals( GrailsDomainClass.GORM ); - } - - public static void autoAssociateBidirectionalOneToOnes(DefaultGrailsDomainClass domainClass, Object target) { - List associations = domainClass.getAssociations(); - for (GrailsDomainClassProperty association : associations) { - if (association.isOneToOne() && association.isBidirectional() && association.isOwningSide()) { - if (isInitialized(target, association.getName())) { - GrailsDomainClassProperty otherSide = association.getOtherSide(); - if (otherSide != null) { - BeanWrapper bean = new BeanWrapperImpl(target); - Object inverseObject = bean.getPropertyValue(association.getName()); - if (inverseObject != null) { - if (isInitialized(inverseObject,otherSide.getName())) { - BeanWrapper inverseBean = new BeanWrapperImpl(inverseObject); - Object propertyValue = inverseBean.getPropertyValue(otherSide.getName()); - if (propertyValue == null) { - inverseBean.setPropertyValue(otherSide.getName(), target); - } - } - } - } - } - } - } - } - - public static String qualify(final String prefix, final String name) { - return StringHelper.qualify(prefix, name); - } - - public static boolean isNotEmpty(final String string) { - return StringHelper.isNotEmpty(string); - } - - public static String unqualify(final String qualifiedName) { - return StringHelper.unqualify(qualifiedName); - } -} 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 deleted file mode 100644 index bff64bf10..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/HibernateUtils.groovy +++ /dev/null @@ -1,364 +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.cfg - -import grails.artefact.Enhanced -import grails.util.GrailsNameUtils -import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode - -import org.apache.commons.beanutils.PropertyUtils -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 -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.plugins.DomainClassGrailsPlugin -import org.codehaus.groovy.runtime.InvokerHelper -import org.codehaus.groovy.runtime.StringGroovyMethods -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.hibernate.FlushMode -import org.hibernate.Session -import org.hibernate.SessionFactory -import org.hibernate.proxy.HibernateProxy -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.context.ApplicationContext -import org.springframework.core.convert.ConversionService -import org.springframework.dao.DataAccessException -import org.springframework.transaction.PlatformTransactionManager - -@CompileStatic -class HibernateUtils { - - static final Logger LOG = LoggerFactory.getLogger(HibernateUtils) - - /** - * Overrides a getter on a property that is a Hibernate proxy in order to make sure the initialized object is returned hence avoiding Hibernate proxy hell. - */ - static void handleLazyProxy(GrailsDomainClass domainClass, GrailsDomainClassProperty property) { - String propertyName = property.name - String getterName = GrailsClassUtils.getGetterName(propertyName) - String setterName = GrailsClassUtils.getSetterName(propertyName) - - GroovyObject mc = (GroovyObject)domainClass.metaClass - - mc.setProperty(getterName, {-> - def propertyValue = PropertyUtils.getProperty(getDelegate(), propertyName) - if (propertyValue instanceof HibernateProxy) { - propertyValue = GrailsHibernateUtil.unwrapProxy(propertyValue) - } - return propertyValue - }) - mc.setProperty(setterName, { PropertyUtils.setProperty(getDelegate(), propertyName, it) }) - - for (GrailsDomainClass sub in domainClass.subClasses) { - handleLazyProxy(sub, sub.getPropertyByName(property.name)) - } - } - - static void enhanceSessionFactories(ApplicationContext ctx, GrailsApplication grailsApplication, Object source = null) { - - Map datastores = [:] - - for (entry in ctx.getBeansOfType(SessionFactory).entrySet()) { - SessionFactory sessionFactory = entry.value - String beanName = entry.key - String suffix = beanName - 'sessionFactory' - enhanceSessionFactory sessionFactory, grailsApplication, ctx, suffix, datastores, source - } - - ctx.getBean("eventTriggeringInterceptor", ClosureEventTriggeringInterceptor).datastores = datastores - } - - static enhanceSessionFactory(SessionFactory sessionFactory, GrailsApplication application, ApplicationContext ctx) { - enhanceSessionFactory(sessionFactory, application, ctx, '', [:]) - } - - static enhanceSessionFactory(SessionFactory sessionFactory, GrailsApplication application, - ApplicationContext ctx, String suffix, Map datastores, Object source = null) { - - MappingContext mappingContext = ctx.getBean("grailsDomainClassMappingContext", MappingContext) - PlatformTransactionManager transactionManager = ctx.getBean("transactionManager$suffix", PlatformTransactionManager) - HibernateDatastore datastore = (HibernateDatastore)ctx.getBean("hibernateDatastore$suffix", Datastore) - datastores[sessionFactory] = datastore - String datasourceName = suffix ? suffix[1..-1] : GrailsDomainClassProperty.DEFAULT_DATA_SOURCE - - HibernateGormEnhancer enhancer = new HibernateGormEnhancer(datastore, transactionManager, application) - - def enhanceEntity = { PersistentEntity entity -> - GrailsDomainClass dc = (GrailsDomainClass)application.getArtefact(DomainClassArtefactHandler.TYPE, entity.javaClass.name) - if (!GrailsHibernateUtil.isMappedWithHibernate(dc) || !GrailsHibernateUtil.usesDatasource(dc, datasourceName)) { - return - } - - if (!datasourceName.equals(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE)) { - LOG.debug "Registering namespace methods for $dc.clazz.name in DataSource '$datasourceName'" - registerNamespaceMethods dc, datastore, datasourceName, transactionManager, application - } - - if (datasourceName.equals(GrailsDomainClassProperty.DEFAULT_DATA_SOURCE) || datasourceName.equals(GrailsHibernateUtil.getDefaultDataSource(dc))) { - LOG.debug "Enhancing GORM entity ${entity.name}" - if (entity.javaClass.getAnnotation(Enhanced) == null) { - enhancer.enhance entity - } - else { - enhancer.enhance entity, true - } - - DomainClassGrailsPlugin.addRelationshipManagementMethods(dc, ctx) - } - } - - // If we are reloading via an onChange event, the source indicates the specific - // entity that needs to be reloaded. Otherwise, just reload all of them. - if (source) { - PersistentEntity entity = getPersistentEntity(mappingContext, InvokerHelper.getPropertySafe(source, 'name')?.toString()) - if (entity) { - enhanceEntity(entity) - } - } - else { - for (PersistentEntity entity in mappingContext.getPersistentEntities()) { - enhanceEntity(entity) - } - } - } - - // workaround CS bug - @CompileStatic(TypeCheckingMode.SKIP) - private static PersistentEntity getPersistentEntity(mappingContext, String name) { - mappingContext.getPersistentEntity(name) - } - - static 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 - } - - private static List removeNullNames(Map query) { - List nullNames = [] - Set allNames = new HashSet(query.keySet()) - for (String name in allNames) { - if (query[name] == null) { - query.remove name - nullNames << name - } - } - nullNames - } - - // 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) - if (grailsEnhancedMetaMethod != null && grailsEnhancedMetaMethod.invoke(proxyClass, null) == proxyClass) { - return - } - - MetaClass mc = (MetaClass)InvokerHelper.getMetaClass(proxyClass) - MetaClass superMc = InvokerHelper.getMetaClass(proxyClass.getSuperclass()) - - // hasProperty - registerMetaMethod(mc, 'hasProperty', { String name -> - Object obj = getDelegate() - boolean result = superMc.hasProperty(obj, name) - if (!result) { - Object unwrapped = GrailsHibernateUtil.unwrapProxy((HibernateProxy)obj) - result = unwrapped.getMetaClass().hasProperty(obj, name) - } - return result - }) - // respondsTo - registerMetaMethod(mc, 'respondsTo', { String name -> - Object obj = getDelegate() - def result = superMc.respondsTo(obj, name) - if (!result) { - Object unwrapped = GrailsHibernateUtil.unwrapProxy((HibernateProxy)obj) - result = unwrapped.getMetaClass().respondsTo(obj, name) - } - result - }) - registerMetaMethod(mc, 'respondsTo', { String name, Object[] args -> - Object obj = getDelegate() - def result = superMc.respondsTo(obj, name, args) - if (!result) { - Object unwrapped = GrailsHibernateUtil.unwrapProxy((HibernateProxy)obj) - result = unwrapped.getMetaClass().respondsTo(obj, name, args) - } - result - }) - - // setter - registerMetaMethod(mc, 'propertyMissing', { String name, Object val -> - Object obj = getDelegate() - try { - superMc.setProperty(proxyClass, obj, name, val, true, true) - } catch (MissingPropertyException e) { - Object unwrapped = GrailsHibernateUtil.unwrapProxy((HibernateProxy)obj) - unwrapped.getMetaClass().setProperty(unwrapped, name, val) - } - }) - - // getter - registerMetaMethod(mc, 'propertyMissing', { String name -> - Object obj = getDelegate() - try { - return superMc.getProperty(proxyClass, obj, name, true, true) - } catch (MissingPropertyException e) { - Object unwrapped = GrailsHibernateUtil.unwrapProxy((HibernateProxy)obj) - unwrapped.getMetaClass().getProperty(unwrapped, name) - } - }) - - registerMetaMethod(mc, 'methodMissing', { String name, Object args -> - Object obj = getDelegate() - Object[] argsArray = (Object[])args - try { - superMc.invokeMethod(proxyClass, obj, name, argsArray, true, true) - } catch (MissingMethodException e) { - Object unwrapped = GrailsHibernateUtil.unwrapProxy((HibernateProxy)obj) - unwrapped.getMetaClass().invokeMethod(unwrapped, name, argsArray) - } - }) - - mc.static.grailsEnhanced = {->proxyClass} - } - - - @CompileStatic(TypeCheckingMode.SKIP) - private static final registerMetaMethod(MetaClass mc, String name, Closure c) { - mc."$name" = c - } - - static void enhanceProxy(HibernateProxy proxy) { - // no need to do anything here - } - - private static void registerNamespaceMethods(GrailsDomainClass dc, HibernateDatastore datastore, - String datasourceName, PlatformTransactionManager transactionManager, - GrailsApplication application) { - - String getter = GrailsNameUtils.getGetterName(datasourceName) - if (dc.metaClass.methods.any { MetaMethod it -> it.name == getter && it.parameterTypes.size() == 0 }) { - LOG.warn "The $dc.clazz.name domain class has a method '$getter' - unable to add namespaced methods for datasource '$datasourceName'" - return - } - - def classLoader = application.classLoader - - def finders = new HibernateGormEnhancer(datastore, transactionManager, application).getFinders() - def staticApi = new HibernateGormStaticApi(dc.clazz, datastore, finders, classLoader, transactionManager) - ((GroovyObject)((GroovyObject)dc.metaClass).getProperty('static')).setProperty(getter, { -> staticApi }) - - def validateApi = new HibernateGormValidationApi(dc.clazz, datastore, classLoader) - def instanceApi = new HibernateGormInstanceApi(dc.clazz, datastore, classLoader) - ((GroovyObject)dc.metaClass).setProperty(getter, { -> new InstanceProxy(getDelegate(), instanceApi, validateApi) }) - } - - /** - * Session should no longer be flushed after a data access exception occurs (such a constriant violation) - */ - static void handleDataAccessException(GrailsHibernateTemplate template, DataAccessException e) { - try { - template.execute new GrailsHibernateTemplate.HibernateCallback() { - def doInHibernate(Session session) { - session.setFlushMode(FlushMode.MANUAL) - } - } - } - finally { - throw e - } - } - - static shouldFlush(GrailsApplication application, Map map = [:]) { - def shouldFlush - - if (map?.containsKey('flush')) { - shouldFlush = Boolean.TRUE == map.flush - } else { - def config = application.flatConfig - shouldFlush = Boolean.TRUE == config.get('grails.gorm.autoFlush') - } - return shouldFlush - } - - /** - * Converts an id value to the appropriate type for a domain class. - * - * @param grailsDomainClass a GrailsDomainClass - * @param idValue an value to be converted - * @return the idValue parameter converted to the type that grailsDomainClass expects - * its identifiers to be - */ - static Object convertValueToIdentifierType(GrailsDomainClass grailsDomainClass, Object idValue, ConversionService conversionService) { - convertValueToType(idValue, grailsDomainClass.identifier.type, conversionService) - } - - 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-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/IdentityEnumType.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/IdentityEnumType.java deleted file mode 100644 index 3d7f69239..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/cfg/IdentityEnumType.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * 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.cfg; - -import grails.util.GrailsWebUtil; - -import java.io.Serializable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Collections; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import org.hibernate.HibernateException; -import org.hibernate.MappingException; -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.type.AbstractStandardBasicType; -import org.hibernate.type.TypeResolver; -import org.hibernate.usertype.ParameterizedType; -import org.hibernate.usertype.UserType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Hibernate Usertype that enum values by their ID. - * - * @author Siegfried Puchbauer - * @since 1.1 - */ -public class IdentityEnumType implements UserType, ParameterizedType, Serializable { - - private static final long serialVersionUID = -6625622185856547501L; - - private static final Logger LOG = LoggerFactory.getLogger(IdentityEnumType.class); - - private static TypeResolver typeResolver = new TypeResolver(); - public static final String ENUM_ID_ACCESSOR = "getId"; - - public static final String PARAM_ENUM_CLASS = "enumClass"; - - private static final Map>, BidiEnumMap> ENUM_MAPPINGS = new HashMap>, BidiEnumMap>(); - private Class> enumClass; - private BidiEnumMap bidiMap; - private AbstractStandardBasicType type; - private int[] sqlTypes; - - public static BidiEnumMap getBidiEnumMap(Class> cls) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - BidiEnumMap m = ENUM_MAPPINGS.get(cls); - if (m == null) { - synchronized (ENUM_MAPPINGS) { - if (!ENUM_MAPPINGS.containsKey(cls)) { - m = new BidiEnumMap(cls); - ENUM_MAPPINGS.put(cls, m); - } - else { - m = ENUM_MAPPINGS.get(cls); - } - } - } - return m; - } - - public static boolean isEnabled() { - Object disableConfigOption = GrailsWebUtil.currentFlatConfiguration().get("grails.orm.enum.id.mapping"); - return disableConfigOption == null || !(Boolean.FALSE.equals(disableConfigOption)); - } - - @SuppressWarnings("unchecked") - public static boolean supports(@SuppressWarnings("rawtypes") Class enumClass) { - if (!isEnabled()) return false; - if (enumClass.isEnum()) { - try { - Method idAccessor = enumClass.getMethod(ENUM_ID_ACCESSOR); - int mods = idAccessor.getModifiers(); - if (Modifier.isPublic(mods) && !Modifier.isStatic(mods)) { - Class returnType = idAccessor.getReturnType(); - return returnType != null && typeResolver.basic(returnType.getName()) instanceof AbstractStandardBasicType; - } - } - catch (NoSuchMethodException e) { - // ignore - } - } - return false; - } - - @SuppressWarnings("unchecked") - public void setParameterValues(Properties properties) { - try { - enumClass = (Class>)Thread.currentThread().getContextClassLoader().loadClass( - (String)properties.get(PARAM_ENUM_CLASS)); - if (LOG.isDebugEnabled()) { - LOG.debug(String.format("Building ID-mapping for Enum Class %s", enumClass.getName())); - } - bidiMap = getBidiEnumMap(enumClass); - type = (AbstractStandardBasicType)typeResolver.basic(bidiMap.keyType.getName()); - if (LOG.isDebugEnabled()) { - LOG.debug(String.format("Mapped Basic Type is %s", type)); - } - sqlTypes = type.sqlTypes(null); - } - catch (Exception e) { - throw new MappingException("Error mapping Enum Class using IdentifierEnumType", e); - } - } - - public int[] sqlTypes() { - return sqlTypes; - } - - public Class returnedClass() { - return enumClass; - } - - public boolean equals(Object o1, Object o2) throws HibernateException { - return o1 == o2; - } - - public int hashCode(Object o) throws HibernateException { - return o.hashCode(); - } - - public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor session, Object owner) throws SQLException { - Object id = type.nullSafeGet(resultSet, names[0], session); - if ((!resultSet.wasNull()) && id != null) { - return bidiMap.getEnumValue(id); - } - return null; - } - - public void nullSafeSet(PreparedStatement pstmt, Object value, int idx, SessionImplementor session) throws SQLException { - if (value == null) { - pstmt.setNull(idx, sqlTypes[0]); - } - else { - type.nullSafeSet(pstmt, bidiMap.getKey(value), idx, session); - } - } - - public Object deepCopy(Object o) throws HibernateException { - return o; - } - - public boolean isMutable() { - return false; - } - - public Serializable disassemble(Object o) throws HibernateException { - return (Serializable) o; - } - - public Object assemble(Serializable cached, Object owner) throws HibernateException { - return cached; - } - - public Object replace(Object orig, Object target, Object owner) throws HibernateException { - return orig; - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - private static class BidiEnumMap implements Serializable { - - private static final long serialVersionUID = 3325751131102095834L; - private final Map enumToKey; - private final Map keytoEnum; - private Class keyType; - - private BidiEnumMap(Class enumClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - if (LOG.isDebugEnabled()) { - LOG.debug(String.format("Building Bidirectional Enum Map...")); - } - - EnumMap enumToKey = new EnumMap(enumClass); - HashMap keytoEnum = new HashMap(); - - Method idAccessor = enumClass.getMethod(ENUM_ID_ACCESSOR); - - keyType = idAccessor.getReturnType(); - - Method valuesAccessor = enumClass.getMethod("values"); - Object[] values = (Object[]) valuesAccessor.invoke(enumClass); - - for (Object value : values) { - Object id = idAccessor.invoke(value); - enumToKey.put((Enum) value, id); - if (keytoEnum.containsKey(id)) { - LOG.warn(String.format("Duplicate Enum ID '%s' detected for Enum %s!", id, enumClass.getName())); - } - keytoEnum.put(id, value); - } - - this.enumToKey = Collections.unmodifiableMap(enumToKey); - this.keytoEnum = Collections.unmodifiableMap(keytoEnum); - } - - public Object getEnumValue(Object id) { - return keytoEnum.get(id); - } - - public Object getKey(Object enumValue) { - return enumToKey.get(enumValue); - } - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/events/PatchedDefaultFlushEventListener.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/events/PatchedDefaultFlushEventListener.java deleted file mode 100644 index a72a0b3fb..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/events/PatchedDefaultFlushEventListener.java +++ /dev/null @@ -1,58 +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.events; - -import org.hibernate.HibernateException; -import org.hibernate.event.internal.DefaultFlushEventListener; -import org.hibernate.event.spi.EventSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Patches Hibernate to prevent this issue - * http://opensource.atlassian.com/projects/hibernate/browse/HHH-2763 - * - * TODO: Remove this patch when HHH-2763 is resolved - * - * @author Graeme Rocher - * @since 1.2 - */ -public class PatchedDefaultFlushEventListener extends DefaultFlushEventListener{ - - private static final long serialVersionUID = -7413770767669684078L; - private static final Logger LOG = LoggerFactory.getLogger(PatchedDefaultFlushEventListener.class); - - @Override - protected void performExecutions(EventSource session) throws HibernateException { - session.getPersistenceContext().setFlushing(true); - try { - session.getTransactionCoordinator().getJdbcCoordinator().flushBeginning(); - // we need to lock the collection caches before - // executing entity inserts/updates in order to - // account for bidi associations - session.getActionQueue().prepareActions(); - session.getActionQueue().executeActions(); - } - catch (HibernateException he) { - LOG.error("Could not synchronize database state with session", he); - throw he; - } - finally { - session.getPersistenceContext().setFlushing(false); - session.getTransactionCoordinator().getJdbcCoordinator().flushEnding(); - } - } -} 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 a3f4bee5e..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractClausedStaticPersistentMethod.java +++ /dev/null @@ -1,538 +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 java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Locale; -import java.util.regex.Matcher; -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.commons.GrailsDomainClassProperty; -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.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.TypeMismatchException; -import org.springframework.core.convert.ConversionService; -import org.springframework.util.Assert; - -/** - * @author Graeme Rocher - * @since 31-Aug-2005 - */ -public abstract class AbstractClausedStaticPersistentMethod extends AbstractStaticPersistentMethod { - - private static final Logger LOG = LoggerFactory.getLogger(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++) { - if (args[i] == null) continue; - // convert GStrings to strings - if (prop.getType() == String.class && (args[i] instanceof CharSequence)) { - args[i] = args[i].toString(); - } - else if (!prop.getType().isAssignableFrom(args[i].getClass()) && !(GrailsClassUtils.isMatchBetweenPrimativeAndWrapperTypes(prop.getType(), args[i].getClass()))) { - try { - if (type.equals(IN_LIST)) { - args[i] = conversionService.convert(args[i], Collection.class); - } - else { - args[i] = conversionService.convert(args[i], 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(args[i].getClass())) { - try { - args[i] = conversionService.convert(args[i].toString(), prop.getType()); - } - catch(TypeMismatchException tme1) { - throw new IllegalArgumentException("Cannot convert value " + args[i] + " of property '"+propertyName+"' to required type " + prop.getType() + ": " + tme1.getMessage()); - } - } - else { - throw new IllegalArgumentException("Cannot convert value " + args[i] + " of property '"+propertyName+"' to required type " + prop.getType()); - } - } - } - } - - arguments = args; - } - - 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) { - super(sessionFactory, classLoader, pattern, application); - 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 expressions = new ArrayList(); - 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 9757d1f50..000000000 --- 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; - - public AbstractDynamicPersistentMethod(Pattern pattern, SessionFactory sessionFactory, ClassLoader classLoader, GrailsApplication application) { - 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); - } - - 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. Note that the binding errors - * will no longer be flagged as binding errors - * - * @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 fc60ea0d2..000000000 --- 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 useLimitCache = new ConcurrentHashMap(); - - public AbstractFindByPersistentMethod(HibernateDatastore datastore, GrailsApplication application, - SessionFactory sessionFactory, ClassLoader classLoader, - Pattern pattern, String[] operators) { - super(application, sessionFactory, classLoader, pattern, operators, datastore.getMappingContext().getConversionService()); - 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() { - 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 8dfa7d8f3..000000000 --- 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> disableAutoValidationFor = new ThreadLocal>(); - - static { - ShutdownOperations.addOperation(new Runnable() { - public void run() { - disableAutoValidationFor.remove(); - } - }); - } - - private static Set getDisableAutoValidationFor() { - Set identifiers = disableAutoValidationFor.get(); - if (identifiers == null) - disableAutoValidationFor.set(identifiers = new HashSet()); - return identifiers; - } - - public static boolean isAutoValidationDisabled(Object obj) { - Set 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); - - 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 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 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 2d803ac96..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/AbstractStaticPersistentMethod.java +++ /dev/null @@ -1,120 +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) { - 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); - } - - 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()); - 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 30a107d01..000000000 --- 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()); - 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() { - 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)expressions) { - dis.add(current.getCriterion()); - } - crit.add(dis); - } - else { - for (GrailsMethodExpression current : (List)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 f1ecff172..000000000 --- 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. - *

    - * 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 http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html - * @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 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) { - super(sessionFactory, classLoader, METHOD_PATTERN, application); - 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() { - 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 04c61241b..000000000 --- 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. - *

    - * 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) { - super(sessionFactory, classLoader, METHOD_PATTERN, application); - } - - @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)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 985fe1eac..000000000 --- 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 "findAllBy*" 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 58832ca79..000000000 --- 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()); - 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() { - 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 18ac70b66..000000000 --- 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; - -/** - *

    - * 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. - *

    - * Syntax: - * DomainClass.findAll(query, params?) - * DomainClass.findAll(query, params?, max) - * DomainClass.findAll(query, params?, max, offset) - * DomainClass.findAll(query, params?, [max:10, offset:5]) - * - *

    - * Examples in Groovy: - * // 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) - * - * - * - * @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) { - super(sessionFactory, classLoader, Pattern.compile("^findAll$"), application); - 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() { - 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() { - 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() { - 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 c0ee00c66..000000000 --- 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 "findBy*" 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 b2c5a9588..000000000 --- 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 0065135d0..000000000 --- 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 c1dad7dc5..000000000 --- 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 ea7271732..000000000 --- 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; - -/** - *

    - * 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. - * - *

    - * Examples in Groovy: - * // 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) - * - * - * - * @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) { - super(sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), application); - 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() { - 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() { - 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 6296d5150..000000000 --- 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); - 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() { - 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 b7360a1e1..000000000 --- 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) { - super(sessionFactory, classLoader, Pattern.compile(METHOD_PATTERN), grailsApplication); - 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() { - 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 4b3131242..000000000 --- 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() { - 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 c05b0ed85..000000000 --- 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() { - 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() { - 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 31b598383..000000000 --- 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); - 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-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/persister/entity/GroovyAwareJoinedSubclassEntityPersister.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/persister/entity/GroovyAwareJoinedSubclassEntityPersister.java deleted file mode 100644 index e66892d29..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/persister/entity/GroovyAwareJoinedSubclassEntityPersister.java +++ /dev/null @@ -1,57 +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.persister.entity; - -import java.io.Serializable; - -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwareJavassistProxyFactory; -import org.hibernate.HibernateException; -import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; -import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; -import org.hibernate.engine.spi.Mapping; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.persister.entity.JoinedSubclassEntityPersister; - -/** - * A customized EntityPersister that creates proxies valid for use with Groovy. - * - * @author Graeme Rocher - * @since 1.1.1 - */ -public class GroovyAwareJoinedSubclassEntityPersister extends JoinedSubclassEntityPersister { - - private GroovyAwareJavassistProxyFactory proxyFactory; - - public GroovyAwareJoinedSubclassEntityPersister(PersistentClass persistentClass, - EntityRegionAccessStrategy cacheAccessStrategy, - NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, - SessionFactoryImplementor factory, Mapping mapping) throws HibernateException { - super(persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory, mapping); - proxyFactory = GrailsHibernateUtil.buildProxyFactory(persistentClass); - } - - @Override - public Object createProxy(Serializable id, SessionImplementor session) throws HibernateException { - if (proxyFactory != null) { - return proxyFactory.getProxy(id,session); - } - - return super.createProxy(id, session); - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/persister/entity/GroovyAwareSingleTableEntityPersister.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/persister/entity/GroovyAwareSingleTableEntityPersister.java deleted file mode 100644 index 7cb6658fb..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/persister/entity/GroovyAwareSingleTableEntityPersister.java +++ /dev/null @@ -1,57 +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.persister.entity; - -import java.io.Serializable; - -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwareJavassistProxyFactory; -import org.hibernate.HibernateException; -import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; -import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; -import org.hibernate.engine.spi.Mapping; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.persister.entity.SingleTableEntityPersister; - -/** - * A customized EntityPersister that creates proxies valid for use with Groovy. - * - * @author Graeme Rocher - * @since 1.1.1 - */ -public class GroovyAwareSingleTableEntityPersister extends SingleTableEntityPersister { - - private GroovyAwareJavassistProxyFactory proxyFactory; - - public GroovyAwareSingleTableEntityPersister(PersistentClass persistentClass, - EntityRegionAccessStrategy cacheAccessStrategy, - NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy, - SessionFactoryImplementor factory, Mapping mapping) throws HibernateException { - super(persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory, mapping); - proxyFactory = GrailsHibernateUtil.buildProxyFactory(persistentClass); - } - - @Override - public Object createProxy(Serializable id, SessionImplementor session) throws HibernateException { - if (proxyFactory != null) { - return proxyFactory.getProxy(id,session); - } - - return super.createProxy(id, session); - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwareJavassistLazyInitializer.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwareJavassistLazyInitializer.java deleted file mode 100644 index 37a0229a8..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwareJavassistLazyInitializer.java +++ /dev/null @@ -1,243 +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.proxy; - -import grails.util.CollectionUtils; -import groovy.lang.GroovyObject; - -import java.io.Serializable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import javassist.util.proxy.MethodFilter; -import javassist.util.proxy.MethodHandler; -import javassist.util.proxy.ProxyFactory; -import javassist.util.proxy.ProxyObject; - -import org.codehaus.groovy.grails.orm.hibernate.cfg.HibernateUtils; -import org.grails.datastore.mapping.proxy.GroovyObjectMethodHandler; -import org.hibernate.HibernateException; -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.proxy.HibernateProxy; -import org.hibernate.proxy.pojo.BasicLazyInitializer; -import org.hibernate.proxy.pojo.javassist.SerializableProxy; -import org.hibernate.type.CompositeType; -import org.slf4j.LoggerFactory; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public class GroovyAwareJavassistLazyInitializer extends BasicLazyInitializer implements MethodHandler { - - private static final String WRITE_CLASSES_DIRECTORY = System.getProperty("javassist.writeDirectory"); - - private static final Set GROOVY_METHODS = CollectionUtils.newSet("$getStaticMetaClass"); - - private static final MethodFilter METHOD_FILTERS = new MethodFilter() { - public boolean isHandled(Method m) { - // skip finalize methods - return m.getName().indexOf("super$") == -1 && - !GROOVY_METHODS.contains(m.getName()) && - !(m.getParameterTypes().length == 0 && (m.getName().equals("finalize"))); - } - }; - - private Class[] interfaces; - private boolean constructed = false; - HibernateGroovyObjectMethodHandler groovyObjectMethodHandler; - - protected GroovyAwareJavassistLazyInitializer( - final String entityName, - final Class persistentClass, - final Class[] interfaces, - final Serializable id, - final Method getIdentifierMethod, - final Method setIdentifierMethod, - final CompositeType componentIdType, - final SessionImplementor session, - final boolean overridesEquals) { - super(entityName, persistentClass, id, getIdentifierMethod, setIdentifierMethod, componentIdType, session, overridesEquals); - this.interfaces = interfaces; - } - - public static HibernateProxy getProxy( - final String entityName, - final Class persistentClass, - final Class[] interfaces, - final Method getIdentifierMethod, - final Method setIdentifierMethod, - CompositeType componentIdType, - final Serializable id, - final SessionImplementor session) throws HibernateException { - // note: interface is assumed to already contain HibernateProxy.class - final GroovyAwareJavassistLazyInitializer instance = new GroovyAwareJavassistLazyInitializer( - entityName, persistentClass, interfaces, id, getIdentifierMethod, - setIdentifierMethod, componentIdType, session, ReflectHelper.overridesEquals(persistentClass)); - return createProxyInstance(getProxyFactory(persistentClass, interfaces), instance); - } - - protected static HibernateProxy createProxyInstance(Class proxyClass, - final GroovyAwareJavassistLazyInitializer instance) { - final HibernateProxy proxy; - try { - proxy = (HibernateProxy)proxyClass.newInstance(); - } catch (Exception e) { - throw new HibernateException("Javassist Enhancement failed: " + proxyClass.getName(), e); - } - ((ProxyObject) proxy).setHandler(instance); - instance.groovyObjectMethodHandler = new HibernateGroovyObjectMethodHandler(proxyClass, proxy); - HibernateUtils.enhanceProxy(proxy); - instance.constructed = true; - return proxy; - } - - public static HibernateProxy getProxy( - final Class factory, - final String entityName, - final Class persistentClass, - final Class[] interfaces, - final Method getIdentifierMethod, - final Method setIdentifierMethod, - final CompositeType componentIdType, - final Serializable id, - final SessionImplementor session) throws HibernateException { - - final GroovyAwareJavassistLazyInitializer instance = new GroovyAwareJavassistLazyInitializer( - entityName, persistentClass, interfaces, id, getIdentifierMethod, - setIdentifierMethod, componentIdType, session, ReflectHelper.overridesEquals(persistentClass)); - - return createProxyInstance(factory, instance); - } - - public static Class getProxyFactory(Class persistentClass, Class[] interfaces) throws HibernateException { - // note: interfaces is assumed to already contain HibernateProxy.class - - try { - Set> allInterfaces = new HashSet>(); - if(interfaces != null) { - allInterfaces.addAll(Arrays.asList(interfaces)); - } - allInterfaces.add(GroovyObject.class); - ProxyFactory factory = createProxyFactory(persistentClass, allInterfaces.toArray(new Class[allInterfaces.size()])); - Class proxyClass = factory.createClass(); - HibernateUtils.enhanceProxyClass(proxyClass); - return proxyClass; - } - catch (Throwable t) { - LoggerFactory.getLogger(BasicLazyInitializer.class).error( - "Javassist Enhancement failed: " + persistentClass.getName(), t); - throw new HibernateException("Javassist Enhancement failed: " + persistentClass.getName(), t); - } - } - - private static ProxyFactory createProxyFactory(Class persistentClass, Class[] interfaces) { - ProxyFactory factory = new ProxyFactory(); - factory.setSuperclass(persistentClass); - factory.setInterfaces(interfaces); - factory.setFilter(METHOD_FILTERS); - factory.setUseCache(true); - if (WRITE_CLASSES_DIRECTORY != null) { - factory.writeDirectory = WRITE_CLASSES_DIRECTORY; - } - return factory; - } - - public Object invoke(final Object proxy, final Method thisMethod, final Method proceed, - final Object[] args) throws Throwable { - Object result = groovyObjectMethodHandler.handleInvocation(proxy, thisMethod, args); - if (groovyObjectMethodHandler.wasHandled(result)) { - return result; - } - - if (constructed) { - try { - result = invoke(thisMethod, args, proxy); - } - catch (Throwable t) { - throw new Exception(t.getCause()); - } - if (result == INVOKE_IMPLEMENTATION) { - Object target = getImplementation(); - final Object returnValue; - try { - if (ReflectHelper.isPublic(persistentClass, thisMethod)) { - if (!thisMethod.getDeclaringClass().isInstance(target)) { - throw new ClassCastException(target.getClass().getName()); - } - returnValue = thisMethod.invoke(target, args); - } - else { - if (!thisMethod.isAccessible()) { - thisMethod.setAccessible(true); - } - returnValue = thisMethod.invoke(target, args); - } - return returnValue == target ? proxy : returnValue; - } - catch (InvocationTargetException ite) { - throw ite.getTargetException(); - } - } - return result; - } - - // while constructor is running - if (thisMethod.getName().equals("getHibernateLazyInitializer")) { - return this; - } - - return proceed.invoke(proxy, args); - } - - @Override - protected Object serializableProxy() { - return new SerializableProxy( - getEntityName(), - persistentClass, - interfaces, - getIdentifier(), - false, - getIdentifierMethod, - setIdentifierMethod, - componentIdType); - } - - private static class HibernateGroovyObjectMethodHandler extends GroovyObjectMethodHandler { - private Object target; - private final Object originalSelf; - - public HibernateGroovyObjectMethodHandler(Class proxyClass, Object originalSelf) { - super(proxyClass); - this.originalSelf = originalSelf; - } - - @Override - protected Object resolveDelegate(Object self) { - if (self != originalSelf) { - throw new IllegalStateException("self instance has changed."); - } - if (target == null) { - target = ((HibernateProxy)self).getHibernateLazyInitializer().getImplementation(); - } - return target; - } - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwareJavassistProxyFactory.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwareJavassistProxyFactory.java deleted file mode 100644 index d6b69eb90..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/GroovyAwareJavassistProxyFactory.java +++ /dev/null @@ -1,76 +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.proxy; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.Set; - -import org.hibernate.HibernateException; -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.proxy.HibernateProxy; -import org.hibernate.proxy.ProxyFactory; -import org.hibernate.type.CompositeType; - -/** - * Hibernate's default proxying mechanism proxies Groovy's getMetaClass() method. To avoid this - * we customize the proxying creation proxy here and in #GroovyAwareJavassistLazyInitializer. - * - * @author Graeme Rocher - * @since 1.1.1 - */ -public class GroovyAwareJavassistProxyFactory implements ProxyFactory, Serializable { - - private static final long serialVersionUID = 8959336753472691947L; - protected static final Class[] NO_CLASSES = {}; - private Class persistentClass; - private String entityName; - private Class[] interfaces; - private Method getIdentifierMethod; - private Method setIdentifierMethod; - private CompositeType componentIdType; - private Class factory; - - @SuppressWarnings({"unchecked", "rawtypes"}) - public void postInstantiate( - final String entityName, - final Class persistentClass, - final Set interfaces, - final Method getIdentifierMethod, - final Method setIdentifierMethod, - final CompositeType componentIdType) throws HibernateException { - this.entityName = entityName; - this.persistentClass = persistentClass; - this.interfaces = (Class[])interfaces.toArray(NO_CLASSES); - this.getIdentifierMethod = getIdentifierMethod; - this.setIdentifierMethod = setIdentifierMethod; - this.componentIdType = componentIdType; - factory = GroovyAwareJavassistLazyInitializer.getProxyFactory(persistentClass, this.interfaces); - } - - public HibernateProxy getProxy(Serializable id, SessionImplementor session) throws HibernateException { - return GroovyAwareJavassistLazyInitializer.getProxy( - factory, - entityName, - persistentClass, - interfaces, - getIdentifierMethod, - setIdentifierMethod, - componentIdType, - id, - session); - } -} 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 deleted file mode 100644 index 695a11990..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/proxy/HibernateProxyHandler.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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 java.lang.reflect.InvocationTargetException; - -import org.apache.commons.beanutils.PropertyUtils; -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.codehaus.groovy.grails.support.proxy.EntityProxyHandler; -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. - * - * @author Graeme Rocher - * @since 1.2.2 - */ -public class HibernateProxyHandler implements EntityProxyHandler { - - 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 = PropertyUtils.getProperty(obj, associationName); - return Hibernate.isInitialized(proxy); - } - catch (IllegalAccessException e) { - return false; - } - catch (InvocationTargetException e) { - return false; - } - catch (NoSuchMethodException e) { - return false; - } - } - - 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 = PropertyUtils.getProperty(obj, associationName); - if (proxy instanceof HibernateProxy) { - return (HibernateProxy) proxy; - } - return null; - } - catch (IllegalAccessException e) { - return null; - } - catch (InvocationTargetException e) { - return null; - } - catch (NoSuchMethodException e) { - return null; - } - } - - public boolean isProxy(Object o) { - return (o instanceof HibernateProxy) || (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) { - 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); - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateCriterionAdapter.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateCriterionAdapter.java deleted file mode 100644 index d765f4f86..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateCriterionAdapter.java +++ /dev/null @@ -1,46 +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.codehaus.groovy.grails.orm.hibernate.query; - -import grails.orm.HibernateCriteriaBuilder; -import grails.orm.RlikeExpression; - -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.hibernate.criterion.Criterion; - -/** - * @author Graeme Rocher - * @since 2.0 - */ -public class HibernateCriterionAdapter extends AbstractHibernateCriterionAdapter { - - public HibernateCriterionAdapter(PersistentEntity entity, Query.Criterion criterion, String alias) { - super(entity, criterion, alias); - } - - public HibernateCriterionAdapter(Query.Criterion criterion) { - super(criterion); - } - - protected Criterion createRlikeExpression(String propertyName, String pattern) { - return new RlikeExpression(propertyName, pattern); - } - - protected Object getHibernateDetachedCriteria(QueryableCriteria value) { - return HibernateCriteriaBuilder.getHibernateDetachedCriteria(value); - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateQuery.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateQuery.java deleted file mode 100644 index 0d8f8bf30..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/query/HibernateQuery.java +++ /dev/null @@ -1,113 +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.codehaus.groovy.grails.orm.hibernate.query; - -import grails.orm.HibernateCriteriaBuilder; -import grails.orm.RlikeExpression; - -import java.sql.SQLException; -import java.util.Iterator; -import java.util.List; - -import org.codehaus.groovy.grails.orm.hibernate.AbstractHibernateSession; -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.orm.hibernate.HibernateSession; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.DetachedCriteria; -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.function.SQLFunction; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.internal.CriteriaImpl; -import org.hibernate.persister.entity.PropertyMapping; -import org.hibernate.type.BasicType; -import org.hibernate.type.TypeResolver; - -/** - * Bridges the Query API with the Hibernate Criteria API - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class HibernateQuery extends AbstractHibernateQuery { - - public HibernateQuery(Criteria criteria, AbstractHibernateSession session, PersistentEntity entity) { - super(criteria, session, entity); - } - - public HibernateQuery(Criteria subCriteria, AbstractHibernateSession session, PersistentEntity associatedEntity, String newAlias) { - super(subCriteria, session, associatedEntity, newAlias); - } - - protected AbstractHibernateCriterionAdapter createHibernateCriterionAdapter(PersistentEntity entity, Criterion c, String alias) { - return new HibernateCriterionAdapter(entity, c, alias); - } - - protected org.hibernate.criterion.Criterion createRlikeExpression(String propertyName, String value) { - return new RlikeExpression(propertyName, value); - } - - protected void setDetachedCriteriaValue(QueryableCriteria value, PropertyCriterion pc) { - DetachedCriteria hibernateDetachedCriteria = HibernateCriteriaBuilder.getHibernateDetachedCriteria(value); - pc.setValue(hibernateDetachedCriteria); - } - - protected String render(BasicType basic, List columns, SessionFactory sessionFactory, SQLFunction sqlFunction) { - return sqlFunction.render(basic, columns, (SessionFactoryImplementor) sessionFactory); - } - - protected PropertyMapping getEntityPersister(String name, SessionFactory sessionFactory) { - return (PropertyMapping) ((SessionFactoryImplementor) sessionFactory).getEntityPersister(name); - } - - protected TypeResolver getTypeResolver(SessionFactory sessionFactory) { - return ((SessionFactoryImplementor) sessionFactory).getTypeResolver(); - } - - protected Dialect getDialect(SessionFactory sessionFactory) { - return ((SessionFactoryImplementor) sessionFactory).getDialect(); - } - - @Override - public Object clone() { - final CriteriaImpl impl = (CriteriaImpl) criteria; - final HibernateSession hibernateSession = (HibernateSession) getSession(); - final GrailsHibernateTemplate hibernateTemplate = (GrailsHibernateTemplate) hibernateSession.getNativeInterface(); - return hibernateTemplate.execute(new GrailsHibernateTemplate.HibernateCallback() { - @Override - public HibernateQuery doInHibernate(Session session) throws HibernateException, SQLException { - Criteria newCriteria = session.createCriteria(impl.getEntityOrClassName()); - - Iterator iterator = impl.iterateExpressionEntries(); - while (iterator.hasNext()) { - CriteriaImpl.CriterionEntry entry = (CriteriaImpl.CriterionEntry) iterator.next(); - newCriteria.add(entry.getCriterion()); - } - Iterator subcriteriaIterator = impl.iterateSubcriteria(); - while (subcriteriaIterator.hasNext()) { - CriteriaImpl.Subcriteria sub = (CriteriaImpl.Subcriteria) subcriteriaIterator.next(); - newCriteria.createAlias(sub.getPath(), sub.getAlias(), sub.getJoinType(), sub.getWithClause()); - } - return new HibernateQuery(newCriteria, hibernateSession, entity); - } - }); - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AggregatePersistenceContextInterceptor.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AggregatePersistenceContextInterceptor.java deleted file mode 100644 index f36a479a3..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/AggregatePersistenceContextInterceptor.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 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.codehaus.groovy.grails.orm.hibernate.support; - -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.hibernate.SessionFactory; - -/** - * @author Burt Beckwith - */ -public class AggregatePersistenceContextInterceptor extends AbstractAggregatePersistenceContextInterceptor { - - public void afterPropertiesSet() { - // need to lazily create these instead of registering as beans since GrailsPageFilter - // looks for instances of PersistenceContextInterceptor and picks one assuming - // there's only one, so this one has to be the only one - for (String name : dataSourceNames) { - String suffix = name == GrailsDomainClassProperty.DEFAULT_DATA_SOURCE ? "" : "_" + name; - HibernatePersistenceContextInterceptor interceptor = new HibernatePersistenceContextInterceptor(); - String beanName = "sessionFactory" + suffix; - if (applicationContext.containsBean(beanName)) { - interceptor.setSessionFactory((SessionFactory)applicationContext.getBean(beanName)); - } - interceptors.add(interceptor); - } - } -} 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 deleted file mode 100644 index e680cbdc0..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventListener.java +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Copyright 2003-2007 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.support; - -import grails.validation.ValidationException; -import groovy.lang.Closure; -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; -import groovy.lang.MetaMethod; -import groovy.lang.MetaProperty; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang.ArrayUtils; -import org.codehaus.groovy.grails.commons.GrailsClassUtils; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -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; -import org.grails.datastore.mapping.engine.event.ValidationEvent; -import org.hibernate.FlushMode; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.event.spi.AbstractEvent; -import org.hibernate.event.spi.PostDeleteEvent; -import org.hibernate.event.spi.PostDeleteEventListener; -import org.hibernate.event.spi.PostInsertEvent; -import org.hibernate.event.spi.PostInsertEventListener; -import org.hibernate.event.spi.PostLoadEvent; -import org.hibernate.event.spi.PostLoadEventListener; -import org.hibernate.event.spi.PostUpdateEvent; -import org.hibernate.event.spi.PostUpdateEventListener; -import org.hibernate.event.spi.PreDeleteEvent; -import org.hibernate.event.spi.PreDeleteEventListener; -import org.hibernate.event.spi.PreInsertEvent; -import org.hibernate.event.spi.PreLoadEvent; -import org.hibernate.event.spi.PreLoadEventListener; -import org.hibernate.event.spi.PreUpdateEvent; -import org.hibernate.event.spi.PreUpdateEventListener; -import org.hibernate.event.spi.SaveOrUpdateEvent; -import org.hibernate.event.spi.SaveOrUpdateEventListener; -import org.hibernate.persister.entity.EntityPersister; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.ReflectionUtils; -import org.springframework.validation.Errors; - -/** - *

    Invokes closure events on domain entities such as beforeInsert, beforeUpdate and beforeDelete. - * - *

    Also deals with auto time stamping of domain classes that have properties named 'lastUpdated' and/or 'dateCreated'. - * - * @author Lari Hotari - * @since 1.3.5 - */ -@SuppressWarnings({"rawtypes", "unchecked", "serial"}) -public class ClosureEventListener implements SaveOrUpdateEventListener, - PreLoadEventListener, - PostLoadEventListener, - PostInsertEventListener, - PostUpdateEventListener, - PostDeleteEventListener, - PreDeleteEventListener, - PreUpdateEventListener { - - private static final long serialVersionUID = 1; - private static final Logger log = LoggerFactory.getLogger(ClosureEventListener.class); - private static final Object[] EMPTY_OBJECT_ARRAY = {}; - - EventTriggerCaller saveOrUpdateCaller; - EventTriggerCaller beforeInsertCaller; - EventTriggerCaller preLoadEventCaller; - EventTriggerCaller postLoadEventListener; - EventTriggerCaller postInsertEventListener; - EventTriggerCaller postUpdateEventListener; - EventTriggerCaller postDeleteEventListener; - EventTriggerCaller preDeleteEventListener; - EventTriggerCaller preUpdateEventListener; - private BeforeValidateHelper beforeValidateHelper = new BeforeValidateHelper(); - boolean shouldTimestamp = false; - MetaProperty dateCreatedProperty; - MetaProperty lastUpdatedProperty; - MetaClass domainMetaClass; - boolean failOnErrorEnabled = false; - MetaProperty errorsProperty; - Map validateParams; - MetaMethod validateMethod; - - public ClosureEventListener(Class domainClazz, boolean failOnError, List failOnErrorPackages) { - domainMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(domainClazz); - dateCreatedProperty = domainMetaClass.getMetaProperty(GrailsDomainClassProperty.DATE_CREATED); - lastUpdatedProperty = domainMetaClass.getMetaProperty(GrailsDomainClassProperty.LAST_UPDATED); - if (dateCreatedProperty != null || lastUpdatedProperty != null) { - Mapping m = new GrailsDomainBinder().getMapping(domainClazz); - shouldTimestamp = m == null || m.isAutoTimestamp(); - } - - saveOrUpdateCaller = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.ONLOAD_SAVE); - beforeInsertCaller = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.BEFORE_INSERT_EVENT); - preLoadEventCaller = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.ONLOAD_EVENT); - if (preLoadEventCaller == null) { - preLoadEventCaller = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.BEFORE_LOAD_EVENT); - } - postLoadEventListener = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.AFTER_LOAD_EVENT); - postInsertEventListener = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.AFTER_INSERT_EVENT); - postUpdateEventListener = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.AFTER_UPDATE_EVENT); - postDeleteEventListener = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.AFTER_DELETE_EVENT); - preDeleteEventListener = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.BEFORE_DELETE_EVENT); - preUpdateEventListener = buildCaller(domainClazz, ClosureEventTriggeringInterceptor.BEFORE_UPDATE_EVENT); - - if (failOnErrorPackages.size() > 0) { - failOnErrorEnabled = GrailsClassUtils.isClassBelowPackage(domainClazz, failOnErrorPackages); - } else { - failOnErrorEnabled = failOnError; - } - - validateParams = new HashMap(); - validateParams.put(ValidatePersistentMethod.ARGUMENT_DEEP_VALIDATE, Boolean.FALSE); - - errorsProperty = domainMetaClass.getMetaProperty(AbstractDynamicPersistentMethod.ERRORS_PROPERTY); - - validateMethod = domainMetaClass.getMetaMethod(ValidatePersistentMethod.METHOD_SIGNATURE, - new Object[] { Map.class }); - } - - private EventTriggerCaller buildCaller(Class domainClazz, String event) { - Method method = ReflectionUtils.findMethod(domainClazz, event); - if (method != null) { - ReflectionUtils.makeAccessible(method); - return new MethodCaller(method); - } - - Field field = ReflectionUtils.findField(domainClazz, event); - if (field != null) { - ReflectionUtils.makeAccessible(field); - return new FieldClosureCaller(field); - } - - MetaMethod metaMethod = domainMetaClass.getMetaMethod(event, EMPTY_OBJECT_ARRAY); - if (metaMethod != null) { - return new MetaMethodCaller(metaMethod); - } - - MetaProperty metaProperty = domainMetaClass.getMetaProperty(event); - if (metaProperty != null) { - return new MetaPropertyClosureCaller(metaProperty); - } - - return null; - } - - public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException { - // no-op, merely a hook for plugins to override - } - - private void synchronizePersisterState(Object entity, EntityPersister persister, Object[] state) { - String[] propertyNames = persister.getPropertyNames(); - for (int i = 0; i < propertyNames.length; i++) { - String p = propertyNames[i]; - MetaProperty metaProperty = domainMetaClass.getMetaProperty(p); - if (ClosureEventTriggeringInterceptor.IGNORED.contains(p) || metaProperty == null) { - continue; - } - Object value = metaProperty.getProperty(entity); - state[i] = value; - persister.setPropertyValue(entity, i, value); - } - } - - public void onPreLoad(final PreLoadEvent event) { - if (preLoadEventCaller == null) { - return; - } - - doWithManualSession(event, new Closure(this) { - @Override - public Object call() { - preLoadEventCaller.call(event.getEntity()); - return null; - } - }); - } - - public void onPostLoad(final PostLoadEvent event) { - if (postLoadEventListener == null) { - return; - } - - doWithManualSession(event, new Closure(this) { - @Override - public Object call() { - postLoadEventListener.call(event.getEntity()); - return null; - } - }); - } - - public void onPostInsert(PostInsertEvent event) { - final Object entity = event.getEntity(); - AbstractSavePersistentMethod.clearDisabledValidations(entity); - if (postInsertEventListener == null) { - return; - } - - doWithManualSession(event, new Closure(this) { - @Override - public Object call() { - postInsertEventListener.call(entity); - return null; - } - }); - } - - public void onPostUpdate(PostUpdateEvent event) { - final Object entity = event.getEntity(); - AbstractSavePersistentMethod.clearDisabledValidations(entity); - if (postUpdateEventListener == null) { - return; - } - - doWithManualSession(event, new Closure(this) { - @Override - public Object call() { - postUpdateEventListener.call(entity); - return null; - } - }); - } - - public void onPostDelete(PostDeleteEvent event) { - final Object entity = event.getEntity(); - AbstractSavePersistentMethod.clearDisabledValidations(entity); - if (postDeleteEventListener == null) { - return; - } - - doWithManualSession(event, new Closure(this) { - @Override - public Object call() { - postDeleteEventListener.call(entity); - return null; - } - }); - } - - public boolean onPreDelete(final PreDeleteEvent event) { - if (preDeleteEventListener == null) { - return false; - } - - return doWithManualSession(event, new Closure(this) { - @Override - public Boolean call() { - return preDeleteEventListener.call(event.getEntity()); - } - }); - } - - public boolean onPreUpdate(final PreUpdateEvent event) { - return doWithManualSession(event, new Closure(this) { - @Override - public Boolean call() { - Object entity = event.getEntity(); - boolean evict = false; - if (preUpdateEventListener != null) { - evict = preUpdateEventListener.call(entity); - synchronizePersisterState(entity, event.getPersister(), event.getState()); - } - if (lastUpdatedProperty != null && shouldTimestamp) { - Object now = DefaultGroovyMethods.newInstance(lastUpdatedProperty.getType(), new Object[] { System.currentTimeMillis() }); - event.getState()[ArrayUtils.indexOf(event.getPersister().getPropertyNames(), GrailsDomainClassProperty.LAST_UPDATED)] = now; - lastUpdatedProperty.setProperty(entity, now); - } - if (!AbstractSavePersistentMethod.isAutoValidationDisabled(entity) - && !DefaultTypeTransformation.castToBoolean(validateMethod.invoke(entity, new Object[] { validateParams }))) { - evict = true; - if (failOnErrorEnabled) { - Errors errors = (Errors) errorsProperty.getProperty(entity); - throw new ValidationException("Validation error whilst flushing entity [" + entity.getClass().getName() - + "]", errors); - } - } - return evict; - } - }); - } - - private T doWithManualSession(AbstractEvent event, Closure callable) { - Session session = event.getSession(); - FlushMode current = session.getFlushMode(); - try { - session.setFlushMode(FlushMode.MANUAL); - return callable.call(); - } finally { - session.setFlushMode(current); - } - } - - public boolean onPreInsert(final PreInsertEvent event) { - return doWithManualSession(event, new Closure(this) { - @Override - public Boolean call() { - Object entity = event.getEntity(); - boolean synchronizeState = false; - if (beforeInsertCaller != null) { - if (beforeInsertCaller.call(entity)) { - return true; - } - synchronizeState = true; - } - if (shouldTimestamp) { - long time = System.currentTimeMillis(); - if (dateCreatedProperty != null) { - Object now = DefaultGroovyMethods.newInstance(dateCreatedProperty.getType(), new Object[] { time }); - dateCreatedProperty.setProperty(entity, now); - synchronizeState = true; - } - if (lastUpdatedProperty != null) { - Object now = DefaultGroovyMethods.newInstance(lastUpdatedProperty.getType(), new Object[] { time }); - lastUpdatedProperty.setProperty(entity, now); - synchronizeState = true; - } - } - - if (synchronizeState) { - synchronizePersisterState(entity, event.getPersister(), event.getState()); - } - - boolean evict = false; - if (!AbstractSavePersistentMethod.isAutoValidationDisabled(entity) - && !DefaultTypeTransformation.castToBoolean(validateMethod.invoke(entity, - new Object[] { validateParams }))) { - evict = true; - if (failOnErrorEnabled) { - Errors errors = (Errors) errorsProperty.getProperty(entity); - throw new ValidationException("Validation error whilst flushing entity [" + entity.getClass().getName() - + "]", errors); - } - } - return evict; - } - }); - } - - public void onValidate(ValidationEvent event) { - beforeValidateHelper.invokeBeforeValidate( - event.getEntityObject(), event.getValidatedFields()); - } - - private static abstract class EventTriggerCaller { - - public abstract boolean call(Object entity); - - boolean resolveReturnValue(Object retval) { - if (retval instanceof Boolean) { - return !(Boolean)retval; - } - return false; - } - } - - private static class MethodCaller extends EventTriggerCaller { - Method method; - - MethodCaller(Method method) { - this.method = method; - } - - @Override - public boolean call(Object entity) { - Object retval = ReflectionUtils.invokeMethod(method, entity); - return resolveReturnValue(retval); - } - } - - private static class MetaMethodCaller extends EventTriggerCaller { - MetaMethod method; - - MetaMethodCaller(MetaMethod method) { - this.method = method; - } - - @Override - public boolean call(Object entity) { - Object retval = method.invoke(entity, EMPTY_OBJECT_ARRAY); - return resolveReturnValue(retval); - } - } - - private static abstract class ClosureCaller extends EventTriggerCaller { - boolean cloneFirst = false; - - Object callClosure(Object entity, Closure callable) { - if (cloneFirst) { - callable = (Closure)callable.clone(); - } - callable.setResolveStrategy(Closure.DELEGATE_FIRST); - callable.setDelegate(entity); - return callable.call(); - } - } - - private static class FieldClosureCaller extends ClosureCaller { - Field field; - - FieldClosureCaller(Field field) { - this.field = field; - if (Modifier.isStatic(field.getModifiers())) { - cloneFirst = true; - } - } - - @Override - public boolean call(Object entity) { - Object fieldval = ReflectionUtils.getField(field, entity); - if (fieldval instanceof Closure) { - return resolveReturnValue(callClosure(entity, (Closure) fieldval)); - } - log.error("Field " + field + " is not Closure or method."); - return false; - } - } - - private static class MetaPropertyClosureCaller extends ClosureCaller { - MetaProperty metaProperty; - - MetaPropertyClosureCaller(MetaProperty metaProperty) { - this.metaProperty = metaProperty; - if (Modifier.isStatic(metaProperty.getModifiers())) { - cloneFirst = true; - } - } - - @Override - public boolean call(Object entity) { - Object fieldval = metaProperty.getProperty(entity); - if (fieldval instanceof Closure) { - return resolveReturnValue(callClosure(entity, (Closure) fieldval)); - } - log.error("Field " + metaProperty + " is not Closure."); - return false; - } - } -} 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 deleted file mode 100644 index 910059755..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright 2003-2007 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.support; - -import grails.util.CollectionUtils; - -import java.util.Collection; -import java.util.Map; - -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore; -import org.codehaus.groovy.grails.orm.hibernate.SessionFactoryProxy; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; -import org.hibernate.HibernateException; -import org.hibernate.SessionFactory; -import org.hibernate.engine.internal.Nullability; -import org.hibernate.event.internal.DefaultSaveOrUpdateEventListener; -import org.hibernate.event.service.spi.EventListenerRegistry; -import org.hibernate.event.spi.AbstractEvent; -import org.hibernate.event.spi.EventType; -import org.hibernate.event.spi.PostDeleteEvent; -import org.hibernate.event.spi.PostDeleteEventListener; -import org.hibernate.event.spi.PostInsertEvent; -import org.hibernate.event.spi.PostInsertEventListener; -import org.hibernate.event.spi.PostLoadEvent; -import org.hibernate.event.spi.PostLoadEventListener; -import org.hibernate.event.spi.PostUpdateEvent; -import org.hibernate.event.spi.PostUpdateEventListener; -import org.hibernate.event.spi.PreDeleteEvent; -import org.hibernate.event.spi.PreDeleteEventListener; -import org.hibernate.event.spi.PreInsertEvent; -import org.hibernate.event.spi.PreInsertEventListener; -import org.hibernate.event.spi.PreLoadEvent; -import org.hibernate.event.spi.PreLoadEventListener; -import org.hibernate.event.spi.PreUpdateEvent; -import org.hibernate.event.spi.PreUpdateEventListener; -import org.hibernate.event.spi.SaveOrUpdateEvent; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; - -/** - * Listens for Hibernate events and publishes corresponding Datastore events. - * - * @author Graeme Rocher - * @author Lari Hotari - * @author Burt Beckwith - * @since 1.0 - */ -public class ClosureEventTriggeringInterceptor extends DefaultSaveOrUpdateEventListener - implements ApplicationContextAware, - PreLoadEventListener, - PostLoadEventListener, - PostInsertEventListener, - PostUpdateEventListener, - PostDeleteEventListener, - PreDeleteEventListener, - PreUpdateEventListener, - PreInsertEventListener { - -// private final Logger log = LoggerFactory.getLogger(getClass()); - private static final long serialVersionUID = 1; - - public static final Collection IGNORED = CollectionUtils.newSet("version", "id"); - public static final String ONLOAD_EVENT = "onLoad"; - public static final String ONLOAD_SAVE = "onSave"; - public static final String BEFORE_LOAD_EVENT = "beforeLoad"; - public static final String BEFORE_INSERT_EVENT = "beforeInsert"; - public static final String AFTER_INSERT_EVENT = "afterInsert"; - public static final String BEFORE_UPDATE_EVENT = "beforeUpdate"; - public static final String AFTER_UPDATE_EVENT = "afterUpdate"; - public static final String BEFORE_DELETE_EVENT = "beforeDelete"; - public static final String AFTER_DELETE_EVENT = "afterDelete"; - public static final String AFTER_LOAD_EVENT = "afterLoad"; - -// private Method markInterceptorDirtyMethod; - private ApplicationContext ctx; - private Map datastores; - - private static final ThreadLocal insertActiveThreadLocal = new ThreadLocal(); - -/* public ClosureEventTriggeringInterceptor() { - try { - markInterceptorDirtyMethod = ReflectionUtils.findMethod(AbstractSaveEventListener.class, "markInterceptorDirty", - new Class[] { Object.class, EntityPersister.class, EventSource.class }); - ReflectionUtils.makeAccessible(markInterceptorDirtyMethod); - } catch (Exception e) { - // ignore - } - } -*/ - public void setDatastores(Map datastores) { - this.datastores = datastores; - } - - @Override - public void onSaveOrUpdate(SaveOrUpdateEvent hibernateEvent) throws HibernateException { - publishEvent(hibernateEvent, new org.grails.datastore.mapping.engine.event.SaveOrUpdateEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity())); - super.onSaveOrUpdate(hibernateEvent); - } - - public void onPreLoad(PreLoadEvent hibernateEvent) { - publishEvent(hibernateEvent, new org.grails.datastore.mapping.engine.event.PreLoadEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity())); - } - - public void onPostLoad(PostLoadEvent hibernateEvent) { - publishEvent(hibernateEvent, new org.grails.datastore.mapping.engine.event.PostLoadEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity())); - } - - public boolean onPreInsert(PreInsertEvent hibernateEvent) { - AbstractPersistenceEvent event = new org.grails.datastore.mapping.engine.event.PreInsertEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity()); - publishEvent(hibernateEvent, event); - return event.isCancelled(); - } - - public void onPostInsert(PostInsertEvent hibernateEvent) { - publishEvent(hibernateEvent, new org.grails.datastore.mapping.engine.event.PostInsertEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity())); - } - - public boolean onPreUpdate(PreUpdateEvent hibernateEvent) { - AbstractPersistenceEvent event = new org.grails.datastore.mapping.engine.event.PreUpdateEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity()); - publishEvent(hibernateEvent, event); - return event.isCancelled(); - } - - public void onPostUpdate(PostUpdateEvent hibernateEvent) { - publishEvent(hibernateEvent, new org.grails.datastore.mapping.engine.event.PostUpdateEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity())); - } - - public boolean onPreDelete(PreDeleteEvent hibernateEvent) { - AbstractPersistenceEvent event = new org.grails.datastore.mapping.engine.event.PreDeleteEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity()); - publishEvent(hibernateEvent, event); - return event.isCancelled(); - } - - public void onPostDelete(PostDeleteEvent hibernateEvent) { - publishEvent(hibernateEvent, new org.grails.datastore.mapping.engine.event.PostDeleteEvent( - findDatastore(hibernateEvent), hibernateEvent.getEntity())); - } - - public void setApplicationContext(ApplicationContext applicationContext) { - ctx = applicationContext; - } - - private void publishEvent(AbstractEvent hibernateEvent, AbstractPersistenceEvent mappingEvent) { - mappingEvent.setNativeEvent(hibernateEvent); - ctx.publishEvent(mappingEvent); - } - - private Datastore findDatastore(AbstractEvent hibernateEvent) { - SessionFactory sessionFactory = hibernateEvent.getSession().getSessionFactory(); - if (!(sessionFactory instanceof SessionFactoryProxy)) { - // should always be the case - for (Map.Entry entry : datastores.entrySet()) { - SessionFactory sf = entry.getKey(); - if (sf instanceof SessionFactoryProxy) { - if (((SessionFactoryProxy)sf).getCurrentSessionFactory() == sessionFactory) { - return entry.getValue(); - } - } - } - } - - Datastore datastore = datastores.get(sessionFactory); - if (datastore == null && datastores.size() == 1) { - datastore = datastores.values().iterator().next(); - } - return datastore; - } - - /* - * TODO: This is a horrible hack due to a bug in Hibernate's post-insert event processing (HHH-3904) - */ -/* @Override - protected Serializable performSaveOrReplicate(Object entity, EntityKey key, EntityPersister persister, boolean useIdentityColumn, - Object anything, EventSource source, boolean requiresImmediateIdAccess) { -*/ - - public static final void addNullabilityCheckerPreInsertEventListener(EventListenerRegistry listenerRegistry) { - listenerRegistry.getEventListenerGroup(EventType.PRE_INSERT).appendListener(NULLABILITY_CHECKER_INSTANCE); - } - - private static final PreInsertEventListener NULLABILITY_CHECKER_INSTANCE = new NullabilityCheckerPreInsertEventListener(); - - @SuppressWarnings("serial") - private static class NullabilityCheckerPreInsertEventListener implements PreInsertEventListener { - public boolean onPreInsert(PreInsertEvent event) { - new Nullability(event.getSession()).checkNullability(event.getState(), event.getPersister(), false); - return false; - } - } - - /** - * 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() - */ - @Override - protected 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(true); - } - - /** - * Clears the ThreadLocal variable set by markInsertActive(). - */ - public static void resetInsertActive() { - insertActiveThreadLocal.remove(); - } -} 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 deleted file mode 100644 index d2434c999..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/FlushOnRedirectEventListener.java +++ /dev/null @@ -1,43 +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.support; - -import org.codehaus.groovy.grails.web.servlet.mvc.RedirectEventListener; -import org.hibernate.FlushMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; - -/** - * Flushes the session on a redirect. - * - * @author Graeme Rocher - * @since 1.2 - */ -public class FlushOnRedirectEventListener implements RedirectEventListener { - - private SessionFactory sessionFactory; - - public FlushOnRedirectEventListener(SessionFactory sf) { - sessionFactory = sf; - } - - public void responseRedirected(String url) { - Session session = sessionFactory.getCurrentSession(); - if (!FlushMode.isManualFlushMode(session.getFlushMode())) { - session.flush(); - } - } -} 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 deleted file mode 100644 index 309227a75..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/GrailsOpenSessionInViewInterceptor.java +++ /dev/null @@ -1,148 +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.support; - -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; - -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.hibernate.FlushMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.springframework.dao.DataAccessException; -import org.springframework.orm.hibernate4.SessionHolder; -import org.springframework.orm.hibernate4.support.OpenSessionInViewInterceptor; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.ui.ModelMap; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.WebRequest; - -/** - * Extends the default spring OSIVI and doesn't flush the session if it has been set - * to MANUAL on the session itself. - * - * @author Graeme Rocher - * @since 0.5 - */ -public class GrailsOpenSessionInViewInterceptor extends OpenSessionInViewInterceptor { - protected static final String IS_FLOW_REQUEST_ATTRIBUTE = "org.codehaus.groovy.grails.webflow.flow_request"; - - protected int flushMode = GrailsHibernateTemplate.FLUSH_AUTO; - - @Override - public void preHandle(WebRequest request) throws DataAccessException { - GrailsWebRequest webRequest = GrailsWebRequest.lookup(); - final boolean isFlowRequest = webRequest != null && webRequest.isFlowRequest(); - if (isFlowRequest) { - webRequest.setAttribute(IS_FLOW_REQUEST_ATTRIBUTE, "true", WebRequest.SCOPE_REQUEST); - } - else { - super.preHandle(request); - SessionFactory sessionFactory = getSessionFactory(); - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory); - Session session = sessionHolder.getSession(); - GrailsHibernateUtil.enableDynamicFilterEnablerIfPresent(sessionFactory, session); - } - } - - @Override - public void postHandle(WebRequest request, ModelMap model) throws DataAccessException { - final boolean isFlowRequest = request.getAttribute(IS_FLOW_REQUEST_ATTRIBUTE, WebRequest.SCOPE_REQUEST) != null; - if (isFlowRequest) { - return; - } - - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(getSessionFactory()); - Session session = sessionHolder.getSession(); - try { - super.postHandle(request, model); - if (session != null && getFlushMode() != GrailsHibernateTemplate.FLUSH_NEVER && !FlushMode.isManualFlushMode(session.getFlushMode())) { - logger.debug("Eagerly flushing Hibernate session"); - session.flush(); - } - } - finally { - session.setFlushMode(FlushMode.MANUAL); - } - } - - @Override - public void afterCompletion(WebRequest request, Exception ex) throws DataAccessException { - try { - final boolean isWebRequest = request.getAttribute(IS_FLOW_REQUEST_ATTRIBUTE, WebRequest.SCOPE_REQUEST) != null; - if (isWebRequest) { - return; - } - - request = (WebRequest) RequestContextHolder.currentRequestAttributes(); - if (!(request instanceof GrailsWebRequest)) { - super.afterCompletion(request, ex); - 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()); - if (sessionHolder != null) { - Session session = sessionHolder.getSession(); - if (session != null) { - session.disconnect(); - } - } - } - catch (IllegalStateException e) { - super.afterCompletion(request, ex); - } - } - finally { - AbstractSavePersistentMethod.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; - } - public int getFlushMode() { - return 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 deleted file mode 100644 index edd7d53a3..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java +++ /dev/null @@ -1,114 +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.support; - -import groovy.util.ConfigObject; - -import java.sql.Connection; -import java.util.Properties; - -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.service.classloading.internal.ClassLoaderServiceImpl; -import org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl; -import org.hibernate.service.jdbc.dialect.internal.StandardDialectResolver; -import org.hibernate.service.jdbc.dialect.spi.DialectFactory; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.jdbc.datasource.DataSourceUtils; -import org.springframework.jdbc.support.JdbcUtils; -import org.springframework.jdbc.support.MetaDataAccessException; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * @author Steven Devijver - */ -public class HibernateDialectDetectorFactoryBean implements FactoryBean, InitializingBean, GrailsApplicationAware { - - private DataSource dataSource; - private Properties vendorNameDialectMappings; - private String hibernateDialectClassName; - private Dialect hibernateDialect; - private GrailsApplication grailsApplication; - - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - } - - public void setVendorNameDialectMappings(Properties mappings) { - vendorNameDialectMappings = mappings; - } - - public String getObject() { - return hibernateDialectClassName; - } - - public Class getObjectType() { - return String.class; - } - - public boolean isSingleton() { - return true; - } - - public void afterPropertiesSet() throws MetaDataAccessException { - Assert.notNull(dataSource, "Data source is not set!"); - Assert.notNull(vendorNameDialectMappings, "Vendor name/dialect mappings are not set!"); - - Connection connection = null; - - String dbName = (String)JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName"); - - try { - connection = DataSourceUtils.getConnection(dataSource); - - try { - ConfigObject config = grailsApplication == null ? null : grailsApplication.getConfig(); - Properties properties = config == null ? new Properties() : config.toProperties(); - final DialectFactory dialectFactory = createDialectFactory(); - hibernateDialect = dialectFactory.buildDialect(properties, connection); - hibernateDialectClassName = hibernateDialect.getClass().getName(); - } catch (HibernateException e) { - hibernateDialectClassName = vendorNameDialectMappings.getProperty(dbName); - } - - if (!StringUtils.hasText(hibernateDialectClassName)) { - throw new CouldNotDetermineHibernateDialectException( - "Could not determine Hibernate dialect for database name [" + dbName + "]!"); - } - } finally { - DataSourceUtils.releaseConnection(connection,dataSource); - } - } - - // should be using the ServiceRegistry, but getting it from the SessionFactory at startup fails in Spring - protected DialectFactory createDialectFactory() { - DialectFactoryImpl factory = new DialectFactoryImpl(); - factory.setDialectResolver(new StandardDialectResolver()); - factory.setClassLoaderService(new ClassLoaderServiceImpl(Thread.currentThread().getContextClassLoader())); - return factory; - } - - public void setGrailsApplication(GrailsApplication grailsApplication) { - this.grailsApplication = grailsApplication; - } -} 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 deleted file mode 100644 index 3a8446be9..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/support/HibernatePersistenceContextInterceptor.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 2004-2006 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.support; - -import grails.validation.DeferredBindingActions; - -import org.codehaus.groovy.grails.lifecycle.ShutdownOperations; -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.hibernate.FlushMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.orm.hibernate4.SessionFactoryUtils; -import org.springframework.orm.hibernate4.SessionHolder; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -/** - * @author Graeme Rocher - * @since 0.4 - */ -public class HibernatePersistenceContextInterceptor implements PersistenceContextInterceptor { - - private static final Logger LOG = LoggerFactory.getLogger(HibernatePersistenceContextInterceptor.class); - private SessionFactory sessionFactory; - - private ThreadLocal participate = new ThreadLocal(); - private ThreadLocal nestingCount = new ThreadLocal(); - - public HibernatePersistenceContextInterceptor() { - ShutdownOperations.addOperation(new Runnable() { - public void run() { - participate.remove(); - nestingCount.remove(); - } - }); - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.support.PersistenceContextInterceptor#destroy() - */ - public void destroy() { - DeferredBindingActions.clear(); - if (decNestingCount() > 0 || getParticipate()) { - return; - } - - try { - // single session mode - SessionHolder holder = (SessionHolder)TransactionSynchronizationManager.unbindResource(getSessionFactory()); - LOG.debug("Closing single Hibernate session in GrailsDispatcherServlet"); - try { - SessionFactoryUtils.closeSession(holder.getSession()); - } - catch (RuntimeException ex) { - LOG.error("Unexpected exception on closing Hibernate Session", ex); - } - } - finally { - AbstractSavePersistentMethod.clearDisabledValidations(); - } - } - - public void disconnect() { - try { - getSession(false).disconnect(); - } - catch (IllegalStateException e) { - // no session ignore - } - } - - public void reconnect() { - getSession(); - } - - public void flush() { - getSession().flush(); - } - - public void clear() { - getSession().clear(); - } - - public void setReadOnly() { - getSession().setFlushMode(FlushMode.MANUAL); - } - - public void setReadWrite() { - getSession().setFlushMode(FlushMode.AUTO); - } - - public boolean isOpen() { - try { - return getSession(false).isOpen(); - } - catch (IllegalStateException e) { - return false; - } - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.support.PersistenceContextInterceptor#init() - */ - public void init() { - if (incNestingCount() > 1) { - return; - } - SessionFactory sf = getSessionFactory(); - if (TransactionSynchronizationManager.hasResource(sf)) { - // Do not modify the Session: just set the participate flag. - setParticipate(true); - } - else { - setParticipate(false); - LOG.debug("Opening single Hibernate session in HibernatePersistenceContextInterceptor"); - Session session = getSession(); - GrailsHibernateUtil.enableDynamicFilterEnablerIfPresent(sf, session); - session.setFlushMode(FlushMode.AUTO); - TransactionSynchronizationManager.bindResource(sf, new SessionHolder(session)); - } - } - - private Session getSession() { - return getSession(true); - } - - private Session getSession(boolean allowCreate) { - - Object value = TransactionSynchronizationManager.getResource(getSessionFactory()); - if (value instanceof Session) { - return (Session) value; - } - - if (value instanceof SessionHolder) { - SessionHolder sessionHolder = (SessionHolder) value; - return sessionHolder.getSession(); - } - - if (allowCreate) { - return getSessionFactory().openSession(); - } - - throw new IllegalStateException("No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here"); - } - - /** - * @return the sessionFactory - */ - public SessionFactory getSessionFactory() { - return sessionFactory; - } - - /** - * @param sessionFactory the sessionFactory to set - */ - public void setSessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - - private int incNestingCount() { - Integer current = nestingCount.get(); - int value = (current != null) ? current + 1 : 1; - nestingCount.set(value); - return value; - } - - private int decNestingCount() { - Integer current = nestingCount.get(); - int value = current == null ? 0 : current - 1; - if (value < 0) { - value = 0; - } - nestingCount.set(value); - return value; - } - - private void setParticipate(boolean flag) { - participate.set(flag); - } - - private boolean getParticipate() { - Boolean ret = participate.get(); - return ret == null ? false : ret; - } -} diff --git a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java b/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java deleted file mode 100644 index 904345ced..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/AbstractPersistentConstraint.java +++ /dev/null @@ -1,92 +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; - -/** - * 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 = new ThreadLocal(); - - static { - ShutdownOperations.addOperation(new Runnable() { - public void run() { - sessionFactory.remove(); - } - }); - } - - protected ApplicationContext applicationContext; - - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - 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); - } - - /** - * 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 - */ - @Override - 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-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 deleted file mode 100644 index 08c5d22a1..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateConstraintsEvaluator.java +++ /dev/null @@ -1,53 +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.codehaus.groovy.grails.orm.hibernate.validation; - -import java.util.Map; - -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -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; - -/** - * Extends default implementation to add Hibernate specific exceptions. - * - * @author Graeme Rocher - * @since 2.0 - */ -public class HibernateConstraintsEvaluator extends DefaultConstraintEvaluator { - - public HibernateConstraintsEvaluator(Map defaultConstraints) { - super(defaultConstraints); - } - - public HibernateConstraintsEvaluator() { - // default - } - - @Override - protected void applyDefaultNullableConstraint(GrailsDomainClassProperty p, ConstrainedProperty cp) { - final PropertyConfig propertyConfig = new GrailsDomainBinder().getPropertyConfig(p); - boolean insertable = propertyConfig != null ? propertyConfig.isInsertable() : true; - - if (!insertable) { - cp.applyConstraint(ConstrainedProperty.NULLABLE_CONSTRAINT,true); - } - else { - super.applyDefaultNullableConstraint(p, cp); - } - } -} 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 deleted file mode 100644 index 11e78ccf0..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateDomainClassValidator.java +++ /dev/null @@ -1,101 +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.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.validation.GrailsDomainClassValidator; -import org.hibernate.FlushMode; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.collection.spi.PersistentCollection; -import org.hibernate.proxy.HibernateProxy; -import org.springframework.beans.BeanWrapper; -import org.springframework.validation.Errors; - -/** - * First checks if the Hibernate PersistentCollection instance has been initialised before bothering - * to cascade. - * - * @author Graeme Rocher - * @since 0.5 - */ -public class HibernateDomainClassValidator extends GrailsDomainClassValidator { - - private SessionFactory sessionFactory; - - @Override - protected GrailsDomainClass getAssociatedDomainClassFromApplication(Object associatedObject) { - String associatedObjectType = associatedObject.getClass().getName(); - if (associatedObject instanceof HibernateProxy) { - associatedObjectType = ((HibernateProxy) associatedObject).getHibernateLazyInitializer().getEntityName(); - } - return (GrailsDomainClass) grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, associatedObjectType); - } - - @Override - public void validate(Object obj, Errors errors, boolean cascade) { - final Session session = sessionFactory.getCurrentSession(); - FlushMode previousMode = null; - try { - if (session != null) { - previousMode = session.getFlushMode(); - session.setFlushMode(FlushMode.MANUAL); - } - - super.validate(obj, errors, cascade); - } - finally { - if (session != null && previousMode != null && !errors.hasErrors()) { - session.setFlushMode(previousMode); - } - } - } - - /** - * Overrides the default behaviour and first checks if a PersistentCollection instance has been initialised using the - * wasInitialised() method before cascading - * - * @param errors The Spring Errors instance - * @param bean The BeanWrapper for the bean - * @param persistentProperty The GrailsDomainClassProperty instance - * @param propertyName The name of the property - * - * @see org.hibernate.collection.PersistentCollection#wasInitialized() - */ - @Override - protected void cascadeValidationToMany(Errors errors, BeanWrapper bean, GrailsDomainClassProperty persistentProperty, String propertyName) { - Object collection = bean.getPropertyValue(propertyName); - if (collection == null) { - return; - } - - if (collection instanceof PersistentCollection) { - PersistentCollection persistentCollection = (PersistentCollection)collection; - if (persistentCollection.wasInitialized()) { - super.cascadeValidationToMany(errors, bean, persistentProperty, propertyName); - } - } - else { - super.cascadeValidationToMany(errors, bean, persistentProperty, propertyName); - } - } - - public void setSessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } -} 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 d0910c5c0..000000000 --- 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 a7c35caf3..000000000 --- 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 deleted file mode 100644 index 2669c0400..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/UniqueConstraint.java +++ /dev/null @@ -1,266 +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 java.util.ArrayList; -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.orm.hibernate.GrailsHibernateTemplate; -import org.codehaus.groovy.grails.validation.ConstrainedProperty; -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.hibernate.criterion.Restrictions; -import org.hibernate.metadata.ClassMetadata; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.util.Assert; -import org.springframework.validation.Errors; - -/** - * A constraint that validates the uniqueness of a property (will query the - * database during validation process). - * - * @author Graeme Rocher - * @author Sergey Nebolsin - * @since 0.4 - */ -public class UniqueConstraint extends AbstractPersistentConstraint { - - private static final String DEFAULT_NOT_UNIQUE_MESSAGE_CODE = "default.not.unique.message"; - private static final String TARGET_DOMAIN_CLASS_ALIAS = "domain_"; - - public static final String UNIQUE_CONSTRAINT = "unique"; - - private boolean unique; - private List uniquenessGroup = new ArrayList(); - - public UniqueConstraint() { - ShutdownOperations.addOperation(new Runnable() { - public void run() { - ConstrainedProperty.removeConstraint(UNIQUE_CONSTRAINT, PersistentConstraintFactory.class); - } - }); - } - - /** - * @return Returns the unique. - */ - public boolean isUnique() { - return unique; - } - - /** - * @return Whether the property is unique within a group - */ - public boolean isUniqueWithinGroup() { - return !uniquenessGroup.isEmpty(); - } - - /* (non-Javadoc) - * @see org.codehaus.groovy.grails.validation.ConstrainedProperty.AbstractConstraint#setParameter(java.lang.Object) - */ - @Override - public void setParameter(Object constraintParameter) { - if (!(constraintParameter instanceof Boolean || - constraintParameter instanceof String || - constraintParameter instanceof CharSequence || - constraintParameter instanceof List)) { - throw new IllegalArgumentException("Parameter for constraint [" + UNIQUE_CONSTRAINT + - "] of property [" + constraintPropertyName + "] of class [" + - constraintOwningClass + "] must be a boolean or string value"); - } - - if (constraintParameter instanceof List) { - for (Object parameter : ((List) constraintParameter)) { - if (!(parameter instanceof String || parameter instanceof CharSequence)) { - throw new IllegalArgumentException("Parameter for constraint [" + UNIQUE_CONSTRAINT + - "] of property [" + constraintPropertyName + "] of class [" + - constraintOwningClass + "] must be a boolean or string value"); - } - uniquenessGroup.add(parameter.toString()); - } - } - else if (constraintParameter instanceof String || constraintParameter instanceof CharSequence) { - uniquenessGroup.add(constraintParameter.toString()); - unique = true; - } - else { - unique = (Boolean)constraintParameter; - } - - if (!uniquenessGroup.isEmpty()) { - unique = true; - for (Object anUniquenessGroup : uniquenessGroup) { - String propertyName = (String) anUniquenessGroup; - if (GrailsClassUtils.getPropertyType(constraintOwningClass, propertyName) == null) { - throw new IllegalArgumentException("Scope for constraint [" + UNIQUE_CONSTRAINT + - "] of property [" + constraintPropertyName + "] of class [" + - constraintOwningClass + "] must be a valid property name of same class"); - } - } - } - - super.setParameter(constraintParameter); - } - - public String getName() { - return UNIQUE_CONSTRAINT; - } - - @Override - protected void processValidate(final Object target, final Object propertyValue, Errors errors) { - if (!unique) { - return; - } - - final Object id; - try { - id = InvokerHelper.invokeMethod(target, "ident", null); - } - catch (Exception e) { - throw new GrailsRuntimeException("Target of [unique] constraints [" + target + - "] is not a domain instance. Unique constraint can only be applied to " + - "domain classes and not custom user types or embedded instances"); - } - - GrailsHibernateTemplate hibernateTemplate = getHibernateTemplate(); - Assert.state(hibernateTemplate != null, - "Unable use [unique] constraint, no Hibernate SessionFactory found!"); - List results = hibernateTemplate.executeFind(new GrailsHibernateTemplate.HibernateCallback>() { - public List doInHibernate(Session session) throws HibernateException { - session.setFlushMode(FlushMode.MANUAL); - try { - 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()); - 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()); - if (domainClass != null) { - property = domainClass.getPropertyByName(constraintPropertyName); - } - } - constraintClass = domainClass != null ? domainClass.getClazz() : constraintClass; - } - Criteria criteria = null; - - if (domainClass.getPersistentProperty(constraintPropertyName).isOneToOne()) { - criteria = session.createCriteria(constraintClass, TARGET_DOMAIN_CLASS_ALIAS); - - String constraintPropertyAlias = constraintPropertyName + "_"; - criteria.createAlias(TARGET_DOMAIN_CLASS_ALIAS + "." + constraintPropertyName, constraintPropertyAlias); - - GrailsDomainClassProperty property = domainClass.getPropertyByName(constraintPropertyName); - ClassMetadata classMetadata = session.getSessionFactory().getClassMetadata(property.getType()); - String identifierPropertyName = classMetadata.getIdentifierPropertyName(); - - BeanWrapper bean = new BeanWrapperImpl(propertyValue); - Object identifierPropertyValue = bean.getPropertyValue(identifierPropertyName); - - criteria.add(Restrictions.eq(constraintPropertyAlias + "." + identifierPropertyName, identifierPropertyValue)); - } else { - criteria = session.createCriteria(constraintClass) - .add(Restrictions.eq(constraintPropertyName, propertyValue)); - } - - if (uniquenessGroup != null) { - for (Object anUniquenessGroup : uniquenessGroup) { - String uniquenessGroupPropertyName = (String) anUniquenessGroup; - Object uniquenessGroupPropertyValue = GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(target, uniquenessGroupPropertyName); - - if (uniquenessGroupPropertyValue != null && DomainClassArtefactHandler.isDomainClass(uniquenessGroupPropertyValue.getClass())) { - try { - // We are merely verifying that the object is not transient here - session.lock(uniquenessGroupPropertyValue, LockMode.NONE); - } - catch (TransientObjectException e) { - shouldValidate = false; - } - } - if (shouldValidate) { - criteria.add(Restrictions.eq(uniquenessGroupPropertyName, uniquenessGroupPropertyValue)); - } - else { - break; // we aren't validating, so no point continuing - } - } - } - - if (shouldValidate) { - return criteria.list(); - } - return Collections.EMPTY_LIST; - } - return Collections.EMPTY_LIST; - } - finally { - session.setFlushMode(FlushMode.AUTO); - } - } - }); - - if (results.isEmpty()) { - return; - } - - boolean reject = false; - if (id != null) { - Object existing = results.get(0); - Object existingId = null; - try { - existingId = InvokerHelper.invokeMethod(existing, "ident", null); - } - catch (Exception e) { - // result is not a domain class - } - if (!id.equals(existingId)) { - reject = true; - } - } - else { - reject = true; - } - if (reject) { - Object[] args = { constraintPropertyName, constraintOwningClass, propertyValue }; - rejectValue(target, errors, UNIQUE_CONSTRAINT, args, getDefaultMessage(DEFAULT_NOT_UNIQUE_MESSAGE_CODE)); - } - } - - public List getUniquenessGroup() { - return uniquenessGroup; - } - -} diff --git a/grails-datastore-gorm-hibernate4/src/main/resources/META-INF/org.hibernate.integrator.spi.Integrator b/grails-datastore-gorm-hibernate4/src/main/resources/META-INF/org.hibernate.integrator.spi.Integrator deleted file mode 100644 index 403a7e2b0..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/resources/META-INF/org.hibernate.integrator.spi.Integrator +++ /dev/null @@ -1 +0,0 @@ -org.codehaus.groovy.grails.orm.hibernate.EventListenerIntegrator \ No newline at end of file diff --git a/grails-datastore-gorm-hibernate4/src/main/resources/META-INF/spring.handlers b/grails-datastore-gorm-hibernate4/src/main/resources/META-INF/spring.handlers deleted file mode 100644 index fef2eece4..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/resources/META-INF/spring.handlers +++ /dev/null @@ -1 +0,0 @@ -http\://grails.org/schema/gorm=org.codehaus.groovy.grails.orm.hibernate.cfg.GORMNamespaceHandler diff --git a/grails-datastore-gorm-hibernate4/src/main/resources/META-INF/spring.schemas b/grails-datastore-gorm-hibernate4/src/main/resources/META-INF/spring.schemas deleted file mode 100644 index 966d5c701..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/resources/META-INF/spring.schemas +++ /dev/null @@ -1 +0,0 @@ -http\://grails.org/schema/gorm/gorm.xsd=org/codehaus/groovy/grails/orm/hibernate/cfg/gorm.xsd \ No newline at end of file diff --git a/grails-datastore-gorm-hibernate4/src/main/resources/org/codehaus/groovy/grails/orm/hibernate/cfg/gorm.xsd b/grails-datastore-gorm-hibernate4/src/main/resources/org/codehaus/groovy/grails/orm/hibernate/cfg/gorm.xsd deleted file mode 100644 index 69b36148b..000000000 --- a/grails-datastore-gorm-hibernate4/src/main/resources/org/codehaus/groovy/grails/orm/hibernate/cfg/gorm.xsd +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/DefaultSortSpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/DefaultSortSpec.groovy deleted file mode 100644 index 61470a952..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/DefaultSortSpec.groovy +++ /dev/null @@ -1,107 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -class DefaultSortSpec extends GormDatastoreSpec { - - void "Test default sort"() { - given: - domainClasses.each { domainClass -> - def age = 40 - ["Bob", "Fred", "Ernie", "Bob", "Joe", "Ernie"].each { - domainClass.newInstance(name: it, age: age++).save() - } - } - - when: - def results = TestEntityWithSortProperty.list() - - then: - results[0].name == "Bob" - results[1].name == "Bob" - results[2].name == "Ernie" - results[3].name == "Ernie" - - when: - results = TestEntityWithSortOrderProperty.list() - - then: - results[0].name == "Joe" - results[1].name == "Fred" - results[2].name == "Ernie" - results[3].name == "Ernie" - - when: - results = TestEntityWithSingleEntrySortOrderMap.list() - - then: - results[0].name == "Joe" - results[1].name == "Fred" - results[2].name == "Ernie" - results[3].name == "Ernie" - - when: - results = TestEntityWithMultiEntrySortOrderMap.list() - - then: - results[0].name == "Joe" && results[0].age == 44 - results[1].name == "Fred" && results[1].age == 41 - results[2].name == "Ernie" && results[2].age == 45 - results[3].name == "Ernie" && results[3].age == 42 - } - - @Override - List getDomainClasses() { - [ - TestEntityWithSortProperty, - TestEntityWithSortOrderProperty, - TestEntityWithSingleEntrySortOrderMap, - TestEntityWithMultiEntrySortOrderMap - ] - } -} - -@Entity -class TestEntityWithSortProperty { - Long id - Long version - String name - Integer age - static mapping = { - sort "name" - } -} - -@Entity -class TestEntityWithSortOrderProperty { - Long id - Long version - String name - Integer age - static mapping = { - sort "name" - order "desc" - } -} - -@Entity -class TestEntityWithSingleEntrySortOrderMap { - Long id - Long version - String name - Integer age - static mapping = { - sort name: "desc" - } -} - -@Entity -class TestEntityWithMultiEntrySortOrderMap { - Long id - Long version - String name - Integer age - static mapping = { - sort name: "desc", age: "desc" - } -} diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/DeleteSpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/DeleteSpec.groovy deleted file mode 100644 index 9163b644b..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/DeleteSpec.groovy +++ /dev/null @@ -1,30 +0,0 @@ -package grails.gorm.tests - -import spock.lang.Issue - -class DeleteSpec extends GormDatastoreSpec { - - @Issue("GRAILS-9922") - def "Test deleting an entity that has a validation error"() { - when: - def entity = new TestEntity(name: "Bob", age: 44).save(flush: true) - - then: - !entity.hasErrors() - TestEntity.count() == 1 - - when: - entity.name = "" - entity.save(flush: true) - - then: - entity.hasErrors() - - when: - entity.delete(flush: true) - - then: - TestEntity.count() == 0 - } - -} diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/GroovyProxySpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/GroovyProxySpec.groovy deleted file mode 100644 index 750de479b..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/GroovyProxySpec.groovy +++ /dev/null @@ -1,36 +0,0 @@ -package grails.gorm.tests - -import org.grails.datastore.gorm.proxy.GroovyProxyFactory - -import spock.lang.Ignore - -/** - * @author graemerocher - */ -class GroovyProxySpec extends GormDatastoreSpec { - - @Ignore - void "Test creation and behavior of Groovy proxies"() { - - given: - session.mappingContext.proxyFactory = new GroovyProxyFactory() - def id = new Location(name:"United Kingdom", code:"UK").save(flush:true)?.id - session.clear() - - when: - def location = Location.proxy(id) - - then: - - location != null - id == location.id - false == location.isInitialized() - false == location.initialized - - "UK" == location.code - "United Kingdom - UK" == location.namedAndCode() - true == location.isInitialized() - true == location.initialized - null != location.target - } -} diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/MultipleOrderBySpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/MultipleOrderBySpec.groovy deleted file mode 100644 index 460bbb9d1..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/MultipleOrderBySpec.groovy +++ /dev/null @@ -1,94 +0,0 @@ -package grails.gorm.tests - -class MultipleOrderBySpec extends GormDatastoreSpec { - - void "Test multiple order by with list() method"() { - given: - def age = 40 - - ["Bob", "Fred", "Ernie", "Bob", "Joe", "Ernie"].each { - new TestEntity(name: it, age: age++).save() - } - - when: - def results = TestEntity.list(sort: [name: "asc", age: "asc"]) - - then: - results[0].name == "Bob" && results[0].age == 40 - results[1].name == "Bob" && results[1].age == 43 - results[2].name == "Ernie" && results[2].age == 42 - results[3].name == "Ernie" && results[3].age == 45 - - when: - results = TestEntity.list(sort: [name: "desc", age: "desc"]) - - then: - results[0].name == "Joe" && results[0].age == 44 - results[1].name == "Fred" && results[1].age == 41 - results[2].name == "Ernie" && results[2].age == 45 - results[3].name == "Ernie" && results[3].age == 42 - - when: - results = TestEntity.list(sort: [name: "asc", age: "desc"]) - - then: - results[0].name == "Bob" && results[0].age == 43 - results[1].name == "Bob" && results[1].age == 40 - results[2].name == "Ernie" && results[2].age == 45 - results[3].name == "Ernie" && results[3].age == 42 - - when: - results = TestEntity.list(sort: [age: "asc", name: "asc"]) - - then: - results[0].name == "Bob" && results[0].age == 40 - results[1].name == "Fred" && results[1].age == 41 - results[2].name == "Ernie" && results[2].age == 42 - results[3].name == "Bob" && results[3].age == 43 - } - - void "Test multiple order by property name with dynamic finder"() { - given: - def age = 40 - - ["Bob", "Fred", "Ernie", "Bob", "Joe", "Ernie"].each { - new TestEntity(name: it, age: age++).save() - } - - when: - def results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort: [name: "asc", age: "asc"]]) - - then: - results[0].name == "Bob" && results[0].age == 40 - results[1].name == "Bob" && results[1].age == 43 - results[2].name == "Ernie" && results[2].age == 42 - results[3].name == "Ernie" && results[3].age == 45 - - when: - results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort: [name: "desc", age: "desc"]]) - - then: - results[0].name == "Joe" && results[0].age == 44 - results[1].name == "Fred" && results[1].age == 41 - results[2].name == "Ernie" && results[2].age == 45 - results[3].name == "Ernie" && results[3].age == 42 - - when: - results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort: [name: "asc", age: "desc"]]) - - then: - results[0].name == "Bob" && results[0].age == 43 - results[1].name == "Bob" && results[1].age == 40 - results[2].name == "Ernie" && results[2].age == 45 - results[3].name == "Ernie" && results[3].age == 42 - - when: - results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort: [age: "asc", name: "asc"]]) - - then: - results[0].name == "Bob" && results[0].age == 40 - results[1].name == "Fred" && results[1].age == 41 - results[2].name == "Ernie" && results[2].age == 42 - results[3].name == "Bob" && results[3].age == 43 - } -} diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy deleted file mode 100644 index 9d7f2b3e0..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy +++ /dev/null @@ -1,109 +0,0 @@ -package grails.gorm.tests - -import org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException - -/** - * @author Burt Beckwith - */ -class OptimisticLockingSpec extends GormDatastoreSpec { - - void "Test versioning"() { - - given: - def o = new OptLockVersioned(name: 'locked') - - when: - o.save flush: true - - then: - o.version == 0 - - when: - session.clear() - o = OptLockVersioned.get(o.id) - o.name = 'Fred' - o.save flush: true - - then: - o.version == 1 - - when: - session.clear() - o = OptLockVersioned.get(o.id) - - then: - o.name == 'Fred' - o.version == 1 - } - - void "Test optimistic locking"() { - - given: - def o = new OptLockVersioned(name: 'locked').save(flush: true) - session.clear() - setupClass.transactionManager.commit setupClass.transactionStatus - setupClass.transactionStatus = null - - when: - o = OptLockVersioned.get(o.id) - - OptLockVersioned.withNewSession { s -> - def reloaded = OptLockVersioned.get(o.id) - assert reloaded - reloaded.name += ' in new session' - reloaded.save(flush: true) - } - - o.name += ' in main session' - def ex - try { - o.save(flush: true) - } - catch (e) { - ex = e - e.printStackTrace() - } - - session.clear() - o = OptLockVersioned.get(o.id) - - then: - ex instanceof HibernateOptimisticLockingFailureException - o.version == 1 - o.name == 'locked in new session' - } - - void "Test optimistic locking disabled with 'version false'"() { - given: - def o = new OptLockNotVersioned(name: 'locked').save(flush: true) - session.clear() - setupClass.transactionManager.commit setupClass.transactionStatus - setupClass.transactionStatus = null - - when: - o = OptLockNotVersioned.get(o.id) - - OptLockNotVersioned.withNewSession { s -> - def reloaded = OptLockNotVersioned.get(o.id) - reloaded.name += ' in new session' - reloaded.save(flush: true) - } - - o.name += ' in main session' - def ex - try { - o.save(flush: true) - } - catch (e) { - ex = e - e.printStackTrace() - } - - session.clear() - o = OptLockNotVersioned.get(o.id) - - then: - ex == null - o.name == 'locked in main session' - } -} diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/QueryEventsSpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/QueryEventsSpec.groovy deleted file mode 100644 index 991358c3a..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/QueryEventsSpec.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package grails.gorm.tests - -import spock.lang.Ignore -import spock.lang.Specification - -/** - * Ignored - */ -@Ignore("Hibernate GORM uses hibernate Criteria in place of Query class, so events not applicable.") -class QueryEventsSpec extends Specification { -} diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy deleted file mode 100644 index 51a89ad3d..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy +++ /dev/null @@ -1,79 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Tests the unique constraint - */ -class UniqueConstraintSpec extends GormDatastoreSpec { - - void "Test simple unique constraint"() { - when:"Two domain classes with the same name are saved" - def one = new UniqueGroup(name:"foo").save(flush:true) - def two = new UniqueGroup(name:"foo") - two.save(flush:true) - - then:"The second has errors" - one != null - two.hasErrors() - UniqueGroup.count() == 1 - - when:"The first is saved again" - one = one.save(flush:true) - - then:"The are no errors" - one != null - - when:"Three domain classes are saved within different uniqueness groups" - one = new GroupWithin(name:"foo", org:"mycompany").save(flush:true) - two = new GroupWithin(name:"foo", org:"othercompany").save(flush:true) - def three = new GroupWithin(name:"foo", org:"mycompany") - three.save(flush:true) - - then:"Only the third has errors" - one != null - two != null - three.hasErrors() - GroupWithin.count() == 2 - } - - def "Test unique constraint with a hasOne association"() { - when:"Two domain classes with the same license are saved" - def license = new License() - def one = new Driver(license: license).save(flush: true) - def two = new Driver(license: license) - two.save(flush: true) - - then:"The second has errors" - one != null - two.hasErrors() - Driver.count() == 1 - License.count() == 1 - - when:"The first is saved again" - one = one.save(flush:true) - - then:"The are no errors" - one != null - } - - @Override - List getDomainClasses() { - [UniqueGroup, GroupWithin, Driver, License] - } -} - -@Entity -class Driver implements Serializable { - Long id - static hasOne = [license: License] - static constraints = { - license unique: true - } -} - -@Entity -class License implements Serializable { - Long id - Driver driver -} diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy deleted file mode 100644 index 8b4fb738b..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy +++ /dev/null @@ -1,178 +0,0 @@ -package grails.gorm.tests - -import org.springframework.transaction.support.TransactionSynchronizationManager - -/** - * Tests validation semantics. - */ -class ValidationSpec extends GormDatastoreSpec { - - void "Test validate() method"() { - // test assumes name cannot be blank - given: - def t - - when: - t = new TestEntity(name:"") - boolean validationResult = t.validate() - def errors = t.errors - - then: - !validationResult - t.hasErrors() - errors != null - errors.hasErrors() - - when: - t.clearErrors() - - then: - !t.hasErrors() - } - - void 'Test that the binding rejected value is retained after validation'() { - when: - def t = new TestEntity() - t.age = null - t.properties = [age: 'bad value'] - - then: - t.errors.errorCount == 1 - - when: - def ageError = t.errors.getFieldError('age') - - then: - 'bad value' == ageError.rejectedValue - - when: - t.validate() - ageError = t.errors.getFieldError('age') - - then: - 'bad value' == ageError.rejectedValue - } - - void "Test that validate is called on save()"() { - - given: - def t - - when: - t = new TestEntity(name:"") - - then: - t.save() == null - t.hasErrors() == true - 0 == TestEntity.count() - - when: - t.clearErrors() - t.name = "Bob" - t.age = 45 - t.child = new ChildEntity(name:"Fred") - t = t.save() - - then: - t != null - 1 == TestEntity.count() - } - - void "Test beforeValidate gets called on save()"() { - given: - def entityWithNoArgBeforeValidateMethod - def entityWithListArgBeforeValidateMethod - def entityWithOverloadedBeforeValidateMethod - - when: - entityWithNoArgBeforeValidateMethod = new ClassWithNoArgBeforeValidate() - entityWithListArgBeforeValidateMethod = new ClassWithListArgBeforeValidate() - entityWithOverloadedBeforeValidateMethod = new ClassWithOverloadedBeforeValidate() - entityWithNoArgBeforeValidateMethod.save() - entityWithListArgBeforeValidateMethod.save() - entityWithOverloadedBeforeValidateMethod.save() - - then: - 1 == entityWithNoArgBeforeValidateMethod.noArgCounter - 1 == entityWithListArgBeforeValidateMethod.listArgCounter - 1 == entityWithOverloadedBeforeValidateMethod.noArgCounter - 0 == entityWithOverloadedBeforeValidateMethod.listArgCounter - } - - void "Test beforeValidate gets called on validate()"() { - given: - def entityWithNoArgBeforeValidateMethod - def entityWithListArgBeforeValidateMethod - def entityWithOverloadedBeforeValidateMethod - - when: - entityWithNoArgBeforeValidateMethod = new ClassWithNoArgBeforeValidate() - entityWithListArgBeforeValidateMethod = new ClassWithListArgBeforeValidate() - entityWithOverloadedBeforeValidateMethod = new ClassWithOverloadedBeforeValidate() - entityWithNoArgBeforeValidateMethod.validate() - entityWithListArgBeforeValidateMethod.validate() - entityWithOverloadedBeforeValidateMethod.validate() - - then: - 1 == entityWithNoArgBeforeValidateMethod.noArgCounter - 1 == entityWithListArgBeforeValidateMethod.listArgCounter - 1 == entityWithOverloadedBeforeValidateMethod.noArgCounter - 0 == entityWithOverloadedBeforeValidateMethod.listArgCounter - } - - void "Test beforeValidate gets called on validate() and passing a list of field names to validate"() { - given: - def entityWithNoArgBeforeValidateMethod - def entityWithListArgBeforeValidateMethod - def entityWithOverloadedBeforeValidateMethod - - when: - entityWithNoArgBeforeValidateMethod = new ClassWithNoArgBeforeValidate() - entityWithListArgBeforeValidateMethod = new ClassWithListArgBeforeValidate() - entityWithOverloadedBeforeValidateMethod = new ClassWithOverloadedBeforeValidate() - entityWithNoArgBeforeValidateMethod.validate(['name']) - entityWithListArgBeforeValidateMethod.validate(['name']) - entityWithOverloadedBeforeValidateMethod.validate(['name']) - - then: - 1 == entityWithNoArgBeforeValidateMethod.noArgCounter - 1 == entityWithListArgBeforeValidateMethod.listArgCounter - 0 == entityWithOverloadedBeforeValidateMethod.noArgCounter - 1 == entityWithOverloadedBeforeValidateMethod.listArgCounter - ['name'] == entityWithOverloadedBeforeValidateMethod.propertiesPassedToBeforeValidate - } - - void "Test that validate works without a bound Session"() { - - given: - def t - - when: - session.disconnect() - if (TransactionSynchronizationManager.hasResource(session.datastore)) { - TransactionSynchronizationManager.unbindResource(session.datastore) - } - - t = new TestEntity(name:"") - - then: - !session.datastore.hasCurrentSession() - t.save() == null - t.hasErrors() == true - 1 == t.errors.allErrors.size() - TestEntity.getValidationErrorsMap().get(System.identityHashCode(t)).is(t.errors) - 0 == TestEntity.count() - - when: - t.clearErrors() - t.name = "Bob" - t.age = 45 - t.child = new ChildEntity(name:"Fred") - t = t.save(flush: true) - - then: - !session.datastore.hasCurrentSession() - t != null - 1 == TestEntity.count() - } -} diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/orm/PagedResultListTests.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/grails/orm/PagedResultListTests.groovy deleted file mode 100644 index aecc9c866..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/grails/orm/PagedResultListTests.groovy +++ /dev/null @@ -1,40 +0,0 @@ -package grails.orm - -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate -import org.hibernate.internal.CriteriaImpl - -/** - * @author Burt Beckwith - */ -class PagedResultListTests extends GroovyTestCase { - - void testSerialize() { - - def list = new TestPagedResultList() - - new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(list) - - assertTrue list.totalCountCalled - } -} - -class TestCriteria extends CriteriaImpl { - TestCriteria() { super(null, null) } - @Override - List list() { /* do nothing */ } -} - -class TestPagedResultList extends PagedResultList { - - private boolean totalCountCalled = false - - TestPagedResultList() { - super(new GrailsHibernateTemplate(), new TestCriteria()) - } - - @Override - int getTotalCount() { - totalCountCalled = true - 42 - } -} 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 deleted file mode 100644 index 89fc84ca9..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformerSpec.groovy +++ /dev/null @@ -1,180 +0,0 @@ -package org.codehaus.groovy.grails.compiler.gorm - -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.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.GormValidationApi -import org.grails.datastore.mapping.simple.SimpleMapDatastore -import org.springframework.validation.Errors - -import spock.lang.Specification -import grails.spring.BeanBuilder -import org.springframework.context.ConfigurableApplicationContext - -class GormTransformerSpec extends Specification { - - private alwaysInjectGormTransformer = new GormTransformer() { - boolean shouldInject(URL url) { true } - } - - private GrailsAwareClassLoader gcl = new GrailsAwareClassLoader() - - void "Test missing method thrown for uninitialized entity"() { - given: - gcl.classInjectors = [alwaysInjectGormTransformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -@grails.persistence.Entity -class TestEntity { - Long id -} - ''') - cls.load(1) - then: - def e = thrown(MissingMethodException) - e.message.contains '''No signature of method: TestEntity.load() is applicable for argument types''' - } - - void "Test that generic information is added to hasMany collections"() { - given: - def domainTransformer = new DefaultGrailsDomainClassInjector() { - boolean shouldInject(URL url) { true } - } - gcl.classInjectors = [alwaysInjectGormTransformer, domainTransformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -@grails.persistence.Entity -class TestEntity { - Long id - - static hasMany = [associated:Associated] -} - -@grails.persistence.Entity -class Associated { - Long id -} - ''') - - then: - cls.getAnnotation(Entity) != null - cls.getDeclaredField("associated") != null - cls.getDeclaredField("associated").genericType != null - cls.getDeclaredField("associated").genericType.getActualTypeArguments()[0] == gcl.loadClass("Associated") - } - - void "Test that only one annotation is added on already annotated entity"() { - given: - gcl.classInjectors = [alwaysInjectGormTransformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -@grails.persistence.Entity -class TestEntity { - Long id -} - ''') - - then: - cls.getAnnotation(Entity) != null - } - - void "Test transforming a @grails.persistence.Entity marked class doesn't generate duplication methods"() { - given: - gcl.classInjectors = [alwaysInjectGormTransformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -@grails.persistence.Entity -class TestEntity { - Long id -} - ''') - - then: - cls - } - - void "Test that GORM static methods are available on transformation"() { - given: - gcl.classInjectors = [alwaysInjectGormTransformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -class TestEntity { - Long id -} - ''') - cls.count() - - then: - thrown MissingMethodException - - when: - cls.metaClass.static.currentGormStaticApi = {-> null} - cls.count() - - then: - thrown MissingMethodException - - when: - def ds = new SimpleMapDatastore() - ds.mappingContext.addPersistentEntity(cls) - - cls.metaClass.static.currentGormStaticApi = {-> new GormStaticApi(cls, ds, [])} - - then: - cls.count() == 0 - } - - void "Test that the new Errors property is valid"() { - given: - def transformer = new GormValidationTransformer() { - boolean shouldInject(URL url) { true } - } - gcl.classInjectors = [transformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -class TestEntity { - Long id - Long version - String name -} - ''') - def dc = new DefaultGrailsDomainClass(cls) - - then: - dc.persistentProperties.size() == 1 - - when: - def obj = dc.newInstance() - - then: - obj != null - obj.errors instanceof Errors - - when: - def ds = new SimpleMapDatastore(new BeanBuilder().createApplicationContext() as ConfigurableApplicationContext) - - cls.metaClass.static.currentGormValidationApi = {-> new GormValidationApi(cls, ds)} - obj.clearErrors() - - then: - obj.errors.hasErrors() == false - obj.hasErrors() == false - - when: - Errors errors = obj.errors - errors.reject("bad") - - then: - obj.hasErrors() == true - } -} 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 deleted file mode 100644 index 702d3a8c9..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformerSpec.groovy +++ /dev/null @@ -1,43 +0,0 @@ -package org.codehaus.groovy.grails.compiler.gorm - -import org.codehaus.groovy.grails.compiler.injection.ClassInjector -import org.codehaus.groovy.grails.compiler.injection.GrailsAwareClassLoader -import org.grails.datastore.gorm.GormValidationApi -import org.grails.datastore.mapping.simple.SimpleMapDatastore - -import spock.lang.Specification - -class GormValidationTransformerSpec extends Specification { - - void "Test that the validate methods are available via an AST transformation"() { - given: - def gcl = new GrailsAwareClassLoader() - def transformer = new GormValidationTransformer() { - boolean shouldInject(URL url) { true } - } - gcl.classInjectors = [transformer] as ClassInjector[] - - when: - def cls = gcl.parseClass(''' -class TestEntity { - Long id - - String name -} - ''') - def obj = cls.newInstance() - obj.validate() - - then: - thrown IllegalStateException - - when: - - def ds = new SimpleMapDatastore() - ds.mappingContext.addPersistentEntity(cls) - cls.metaClass.static.currentGormValidationApi = {-> new GormValidationApi(cls, ds)} - - then: - obj.validate() == true - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/SessionFactoryProxySpec.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/SessionFactoryProxySpec.groovy deleted file mode 100644 index a6cc5c850..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/codehaus/groovy/grails/compiler/gorm/SessionFactoryProxySpec.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package org.codehaus.groovy.grails.compiler.gorm - -import grails.spring.BeanBuilder - -import org.codehaus.groovy.grails.orm.hibernate.SessionFactoryHolder -import org.codehaus.groovy.grails.orm.hibernate.SessionFactoryProxy -import org.hibernate.dialect.H2Dialect -import org.springframework.context.ApplicationContext -import org.springframework.orm.hibernate4.LocalSessionFactoryBean - -import spock.lang.Specification - - /** - * Tests for the SessionFactoryProxy class - */ -class SessionFactoryProxySpec extends Specification { - - void "Ensure that SessionFactoryProxy patches SessionFactoryImpl with an appropriate SpringSessionContext"() { - given: - def ctx = applicationContext - when: - def sessionFactory = ctx.getBean("sessionFactoryHolder").sessionFactory - def sessionFactoryProxy = ctx.getBean("sessionFactoryProxy") - - then: - sessionFactory.@currentSessionContext.@sessionFactory == sessionFactoryProxy - } - - void "Verify that we can access other properties of the SessionFactoryImpl via the proxy in Groovy code"() { - given: - def ctx = applicationContext - def sessionFactoryProxy = ctx.getBean("sessionFactoryProxy") - - when: - def transactionEnvironment = sessionFactoryProxy.transactionEnvironment - - then: - transactionEnvironment != null - } - - ApplicationContext getApplicationContext() { - BeanBuilder bb = new BeanBuilder() - bb.beans { - - sessionFactoryHolder(SessionFactoryHolder) { - sessionFactory = bean(LocalSessionFactoryBean) { - hibernateProperties = ["hibernate.dialect":H2Dialect.name] - } - } - - sessionFactoryProxy(SessionFactoryProxy) { - targetBean = "sessionFactoryHolder" - } - } - bb.createApplicationContext() - } -} diff --git a/grails-datastore-gorm-hibernate4/src/test/groovy/org/grails/datastore/gorm/HibernateSuite.groovy b/grails-datastore-gorm-hibernate4/src/test/groovy/org/grails/datastore/gorm/HibernateSuite.groovy deleted file mode 100644 index 003fed1fc..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/grails/datastore/gorm/HibernateSuite.groovy +++ /dev/null @@ -1,60 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.AttachMethodSpec -import grails.gorm.tests.CircularOneToManySpec -import grails.gorm.tests.CommonTypesPersistenceSpec -import grails.gorm.tests.CriteriaBuilderSpec -import grails.gorm.tests.CrudOperationsSpec -import grails.gorm.tests.DomainEventsSpec -import grails.gorm.tests.FindByMethodSpec -import grails.gorm.tests.GormEnhancerSpec -import grails.gorm.tests.GroovyProxySpec -import grails.gorm.tests.InheritanceSpec -import grails.gorm.tests.ListOrderBySpec -import grails.gorm.tests.NamedQuerySpec -import grails.gorm.tests.NegationSpec -import grails.gorm.tests.OneToManySpec -import grails.gorm.tests.OrderBySpec -import grails.gorm.tests.ProxyLoadingSpec -import grails.gorm.tests.QueryAfterPropertyChangeSpec -import grails.gorm.tests.RangeQuerySpec -import grails.gorm.tests.SaveAllSpec -import grails.gorm.tests.UpdateWithProxyPresentSpec -import grails.gorm.tests.ValidationSpec -import grails.gorm.tests.WithTransactionSpec -import grails.gorm.tests.DeleteAllSpec - -import org.junit.runner.RunWith -import org.junit.runners.Suite -import org.junit.runners.Suite.SuiteClasses - -@RunWith(Suite) -@SuiteClasses([ -// ValidationSpec, -// GroovyProxySpec, -// CommonTypesPersistenceSpec, -// OneToManySpec, -// SaveAllSpec, -// GormEnhancerSpec, -// DomainEventsSpec, -// ProxyLoadingSpec, -// QueryAfterPropertyChangeSpec, -// CircularOneToManySpec, -// InheritanceSpec, -// FindByMethodSpec, -// ListOrderBySpec, -// CriteriaBuilderSpec, -// NegationSpec, -// NamedQuerySpec, -// OrderBySpec, -// RangeQuerySpec, -// UpdateWithProxyPresentSpec, -// AttachMethodSpec, -// WithTransactionSpec, -// CrudOperationsSpec, -// SaveAllSpec, -// DeleteAllSpec -]) -class HibernateSuite { - -} 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 deleted file mode 100644 index b2445ed5a..000000000 --- a/grails-datastore-gorm-hibernate4/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ /dev/null @@ -1,196 +0,0 @@ -package org.grails.datastore.gorm - -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.metaclass.MetaClassEnhancer -import org.codehaus.groovy.grails.domain.GrailsDomainClassMappingContext -import org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTransactionManager -import org.codehaus.groovy.grails.orm.hibernate.GrailsSessionContext -import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore -import org.codehaus.groovy.grails.orm.hibernate.HibernateGormEnhancer -import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration -import org.codehaus.groovy.grails.orm.hibernate.cfg.HibernateUtils -import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor -import org.codehaus.groovy.grails.orm.hibernate.validation.HibernateConstraintsEvaluator -import org.codehaus.groovy.grails.orm.hibernate.validation.PersistentConstraintFactory -import org.codehaus.groovy.grails.orm.hibernate.validation.UniqueConstraint -import org.codehaus.groovy.grails.plugins.web.api.ControllersDomainBindingApi -import org.codehaus.groovy.grails.validation.ConstrainedProperty -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.model.MappingContext -import org.h2.Driver -import org.hibernate.SessionFactory -import org.hibernate.cfg.AvailableSettings -import org.hibernate.dialect.H2Dialect -import org.hibernate.event.service.spi.EventListenerRegistry -import org.hibernate.event.spi.EventType -import org.hibernate.service.ServiceRegistry -import org.springframework.beans.BeanUtils -import org.springframework.beans.BeanWrapper -import org.springframework.beans.BeanWrapperImpl -import org.springframework.beans.factory.config.BeanDefinition -import org.springframework.beans.factory.support.AbstractBeanDefinition -import org.springframework.beans.factory.support.GenericBeanDefinition -import org.springframework.context.ApplicationContext -import org.springframework.context.support.GenericApplicationContext -import org.springframework.jdbc.datasource.DriverManagerDataSource -import org.springframework.orm.hibernate4.SessionFactoryUtils -import org.springframework.transaction.TransactionStatus -import org.springframework.transaction.support.DefaultTransactionDefinition -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -class Setup { - static HibernateDatastore hibernateDatastore - static hibernateSession - static GrailsHibernateTransactionManager transactionManager - static TransactionStatus transactionStatus - - static destroy() { - try { - if (hibernateSession != null) { - SessionFactoryUtils.releaseSession hibernateSession, hibernateDatastore.sessionFactory - } - } - finally { - if (transactionStatus) { - try { - transactionManager.rollback(transactionStatus) - } - finally { - transactionStatus = null - } - } - } - } - - static Session setup(List classes) { - - def grailsApplication = new DefaultGrailsApplication(classes as Class[], Setup.getClassLoader()) - def ctx = new GenericApplicationContext() - - grailsApplication.applicationContext = ctx - grailsApplication.mainContext = ctx - grailsApplication.initialise() - ctx.beanFactory.registerSingleton 'grailsApplication', grailsApplication - - for (GrailsDomainClass dc in grailsApplication.domainClasses) { - if (!dc.abstract) { - ctx.registerBeanDefinition dc.clazz.name, new GenericBeanDefinition( - autowireMode: AbstractBeanDefinition.AUTOWIRE_BY_NAME, - beanClass: dc.clazz, - scope: BeanDefinition.SCOPE_PROTOTYPE) - } - } - ctx.refresh() - - String dbUrl = "jdbc:h2:mem:devDB;MVCC=true" - - def config = new Properties() - config.setProperty AvailableSettings.DIALECT, H2Dialect.name - config.setProperty AvailableSettings.DRIVER, Driver.name - config.setProperty AvailableSettings.URL, dbUrl - config.setProperty AvailableSettings.USER, "sa" - config.setProperty AvailableSettings.PASS, "" - config.setProperty AvailableSettings.HBM2DDL_AUTO, "create-drop" - config.setProperty AvailableSettings.SHOW_SQL, "true" - config.setProperty AvailableSettings.FORMAT_SQL, "true" - config.setProperty AvailableSettings.CURRENT_SESSION_CONTEXT_CLASS, GrailsSessionContext.name - - GrailsAnnotationConfiguration hibernateConfig = new GrailsAnnotationConfiguration() - hibernateConfig.setProperties config - - hibernateConfig.grailsApplication = grailsApplication - - def context = new GrailsDomainClassMappingContext(grailsApplication) - ctx.beanFactory.registerSingleton 'grailsDomainClassMappingContext', context - - SessionFactory sessionFactory = hibernateConfig.buildSessionFactory() - ctx.beanFactory.registerSingleton 'sessionFactory', sessionFactory - - transactionManager = new GrailsHibernateTransactionManager(sessionFactory: sessionFactory) - ctx.beanFactory.registerSingleton 'transactionManager', transactionManager - - hibernateDatastore = new HibernateDatastore(context, sessionFactory, grailsApplication.config, ctx) - ctx.beanFactory.registerSingleton 'hibernateDatastore', hibernateDatastore - - ctx.beanFactory.registerSingleton 'dataSource', new DriverManagerDataSource(Driver.name, dbUrl, 'sa', '') - - def eventTriggeringInterceptor = new ClosureEventTriggeringInterceptor(applicationContext: ctx) - ServiceRegistry serviceRegistry = hibernateConfig.serviceRegistry - EventListenerRegistry listenerRegistry = serviceRegistry.getService(EventListenerRegistry) - for (type in [EventType.PRE_LOAD, EventType.POST_LOAD, EventType.SAVE, EventType.SAVE_UPDATE, - EventType.PRE_INSERT, EventType.POST_INSERT, EventType.PRE_UPDATE, - EventType.PRE_DELETE, EventType.POST_UPDATE, EventType.POST_DELETE]) { - listenerRegistry.appendListeners type, eventTriggeringInterceptor - } - - eventTriggeringInterceptor.datastores = [(sessionFactory): hibernateDatastore] - ctx.beanFactory.registerSingleton 'eventTriggeringInterceptor', eventTriggeringInterceptor - - def metaClassEnhancer = new MetaClassEnhancer() - metaClassEnhancer.addApi new ControllersDomainBindingApi() - - HibernateConstraintsEvaluator evaluator = new HibernateConstraintsEvaluator() - grailsApplication.domainClasses.each { GrailsDomainClass dc -> - if (dc.abstract) { - return - } - - metaClassEnhancer.enhance dc.metaClass - - def validator = [supports: { Class c -> true}, validate: { target, Errors errors -> - for (ConstrainedProperty cp in evaluator.evaluate(dc.clazz).values()) { - cp.validate(target, target[cp.propertyName], errors) - } - }] as Validator - - dc.validator = validator - - dc.metaClass.constructor = { -> - def obj - if (ctx.containsBean(dc.fullName)) { - obj = ctx.getBean(dc.fullName) - } - else { - obj = BeanUtils.instantiateClass(dc.clazz) - } - obj - } - } - - def enhancer = new HibernateGormEnhancer(hibernateDatastore, transactionManager, grailsApplication) - enhancer.enhance() - - hibernateDatastore.mappingContext.addMappingContextListener({ e -> - enhancer.enhance e - } as MappingContext.Listener) - - transactionManager = new GrailsHibernateTransactionManager(sessionFactory: sessionFactory) - if (transactionStatus == null) { - transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition()) - } - else { - throw new RuntimeException("new transaction started during active transaction") - } - - hibernateSession = sessionFactory.getCurrentSession() - - ApplicationContext.metaClass.getProperty = { String name -> - if (delegate.containsBean(name)) { - return delegate.getBean(name) - } - BeanWrapper bw = new BeanWrapperImpl(delegate) - if (bw.isReadableProperty(name)) { - return bw.getPropertyValue(name) - } - } - - HibernateUtils.enhanceSessionFactories(ctx, grailsApplication) - - ConstrainedProperty.registerNewConstraint(UniqueConstraint.UNIQUE_CONSTRAINT, - new PersistentConstraintFactory(ctx, UniqueConstraint)) - - return hibernateDatastore.connect() - } -} diff --git a/grails-datastore-gorm-jcr/build.gradle b/grails-datastore-gorm-jcr/build.gradle deleted file mode 100644 index 3df5587fb..000000000 --- a/grails-datastore-gorm-jcr/build.gradle +++ /dev/null @@ -1,7 +0,0 @@ -dependencies { - compile project(":grails-datastore-gorm"), - project(":grails-datastore-jcr"), - project(":grails-datastore-core") - testCompile project(":grails-datastore-gorm-test"), - project(":grails-datastore-gorm-tck") -} 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 c7e431bfc..000000000 --- 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-jcr/src/main/groovy/org/grails/datastore/gorm/jcr/JcrGormEnhancer.groovy b/grails-datastore-gorm-jcr/src/main/groovy/org/grails/datastore/gorm/jcr/JcrGormEnhancer.groovy deleted file mode 100644 index e749679bd..000000000 --- a/grails-datastore-gorm-jcr/src/main/groovy/org/grails/datastore/gorm/jcr/JcrGormEnhancer.groovy +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2010 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.jcr - -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.jcr.JcrSession -import org.springframework.transaction.PlatformTransactionManager - -/** - * Adds JCR specific functionality to GORM - * - * @author Erawat Chamanont - * @since 1.0 - */ -class JcrGormEnhancer extends GormEnhancer{ - - JcrGormEnhancer(Datastore datastore) { - super(datastore); - } - - JcrGormEnhancer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager); - } - - protected GormStaticApi getStaticApi(Class cls) { - return new JcrGormStaticApi(cls, datastore, finders) - } - - protected GormInstanceApi getInstanceApi(Class cls) { - return new JcrGormInstanceApi(cls, datastore) - } -} -class JcrGormInstanceApi extends GormInstanceApi { - - JcrGormInstanceApi(Class persistentClass, Datastore datastore) { - super(persistentClass, datastore); - } - - def expire(instance, int ttl) { - JcrSession session = datastore.currentSession - - session.expire instance, ttl - } -} - -class JcrGormStaticApi extends GormStaticApi { - JcrGormStaticApi(Class persistentClass, Datastore datastore, List finders) { - super(persistentClass, datastore, finders); - } - - /** - * Expires an entity for the given id and TTL - */ - void expire(Serializable id, int ttl) { - JcrSession session = datastore.currentSession - - session.expire(persistentClass, id, ttl) - } - - /** - * A random domain class instance is returned - * @return A random domain class - */ - def random() { - JcrSession session = datastore.currentSession - - return session.random(persistentClass) - } - - /** - * A random domain class instance is removed and returned - * @return A random removed domain class - */ - def pop() { - JcrSession session = datastore.currentSession - - return session.pop(persistentClass) - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Book.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Book.groovy deleted file mode 100644 index 713b2aecc..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Book.groovy +++ /dev/null @@ -1,13 +0,0 @@ -@grails.persistence.Entity -class Book implements Serializable { - String id - String author - String title - Boolean published - - static mapping = { - published index:true - title index:true - author index:true - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/ChildEntity.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/ChildEntity.groovy deleted file mode 100644 index 093267c1d..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/ChildEntity.groovy +++ /dev/null @@ -1,19 +0,0 @@ -package grails.gorm.tests - -/** - * Override from GORM TCK to test String based Id - * - * @author Erawat Chamanont - * @since 1.0 - */ -@grails.persistence.Entity -class ChildEntity implements Serializable { - String id - String name - - static mapping = { - name index:true - } - - static belongsTo = [TestEntity] -} \ No newline at end of file diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/CommonTypes.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/CommonTypes.groovy deleted file mode 100644 index 7c222a936..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/CommonTypes.groovy +++ /dev/null @@ -1,19 +0,0 @@ -@grails.persistence.Entity -class CommonTypes implements Serializable{ - Long id - Long l - Byte b - Short s - Boolean bool - Integer i - URL url - Date date - Calendar c - BigDecimal bd - BigInteger bi - Double d - Float f - TimeZone tz - Locale loc - Currency cur -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/CommonTypesPersistenceSpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/CommonTypesPersistenceSpec.groovy deleted file mode 100644 index c0d0a1ee0..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/CommonTypesPersistenceSpec.groovy +++ /dev/null @@ -1,72 +0,0 @@ -package grails.gorm.tests - -/** - * @author graemerocher - */ -class CommonTypesPersistenceSpec extends GormDatastoreSpec { - - def testPersistBasicTypes() { - given: - def now = new Date() - def cal = new GregorianCalendar() - def ct = new CommonTypes( - l: 10L, - b: 10 as byte, - s: 10 as short, - bool: true, - i: 10, - url: new URL("http://google.com"), - date: now, - c: cal, - bd: 1.0, - bi: 10 as BigInteger, - d: 1.0 as Double, - f: 1.0 as Float, - tz: TimeZone.getTimeZone("GMT"), - loc: Locale.UK, - cur: Currency.getInstance("USD") - ) - - when: - ct.save(flush:true) - ct.discard() - ct = CommonTypes.get(ct.id) - - then: - ct - 10L == ct.l - (10 as byte) == ct.b - (10 as short) == ct.s - true == ct.bool - 10 == ct.i - new URL("http://google.com") == ct.url - now == ct.date - cal == ct.c - 1.0 == ct.bd - 10 as BigInteger == ct.bi - (1.0 as Double) == ct.d - (1.0 as Float) == ct.f - TimeZone.getTimeZone("GMT") == ct.tz - Locale.UK == ct.loc - Currency.getInstance("USD") == ct.cur - } -} - -class CommonTypes implements Serializable { - String id - Long l - Byte b - Short s - Boolean bool - Integer i - URL url - Date date - Calendar c - BigDecimal bd - BigInteger bi - Double d - Float f - TimeZone tz - Locale loc - Currency cur -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy deleted file mode 100644 index c84147aed..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy +++ /dev/null @@ -1,261 +0,0 @@ -package grails.gorm.tests - -/** - * Abstract base test for criteria queries. Subclasses should do the necessary setup to configure GORM - */ -class CriteriaBuilderSpec extends GormDatastoreSpec { - - def cleanup() { - def nativeSession = session.nativeInterface - def wp = nativeSession.getWorkspace(); - def qm = wp.getQueryManager(); - - def q = qm.createQuery("//ChildEntity", javax.jcr.query.Query.XPATH); - def qr = q.execute() - def itr = qr.getNodes(); - itr.each { it.remove() } - - q = qm.createQuery("//TestEntity", javax.jcr.query.Query.XPATH); - qr = q.execute() - itr = qr.getNodes(); - itr.each { it.remove() } - } - - def "Test id projection"() { - given: - def entity = new TestEntity(name:"Bob", age: 44, child:new ChildEntity(name:"Child")).save(flush:true) - - when: - def result = TestEntity.createCriteria().get { - projections { id() } - idEq entity.id - } - - then: - result != null - result == entity.id - } - - def "Test idEq method"() { - given: - def entity = new TestEntity(name:"Bob", age: 44, child:new ChildEntity(name:"Child")).save(flush:true) - - when: - def result = TestEntity.createCriteria().get { idEq entity.id } - - then: - result != null - result.name == 'Bob' - } - - def "Test disjunction query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - or { - like('name', 'B%') - eq('age', 41) - } - } - - then: - 3 == results.size() - } - - void "Test conjunction query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - and { - like('name', 'B%') - eq('age', 40) - } - } - - then: - 1 == results.size() - } - - void "Test list() query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { like('name', 'B%') } - - then: - 2 == results.size() - - when: - results = criteria.list { - like('name', 'B%') - max 1 - } - - then: - 1 == results.size() - } - - void "Test count()"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def result = criteria.count { like('name', 'B%') } - - then: - 2 == result - } - - void "Test obtain a single result"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def result = criteria.get { eq('name', 'Bob') } - - then: - result != null - "Bob" == result.name - } - - void "Test order by a property name"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - like('name', 'B%') - order "age" - } - - then: - "Bob" == results[0].name - "Barney" == results[1].name - - when: - results = criteria.list { - like('name', 'B%') - order "age", "desc" - } - - then: - "Barney" == results[0].name - "Bob" == results[1].name - } - - - void "Test get minimum value with projection"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def result = criteria.get { - projections { min "age" } - } - - then: - 40 == result - - when: - result = criteria.get { - projections { max "age" } - } - - then: - 43 == result - - when: - def results = criteria.list { - projections { - max "age" - min "age" - } - } - - then: - 2 == results.size() - 43 == results[0] - 40 == results[1] - [43, 40]== results - } - - void "Test obtain property value using projection"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - projections { property "age" } - } - - then: - [40, 41, 42, 43] == results.sort() - } - - void "Test obtain association entity using property projection"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - assert 4 == ChildEntity.count() - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - projections { property "child" } - } - - then: - results.find { it.name = "Bob Child"} - results.find { it.name = "Fred Child"} - results.find { it.name = "Barney Child"} - results.find { it.name = "Frank Child"} - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/CrudOperationsSpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/CrudOperationsSpec.groovy deleted file mode 100644 index fd86fc5b0..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/CrudOperationsSpec.groovy +++ /dev/null @@ -1,75 +0,0 @@ -package grails.gorm.tests - -/** - * Override from GORM TCK to test String based Id - * - * @author Erawat Chamanont - * @since 1.0 - */ -class CrudOperationsSpec extends GormDatastoreSpec { - - def cleanup() { - def nativeSession = session.nativeInterface - def wp = nativeSession.getWorkspace(); - def qm = wp.getQueryManager(); - - def q = qm.createQuery("//TestEntity", javax.jcr.query.Query.XPATH); - def qr = q.execute() - def itr = qr.getNodes(); - itr.each { it.remove() } - } - - void "Test get using a string-based key"() { - given: - def t = new TestEntity(name: "Bob", child: new ChildEntity(name: "Child")) - t.save() - - when: - //No converter found capable of converting from 'org.codehaus.groovy.runtime.GStringImpl' to 'java.lang.String - //t = TestEntity.get("${t.id}") - //id is a String-based key - t = TestEntity.get(t.id); - - then: - t != null - } - - void "Test get returns null of non-existent entity"() { - given: - def t - when: - //JCR plugin supports only get() by using value UUID - t = TestEntity.get("19503d32-fb94-4f85-b50c-681e6f1a02f2"); - then: - t == null - } - - void "Test basic CRUD operations"() { - given: - - def t = new TestEntity(name: "Bob", child: new ChildEntity(name: "Child")) - t.save() - - when: - def results = TestEntity.list() - t = TestEntity.get(t.id) - - then: - t != null - t.id != null - "Bob" == t.name - 1 == results.size() - "Bob" == results[0].name - } - - void "Test save method that takes a map"() { - - given: - def t = new TestEntity(name: "Bob", child: new ChildEntity(name: "Child")) - t.save(param: "one") - when: - t = TestEntity.get(t.id) - then: - t.id != null - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/DomainEventsSpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/DomainEventsSpec.groovy deleted file mode 100644 index c03dd57ec..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/DomainEventsSpec.groovy +++ /dev/null @@ -1,210 +0,0 @@ -package grails.gorm.tests - -import org.grails.datastore.gorm.events.AutoTimestampInterceptor -import org.grails.datastore.gorm.events.DomainEventInterceptor -import org.grails.datastore.mapping.core.Session - -/** - * Override from GORM TCK to test JCR datastore - * - * @author Erawat Chamanont - * @since 1.0 - */ -class DomainEventsSpec extends GormDatastoreSpec { - - def cleanup() { - def nativeSession = session.nativeInterface - def wp = nativeSession.getWorkspace(); - def qm = wp.getQueryManager(); - - def q = qm.createQuery("//ModifyPerson", javax.jcr.query.Query.XPATH); - def qr = q.execute() - def itr = qr.getNodes(); - itr.each { it.remove() } - - q = qm.createQuery("//PersonEvent", javax.jcr.query.Query.XPATH); - qr = q.execute() - itr = qr.getNodes(); - itr.each { it.remove() } - nativeSession.save() - } - - Session setupEventsSession() { - def datastore = session.datastore - datastore.addEntityInterceptor(new DomainEventInterceptor()) - datastore.addEntityInterceptor(new AutoTimestampInterceptor()) - session; - /* - session= datastore.connect([username:"username", - password:"password", - workspace:"default", - configuration:"classpath:repository.xml", - homeDir:"/temp/repo"]) - */ - } - - void "Test modify property before save"() { - given: - session = setupEventsSession() - session.datastore.mappingContext.addPersistentEntity(ModifyPerson) - def p = new ModifyPerson(name:"Bob").save(flush:true) - session.clear() - - when: - p = ModifyPerson.get(p.id) - - then: - p.name == "Fred" - } - - void "Test auto time stamping working"() { - - given: - session = setupEventsSession() - - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - sleep(2000) - - p.dateCreated == p.lastUpdated - - when: - p.name = "Wilma" - p.save(flush:true) - - then: - p.dateCreated.before(p.lastUpdated) == true - } - -// void testOnloadEvent() { -// def personClass = ga.getDomainClass("PersonEvent") -// def p = personClass.newInstance() -// -// p.name = "Fred" -// p.save() -// session.flush() -// session.clear() -// -// p = personClass.clazz.get(1) -// assertEquals "Bob", p.name -// } - - void "Test before delete event"() { - given: - session = setupEventsSession() - PersonEvent.resetStore() - def p = new PersonEvent() - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p.delete(flush:true) - - then: - assert PersonEvent.STORE['deleted'] == true - } - - void "Test before update event"() { - given: - session = setupEventsSession() - PersonEvent.resetStore() - - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - 0 == PersonEvent.STORE['updated'] - - when: - p.name = "Bob" - p.save(flush:true) - session.clear() - p = PersonEvent.get(p.id) - then: - "Bob" == p.name - 1 == PersonEvent.STORE['updated'] - } - - void "Test before insert event"() { - given: - session = setupEventsSession() - PersonEvent.resetStore() - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - 0 == PersonEvent.STORE['updated'] - 1 == PersonEvent.STORE['inserted'] - - when: - p.name = "Bob" - p.save(flush:true) - session.clear() - p = PersonEvent.get(p.id) - - then: - "Bob" == p.name - 1 == PersonEvent.STORE['updated'] - 1 == PersonEvent.STORE['inserted'] - } -} - -class PersonEvent implements Serializable { - //Long id - String id - Long version - String name - Date dateCreated - Date lastUpdated - - static STORE = [updated:0, inserted:0] - - static void resetStore() { STORE = [updated:0, inserted:0] } - - def beforeDelete() { - STORE["deleted"] = true - } - - def beforeUpdate() { - STORE["updated"]++ - } - - def beforeInsert() { - STORE["inserted"]++ - } -} - -class ModifyPerson implements Serializable { - //Long id - String id - Long version - - String name - - def beforeInsert() { - name = "Fred" - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/FindByMethodSpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/FindByMethodSpec.groovy deleted file mode 100644 index c69e35755..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/FindByMethodSpec.groovy +++ /dev/null @@ -1,196 +0,0 @@ -package grails.gorm.tests - -/** - * Override from GORM TCK to test String based Id for FindByMethodSpec - * - * @author Erawat Chamanont - * @since 1.0 - */ -class FindByMethodSpec extends GormDatastoreSpec{ - - def cleanup() { - def nativeSession = session.nativeInterface - def wp = nativeSession.getWorkspace(); - def qm = wp.getQueryManager(); - - def q = qm.createQuery("//Highway", javax.jcr.query.Query.XPATH); - def qr = q.execute() - def itr = qr.getNodes(); - itr.each { it.remove() } - - q = qm.createQuery("//Book", javax.jcr.query.Query.XPATH); - qr = q.execute() - itr = qr.getNodes(); - itr.each { it.remove() } - nativeSession.save() - } - - void testBooleanPropertyQuery() { - given: - new Highway(bypassed: true, name: 'Bypassed Highway').save() - new Highway(bypassed: true, name: 'Bypassed Highway').save() - new Highway(bypassed: false, name: 'Not Bypassed Highway').save() - new Highway(bypassed: false, name: 'Not Bypassed Highway').save() - - when: - def highways= Highway.findAllBypassedByName('Not Bypassed Highway') - - then: - 0 == highways.size() - - when: - highways = Highway.findAllNotBypassedByName('Not Bypassed Highway') - - then: - 2 == highways?.size() - 'Not Bypassed Highway' == highways[0].name - 'Not Bypassed Highway'== highways[1].name - - when: - highways = Highway.findAllBypassedByName('Bypassed Highway') - - then: - 2 == highways?.size() - 'Bypassed Highway'== highways[0].name - 'Bypassed Highway'== highways[1].name - - when: - highways = Highway.findAllNotBypassedByName('Bypassed Highway') - then: - assert 0 == highways?.size() - - when: - highways = Highway.findAllBypassed() - then: - 2 ==highways?.size() - 'Bypassed Highway'== highways[0].name - 'Bypassed Highway'==highways[1].name - - when: - highways = Highway.findAllNotBypassed() - then: - 2 == highways?.size() - 'Not Bypassed Highway' == highways[0].name - 'Not Bypassed Highway'== highways[1].name - - when: - def highway = Highway.findNotBypassed() - then: - 'Not Bypassed Highway' == highway?.name - - when: - highway = Highway.findBypassed() - then: - 'Bypassed Highway' == highway?.name - - when: - highway = Highway.findNotBypassedByName('Not Bypassed Highway') - then: - 'Not Bypassed Highway' == highway?.name - - when: - highway = Highway.findBypassedByName('Bypassed Highway') - then: - 'Bypassed Highway' == highway?.name - - when: - Book.newInstance(author: 'Jeff', title: 'Fly Fishing For Everyone', published: false).save() - Book.newInstance(author: 'Jeff', title: 'DGGv2', published: true).save() - Book.newInstance(author: 'Graeme', title: 'DGGv2', published: true).save() - Book.newInstance(author: 'Dierk', title: 'GINA', published: true).save() - - def book = Book.findPublishedByAuthor('Jeff') - then: - 'Jeff' == book.author - 'DGGv2'== book.title - - when: - book = Book.findPublishedByAuthor('Graeme') - then: - 'Graeme' == book.author - 'DGGv2'== book.title - - when: - book = Book.findPublishedByTitleAndAuthor('DGGv2', 'Jeff') - then: - 'Jeff'== book.author - 'DGGv2'== book.title - - when: - book = Book.findNotPublishedByAuthor('Jeff') - then: - 'Fly Fishing For Everyone'== book.title - -// when: -// book = Book.findPublishedByTitleOrAuthor('Fly Fishing For Everyone', 'Dierk') -// then: -// 'GINA'== book.title -// Book.findPublished() != null - - when: - book = Book.findNotPublished() - then: - 'Fly Fishing For Everyone' == book?.title - - when: - def books = Book.findAllPublishedByTitle('DGGv2') - then: - 2 == books?.size() - - when: - books = Book.findAllPublished() - then: - 3 == books?.size() - - when: - books = Book.findAllNotPublished() - then: - 1 == books?.size() - - when: - books = Book.findAllPublishedByTitleAndAuthor('DGGv2', 'Graeme') - then: - 1 == books?.size() - -// when: -// books = Book.findAllPublishedByAuthorOrTitle('Graeme', 'GINA') -// then: -// 2 == books?.size() - - when: - books = Book.findAllNotPublishedByAuthor('Jeff') - then: - 1 == books?.size() - - when: - books = Book.findAllNotPublishedByAuthor('Graeme') - then: - assert 0 == books?.size() - } -} - -class Highway implements Serializable { - //Long id - String id - Boolean bypassed - String name - - static mapping = { - bypassed index:true - name index:true - } -} - -class Book implements Serializable { - //Long id - String id - String author - String title - Boolean published - - static mapping = { - published index:true - title index:true - author index:true - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/GormEnhancerSpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/GormEnhancerSpec.groovy deleted file mode 100644 index d5b92bf33..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/GormEnhancerSpec.groovy +++ /dev/null @@ -1,220 +0,0 @@ -package grails.gorm.tests - -/** - * @author Erawat - */ -class GormEnhancerSpec extends GormDatastoreSpec { - - def cleanup() { - def nativeSession = session.nativeInterface - def wp = nativeSession.getWorkspace(); - def qm = wp.getQueryManager(); - - def q = qm.createQuery("//Child", javax.jcr.query.Query.XPATH); - def qr = q.execute() - def itr = qr.getNodes(); - itr.each { it.remove() } - - q = qm.createQuery("//TestEntity", javax.jcr.query.Query.XPATH); - qr = q.execute() - itr = qr.getNodes(); - itr.each { it.remove() } - nativeSession.save() - - } - - void "Test basic CRUD operations"() { - given: - def t - - when: - //JCR plugin supports only get() by using value UUID - t = TestEntity.get("19503d32-fb94-4f85-b50c-681e6f1a02f2"); - then: - t == null - - when: - t = new TestEntity(name:"Bob", child:new ChildEntity(name:"Child")) - t.save() - - then: - t.id != null - - when: - def results = TestEntity.list() - - then: - 1 == results.size() - "Bob" == results[0].name - - when: - t = TestEntity.get(t.id) - - then: - t != null - "Bob" == t.name - } - - - - void "Test simple dynamic finder"() { - - given: - def t = new TestEntity(name:"Bob", child:new ChildEntity(name:"Child")) - t.save() - - t = new TestEntity(name:"Fred", child:new ChildEntity(name:"Child")) - t.save() - - when: - def results = TestEntity.list() - def bob = TestEntity.findByName("Bob") - - then: - 2 == results.size() - bob != null - "Bob" == bob.name - } - - - void "Test dynamic finder with disjunction"() { - given: - def age = 40 - ["Bob", "Fred", "Barney"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - - when: - def results = TestEntity.findAllByNameOrAge("Barney", 40) - def barney = results.find { it.name == "Barney" } - def bob = results.find { it.age == 40 } - then: - 3 == TestEntity.count() - 2 == results.size() - barney != null - 42 == barney.age - bob != null - "Bob" == bob.name - - } - - void "Test getAll() method"() { - given: - def age = 40 - ["Bob", "Fred", "Barney"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - when: - def results = TestEntity.getAll('19503d32-fb94-4f85-b50c-681e6f1a02f2','19503d32-fb94-4f85-b50c-681e6f1a02f3') - then: - 2 == results.size() - - } - - - void "Test ident() method"() { - given: - def t - - when: - t= new TestEntity(name:"Bob", child:new ChildEntity(name:"Child")) - t.save() - - then: - t.id != null - t.id == t.ident() - } - - void "Test dynamic finder with pagination parameters"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - when: - def total = TestEntity.count() - then: - 4 == total - - 2 == TestEntity.findAllByNameOrAge("Barney", 40).size() - 1 == TestEntity.findAllByNameOrAge("Barney", 40, [max:1]).size() - } - - - void "Test in list query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - when: - def total = TestEntity.count() - then: - 4 == total - 2 == TestEntity.findAllByNameInList(["Fred", "Frank"]).size() - 1 == TestEntity.findAllByNameInList(["Joe", "Frank"]).size() - 0 == TestEntity.findAllByNameInList(["Jeff", "Jack"]).size() - 2 == TestEntity.findAllByNameInListOrName(["Joe", "Frank"], "Bob").size() - } - - void "Test like query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - when: - def results = TestEntity.findAllByNameLike("Fr%") - - then: - 2 == results.size() - results.find { it.name == "Fred" } != null - results.find { it.name == "Frank" } != null - } - - - void "Test count by query"() { - - given: - def age = 40 - ["Bob", "Fred", "Barney"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - when: - def total = TestEntity.count() - then: - 3 == total - 3 == TestEntity.list().size() - 2 == TestEntity.countByNameOrAge("Barney", 40) - 1 == TestEntity.countByNameAndAge("Bob", 40) - } - - void "Test dynamic finder with conjunction"() { - given: - def age = 40 - ["Bob", "Fred", "Barney"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - when: - def total = TestEntity.count() - then: - 3 == total - 3 == TestEntity.list().size() - - TestEntity.findByNameAndAge("Bob", 40) - !TestEntity.findByNameAndAge("Bob", 41) - } - - - void "Test count() method"() { - given: - def t - - when: - t= new TestEntity(name:"Bob", child:new ChildEntity(name:"Child")) - t.save() - - then: - 1 == TestEntity.count() - - when: - t = new TestEntity(name:"Fred", child:new ChildEntity(name:"Child")) - t.save() - - then: - 2 == TestEntity.count() - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Highway.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Highway.groovy deleted file mode 100644 index c4cd7517e..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Highway.groovy +++ /dev/null @@ -1,11 +0,0 @@ -@grails.persistence.Entity -class Highway implements Serializable { - String id - Boolean bypassed - String name - - static mapping = { - bypassed index:true - name index:true - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/InheritanceSpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/InheritanceSpec.groovy deleted file mode 100644 index 65b7ca098..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/InheritanceSpec.groovy +++ /dev/null @@ -1,96 +0,0 @@ -package grails.gorm.tests - -import org.junit.Test - -/** - * @author graemerocher - */ -class InheritanceSpec extends GormDatastoreSpec { - - void "Test inheritance with dynamic finder"() { - - given: - def city = new City([code: "UK", name: "London", longitude: 49.1, latitude: 53.1]) - def country = new Country([code: "UK", name: "United Kingdom", population: 10000000]) - - city.save() - country.save(flush:true) - session.clear() - - when: - def cities = City.findAllByCode("UK") - def countries = Country.findAllByCode("UK") - - then: - 1 == cities.size() - 1 == countries.size() - "London" == cities[0].name - "United Kingdom" == countries[0].name - } - - void "Test querying with inheritance"() { - - given: - def city = new City([code: "LON", name: "London", longitude: 49.1, latitude: 53.1]) - def location = new Location([code: "XX", name: "The World"]) - def country = new Country([code: "UK", name: "United Kingdom", population: 10000000]) - - country.save() - city.save() - location.save() - - session.flush() - - when: - city = City.get(city.id) - def london = Location.get(city.id) - country = Location.findByName("United Kingdom") - def london2 = Location.findByName("London") - - then: - 1 == City.count() - 1 == Country.count() - 3 == Location.count() - - city != null - city instanceof City - london instanceof City - london2 instanceof City - "London" == london2.name - 49.1 == london2.longitude - "LON" == london2.code - - country instanceof Country - "UK" == country.code - 10000000 == country.population - } - - def clearSession() { - City.withSession { session -> session.flush(); } - } -} - -class Location implements Serializable { - //Long id - String id - String name - String code - - def namedAndCode() { - "$name - $code" - } - - static mapping = { - name index:true - code index:true - } -} - -class City extends Location { - BigDecimal latitude - BigDecimal longitude -} - -class Country extends Location { - Integer population -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Location.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Location.groovy deleted file mode 100644 index 9560ec30c..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Location.groovy +++ /dev/null @@ -1,15 +0,0 @@ -@grails.persistence.Entity -class Location implements Serializable { - String id - String name - String code - - def namedAndCode() { - "$name - $code" - } - - static mapping = { - name index:true - code index:true - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy deleted file mode 100644 index b7445c088..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy +++ /dev/null @@ -1,11 +0,0 @@ -@grails.persistence.Entity -class ModifyPerson implements Serializable { - String id - Long version - - String name - - def beforeInsert() { - name = "Fred" - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/NamedQuerySpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/NamedQuerySpec.groovy deleted file mode 100644 index bea361f85..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/NamedQuerySpec.groovy +++ /dev/null @@ -1,1084 +0,0 @@ -package grails.gorm.tests - -import spock.lang.Ignore - -/** - * @author graemerocher - */ -class NamedQuerySpec extends GormDatastoreSpec { - - void "Test named query with disjunction"() { - given: - def now = new Date() - def oldDate = now - 2000 - - assert Publication.newInstance(title: 'New Paperback', datePublished: now, paperback: true).save() - assert Publication.newInstance(title: 'Old Paperback', datePublished: oldDate, paperback: true).save() - assert Publication.newInstance(title: 'New Hardback', datePublished: now, paperback: false).save() - assert Publication.newInstance(title: 'Old Hardback', datePublished: oldDate, paperback: false).save() - session.flush() - session.clear() - - when: - def publications = Publication.paperbackOrRecent.list() - - then: - assert 3 == publications?.size() - } - - /*void "Test max and offset parameter"() { - given: - (1..25).each {num -> - Publication.newInstance(title: "Book Number ${num}", - datePublished: new Date()).save() - } - - when: - def pubs = Publication.recentPublications.list(max: 10, offset: 5) - - then: - 10 == pubs?.size() - - when: - pubs = Publication.recentPublications.list(max: '10', offset: '5') - - then: - 10 == pubs?.size() - } - - void "Test that parameter to get is converted"() { - - given: - def now = new Date() - def newPublication = Publication.newInstance(title: "Some New Book", datePublished: now - 10).save() - assert newPublication - def oldPublication = Publication.newInstance(title: "Some Old Book", - datePublished: now - 900).save(flush:true) - assert oldPublication - - session.clear() - - when: - def publication = Publication.recentPublications.get(newPublication.id.toString()) - - then: - publication != null - 'Some New Book'== publication.title - } - - void "Test named query with additional criteria closure"() { - - given: - def now = new Date() - 6.times { - assert Publication.newInstance(title: "Some Book", - datePublished: now - 10).save() - assert Publication.newInstance(title: "Some Other Book", - datePublished: now - 10).save() - assert Publication.newInstance(title: "Some Book", - datePublished: now - 900).save() - } - session.flush() - session.clear() - - - when: - def publications = Publication.recentPublications { - eq 'title', 'Some Book' - } - then: - assert 6 == publications?.size() - - when: - publications = Publication.recentPublications { - like 'title', 'Some%' - } - then: - assert 12 == publications?.size() - - - when: - def cnt = Publication.recentPublications.count { - eq 'title', 'Some Book' - } - then: - assert 6 == cnt - - when: - publications = Publication.recentPublications(max: 3) { - like 'title', 'Some%' - } - then: - assert 3 == publications?.size() - } - - void "Test passing parameters to additional criteria"() { - given: - def now = new Date() - - 6.times { cnt -> - new Publication(title: "Some Old Book #${cnt}", - datePublished: now - 1000, paperback: true).save(failOnError: true).id - new Publication(title: "Some New Book #${cnt}", - datePublished: now, paperback: true).save(failOnError: true).id - } - - session?.flush() - - when: - def results = Publication.publishedAfter(now - 5) { - eq 'paperback', true - } - - then: - assert 6 == results?.size() - - when: - results = Publication.publishedAfter(now - 5, [max: 2, offset: 1]) { - eq 'paperback', true - } - - then: - assert 2 == results?.size() - - when: - results = Publication.publishedBetween(now - 5, now + 1) { - eq 'paperback', true - } - then: - assert 6 == results?.size() - - when: - results = Publication.publishedBetween(now - 5, now + 1, [max: 2, offset: 1]) { - eq 'paperback', true - } - then: - assert 2 == results?.size() - - when: - results = Publication.publishedAfter(now - 1005) { - eq 'paperback', true - } - then: - assert 12 == results?.size() - - when: - results = Publication.publishedAfter(now - 5) { - eq 'paperback', false - } - then: - assert 0 == results?.size() - - when: - results = Publication.publishedAfter(now - 5, [max: 2, offset: 1]) { - eq 'paperback', false - } - then: - assert 0 == results?.size() - - when: - results = Publication.publishedBetween(now - 5, now + 1) { - eq 'paperback', false - } - then: - assert 0 == results?.size() - - when: - results = Publication.publishedBetween(now - 5, now + 1, [max: 2, offset: 1]) { - eq 'paperback', false - } - then: - assert 0 == results?.size() - - when: - results = Publication.publishedAfter(now - 1005) { - eq 'paperback', false - } - then: - assert 0 == results?.size() - } - - void "Test get method followed named query chaining"() { - given: - def now = new Date() - - def oldPaperBackWithBookInTitleId = new Publication(title: "Book 1", - datePublished: now - 1000, paperback: true).save().id - def newPaperBackWithBookInTitleId = new Publication(title: "Book 2", - datePublished: now, paperback: true).save().id - - session.flush() - session.clear() - - when: - def publication = Publication.publicationsWithBookInTitle().publishedAfter(now - 5).get(oldPaperBackWithBookInTitleId) - - then: - publication == null - - when: - publication = Publication.publishedAfter(now - 5).publicationsWithBookInTitle().get(oldPaperBackWithBookInTitleId) - - then: - publication == null - - when: - publication = Publication.publishedAfter(now - 5).publicationsWithBookInTitle().get(newPaperBackWithBookInTitleId) - - then: - publication != null - - when: - publication = Publication.publishedAfter(now - 5).publicationsWithBookInTitle().get(newPaperBackWithBookInTitleId) - - then: - publication != null - } - - void "Test named query with findBy*() dynamic finder"() { - - given: - def now = new Date() - assert Publication.newInstance(title: "Book 1", - datePublished: now - 900).save() - def recentBookId = Publication.newInstance(title: "Book 1", - datePublished: now - 10).save(flush:true).id - session.clear() - - when: - def publication = Publication.recentPublications.findByTitle('Book 1') - - then: - publication != null - recentBookId == publication.id - } - - void "Test named query with findAllBy*() dyamic finder"() { - given: - def now = new Date() - 3.times { - assert new Publication(title: "Some Recent Book", - datePublished: now - 10).save() - assert new Publication(title: "Some Other Book", - datePublished: now - 10).save() - assert new Publication(title: "Some Book", - datePublished: now - 900).save(flush:true) - } - session.clear() - - when: - def publications = Publication.recentPublications.findAllByTitle('Some Recent Book') - - then: - assert 3 == publications?.size() - assert 'Some Recent Book' == publications[0].title - assert 'Some Recent Book' == publications[1].title - assert 'Some Recent Book' == publications[2].title - } - - @spock.lang.Ignore // queries on associations not yet supported - void "Test named query with relationships in criteria"() { - - given: - - new PlantCategory(name:"leafy") - .addToPlants(goesInPatch:true, name:"Lettuce") - .save(flush:true) - - new PlantCategory(name:"groovy") - .addToPlants(goesInPatch: true, name: 'Gplant') - .save(flush:true) - - new PlantCategory(name:"grapes") - .addToPlants(goesInPatch:false, name:"Gray") - .save(flush:true) - - session.clear() - - when: - def results = PlantCategory.withPlantsInPatch.list() - - then: - 2 == results.size() - true == 'leafy' in results*.name - true == 'groovy' in results*.name - - when: - results = PlantCategory.withPlantsThatStartWithG.list() - - then: - 2 == results.size() - true == 'groovy' in results*.name - true == 'grapes' in results*.name - - when: - results = PlantCategory.withPlantsInPatchThatStartWithG.list() - - then: - 1 == results.size() - 'groovy' == results[0].name - } - - @spock.lang.Ignore // queries on associations not yet supported - void "Test list distinct entities"() { - - given: - new PlantCategory(name:"leafy") - .addToPlants(goesInPatch:true, name:"lettuce") - .addToPlants(goesInPatch:true, name:"cabbage") - .save(flush:true) - - new PlantCategory(name:"orange") - .addToPlants(goesInPatch:true, name:"carrots") - .addToPlants(goesInPatch:true, name:"pumpkin") - .save(flush:true) - - new PlantCategory(name:"grapes") - .addToPlants(goesInPatch:false, name:"red") - .addToPlants(goesInPatch:false, name:"white") - .save(flush:true) - - session.clear() - - - when: - def categories = plantCategoryClass.withPlantsInPatch().listDistinct() - def names = categories*.name - - then: - 2 == categories.size() - 2 == names.size() - true == 'leafy' in names - true == 'orange' in names - } - - @spock.lang.Ignore // queries on associations not yet supported - void "Another test on listing distinct entities"() { - given: - new PlantCategory(name:"leafy") - .addToPlants(goesInPatch:true, name:"lettuce") - .addToPlants(goesInPatch:true, name:"cabbage") - .save(flush:true) - - new PlantCategory(name:"orange") - .addToPlants(goesInPatch:true, name:"carrots") - .addToPlants(goesInPatch:true, name:"pumpkin") - .save(flush:true) - - new PlantCategory(name:"grapes") - .addToPlants(goesInPatch:false, name:"red") - .addToPlants(goesInPatch:false, name:"white") - .save(flush:true) - - session.clear() - - when: - def categories = plantCategoryClass.withPlantsInPatch.listDistinct() - def names = categories*.name - - then: - 3 == categories.size() - 3 == names.size() - true == 'leafy' in names - true == 'orange' in names - true == 'grapes' in names - } - - void "Test findWhere method after chaining named queries"() { - given: - def now = new Date() - - new Publication(title: "Book 1", - datePublished: now - 10, paperback: false).save() - new Publication(title: "Book 2", - datePublished: now - 1000, paperback: true).save() - new Publication(title: "Book 3", - datePublished: now - 10, paperback: true).save() - - new Publication(title: "Some Title", - datePublished: now - 10, paperback: false).save() - new Publication(title: "Some Title", - datePublished: now - 1000, paperback: false).save() - new Publication(title: "Some Title", - datePublished: now - 10, paperback: true).save(flush:true) - session.clear() - - when: - def results = Publication.recentPublications().publicationsWithBookInTitle().findAllWhere(paperback: true) - - then: - assert 1 == results?.size() - } - - void "Test named query passing multiple parameters to a nested query"() { - given: - def now = new Date() - - new Publication(title: "Some Book", - datePublished: now - 10, paperback: false).save() - new Publication(title: "Some Book", - datePublished: now - 1000, paperback: true).save() - new Publication(title: "Some Book", - datePublished: now - 2, paperback: true).save() - - new Publication(title: "Some Title", - datePublished: now - 2, paperback: false).save() - new Publication(title: "Some Title", - datePublished: now - 1000, paperback: false).save() - new Publication(title: "Some Title", - datePublished: now - 2, paperback: true).save(flush:true) - session.clear() - - when: - - def results = Publication.thisWeeksPaperbacks().list() - - then: - assert 2 == results?.size() - } - - void "Test chaining named queries"() { - - given: - def now = new Date() - [true, false].each { isPaperback -> - 4.times { - Publication.newInstance(title: "Book Some", - datePublished: now - 10, paperback: isPaperback).save() - Publication.newInstance(title: "Book Some Other", - datePublished: now - 10, paperback: isPaperback).save() - Publication.newInstance(title: "Some Other Title", - datePublished: now - 10, paperback: isPaperback).save() - Publication.newInstance(title: "Book Some", - datePublished: now - 1000, paperback: isPaperback).save() - Publication.newInstance(title: "Book Some Other", - datePublished: now - 1000, paperback: isPaperback).save() - Publication.newInstance(title: "Some Other Title", - datePublished: now - 1000, paperback: isPaperback).save() - } - } - session.flush() - session.clear() - - when: - def results = Publication.recentPublications().publicationsWithBookInTitle().list() - - then: "The result size should be 16 when returned from chained queries" - assert 16 == results?.size() - - when: - results = Publication.recentPublications().publicationsWithBookInTitle().count() - then: - assert 16 == results - - - when: - results = Publication.recentPublications.publicationsWithBookInTitle.list() - then:"The result size should be 16 when returned from chained queries" - assert 16 == results?.size() - - when: - results = Publication.recentPublications.publicationsWithBookInTitle.count() - then: - assert 16 == results - - when: - results = Publication.paperbacks().recentPublications().publicationsWithBookInTitle().list() - then: "The result size should be 8 when returned from chained queries" - assert 8 == results?.size() - - when: - results = Publication.paperbacks().recentPublications().publicationsWithBookInTitle().count() - then: - assert 8 == results - - when: - results = Publication.recentPublications().publicationsWithBookInTitle().findAllByPaperback(true) - then: "The result size should be 8" - assert 8 == results?.size() - - when: - results = Publication.paperbacks.recentPublications.publicationsWithBookInTitle.list() - then:"The result size should be 8 when returned from chained queries" - assert 8 == results?.size() - - when: - results = Publication.paperbacks.recentPublications.publicationsWithBookInTitle.count() - then: - assert 8 == results - } - - void testChainingQueriesWithParams() { - def Publication = ga.getDomainClass("Publication").clazz - - def now = new Date() - def lastWeek = now - 7 - def longAgo = now - 1000 - 2.times { - assert Publication.newInstance(title: 'Some Book', - datePublished: now).save() - assert Publication.newInstance(title: 'Some Title', - datePublished: now).save() - } - 3.times { - assert Publication.newInstance(title: 'Some Book', - datePublished: lastWeek).save() - assert Publication.newInstance(title: 'Some Title', - datePublished: lastWeek).save() - } - 4.times { - assert Publication.newInstance(title: 'Some Book', - datePublished: longAgo).save() - assert Publication.newInstance(title: 'Some Title', - datePublished: longAgo).save() - } - session.clear() - - def results = Publication.recentPublicationsByTitle('Some Book').publishedAfter(now - 2).list() - assertEquals 'wrong number of books were returned from chained queries', 2, results?.size() - - results = Publication.recentPublicationsByTitle('Some Book').publishedAfter(now - 2).count() - assertEquals 2, results - - results = Publication.recentPublicationsByTitle('Some Book').publishedAfter(lastWeek - 2).list() - assertEquals 'wrong number of books were returned from chained queries', 5, results?.size() - - results = Publication.recentPublicationsByTitle('Some Book').publishedAfter(lastWeek - 2).count() - assertEquals 5, results - } - - void "Test referencing named query before any dynamic methods"() { - - *//* - * currently this will work: - * Publication.recentPublications().list() - * but this will not: - * Publication.recentPublications.list() - * - * the static property isn't being added to the class until - * the first dynamic method (recentPublications(), save(), list() etc...) is - * invoked - *//* - given: - when: - def publications = Publication.recentPublications.list() - then: - assert 0 == publications.size() - } - - - - void "Test named query with conjunction"() { - given: - def now = new Date() - def oldDate = now - 2000 - - assert Publication.newInstance(title: 'New Paperback', datePublished: now, paperback: true).save() - assert Publication.newInstance(title: 'Old Paperback', datePublished: oldDate, paperback: true).save() - assert Publication.newInstance(title: 'New Hardback', datePublished: now, paperback: false).save() - assert Publication.newInstance(title: 'Old Hardback', datePublished: oldDate, paperback: false).save() - session.flush() - session.clear() - - when: - def publications = Publication.paperbackAndRecent.list() - - then: - 1 == publications?.size() - } - - void "Test named query with list() method"() { - - given: - def now = new Date() - assert Publication.newInstance(title: "Some New Book", - datePublished: now - 10).save() - assert Publication.newInstance(title: "Some Old Book", - datePublished: now - 900).save(flush:true) - - session.clear() - - when: - - def publications = Publication.recentPublications.list() - - then: - assert 1 == publications?.size() - assert 'Some New Book' == publications[0].title - } - - - - // findby boolean queries not yet supported - @Ignore - void "Test named query with findAll by boolean property"() { - given: - def Publication = ga.getDomainClass("Publication").clazz - - def now = new Date() - - assert Publication.newInstance(title: 'Some Book', datePublished: now - 900, paperback: false).save() - assert Publication.newInstance(title: 'Some Book', datePublished: now - 900, paperback: false).save() - assert Publication.newInstance(title: 'Some Book', datePublished: now - 10, paperback: true).save() - assert Publication.newInstance(title: 'Some Book', datePublished: now - 10, paperback: true).save() - - when: - def publications = Publication.recentPublications.findAllPaperbackByTitle('Some Book') - - then: - assert 2 == publications?.size() - assert publications[0].title == 'Some Book' - assert publications[1].title == 'Some Book' - } - - // findby boolean queries not yet supported - @Ignore - void "Test named query with find by boolean property"() { - - given: - def now = new Date() - - assert Publication.newInstance(title: 'Some Book', datePublished: now - 900, paperback: false).save() - assert Publication.newInstance(title: 'Some Book', datePublished: now - 900, paperback: false).save() - assert Publication.newInstance(title: 'Some Book', datePublished: now - 10, paperback: true).save() - assert Publication.newInstance(title: 'Some Book', datePublished: now - 10, paperback: true).save() - - when: - def publication = Publication.recentPublications.findPaperbackByTitle('Some Book') - - then: - assert publication.title == 'Some Book' - } - - - void "Test named query with countBy*() dynamic finder"() { - given: - def now = new Date() - 3.times { - assert Publication.newInstance(title: "Some Book", - datePublished: now - 10).save() - assert Publication.newInstance(title: "Some Other Book", - datePublished: now - 10).save() - assert Publication.newInstance(title: "Some Book", - datePublished: now - 900).save(flush:true) - } - session.clear() - - when: - def numberOfNewBooksNamedSomeBook = Publication.recentPublications.countByTitle('Some Book') - - then: - assert 3 == numberOfNewBooksNamedSomeBook - } - - @Ignore // list order by not yet supported - void "Test named query with listOrderBy*() dynamic finder"() { - - given: - def now = new Date() - - assert Publication.newInstance(title: "Book 1", datePublished: now).save() - assert Publication.newInstance(title: "Book 5", datePublished: now).save() - assert Publication.newInstance(title: "Book 3", datePublished: now - 900).save() - assert Publication.newInstance(title: "Book 2", datePublished: now - 900).save() - assert Publication.newInstance(title: "Book 4", datePublished: now).save(flush:true) - session.clear() - - when: - def publications = Publication.recentPublications.listOrderByTitle() - - then: - assert 3 == publications?.size() - assert 'Book 1' == publications[0].title - assert 'Book 4' == publications[1].title - assert'Book 5'== publications[2].title - - } - - void "Test get with id of object which does not match criteria"() { - - given: - def now = new Date() - def hasBookInTitle = Publication.newInstance(title: "Book 1", - datePublished: now - 10).save() - assert hasBookInTitle - def doesNotHaveBookInTitle = Publication.newInstance(title: "Some Publication", - datePublished: now - 900).save(flush:true) - - - - session.clear() - - when: - def result = Publication.publicationsWithBookInTitle.get(doesNotHaveBookInTitle.id) - - then: - result == null - } - - void "Test get method returns correct object"() { - - given: - def now = new Date() - def newPublication = Publication.newInstance(title: "Some New Book", - datePublished: now - 10).save() - assert newPublication - def oldPublication = Publication.newInstance(title: "Some Old Book", - datePublished: now - 900).save(flush:true) - assert oldPublication - - session.clear() - - when: - def publication = Publication.recentPublications.get(newPublication.id) - - then: - assert publication != null - assert 'Some New Book' == publication.title - } - - - - void "Test get method returns null"() { - - given: - def now = new Date() - def newPublication = Publication.newInstance(title: "Some New Book", - datePublished: now - 10).save() - assert newPublication - def oldPublication = Publication.newInstance(title: "Some Old Book", - datePublished: now - 900).save(flush:true) - assert oldPublication - - session.clear() - - when: - def publication = Publication.recentPublications.get(42 + oldPublication.id) - - then: - assert publication == null - } - - void "Test count method following named criteria"() { - - given: - def now = new Date() - def newPublication = Publication.newInstance(title: "Book Some New ", - datePublished: now - 10).save() - assert newPublication - def oldPublication = Publication.newInstance(title: "Book Some Old ", - datePublished: now - 900).save(flush:true) - assert oldPublication - - session.clear() - - - when: - def publicationsWithBookInTitleCount = Publication.publicationsWithBookInTitle.count() - def recentPublicationsCount = Publication.recentPublications.count() - then: - 2 == publicationsWithBookInTitleCount - 1 == recentPublicationsCount - } - - void "Test count with parameterized named query"() { - - given: - def now = new Date() - assert Publication.newInstance(title: "Book", - datePublished: now - 10).save() - assert Publication.newInstance(title: "Book", - datePublished: now - 10).save() - assert Publication.newInstance(title: "Book", - datePublished: now - 900).save(flush:true) - - session.clear() - - when: - def recentPublicationsCount = Publication.recentPublicationsByTitle('Book').count() - - then: - assert 2 == recentPublicationsCount - } - - void "Test max parameter"() { - given: - (1..25).each {num -> - Publication.newInstance(title: "Book Number ${num}", - datePublished: new Date()).save() - } - - when: - def pubs = Publication.recentPublications.list(max: 10) - then: - assert 10 == pubs?.size() - } - - void "Test max results"() { - given: - (1..25).each {num -> - Publication.newInstance(title: 'Book Title', - datePublished: new Date() + num).save() - } - - when: - def pubs = Publication.latestBooks.list() - - then: - assert 10 == pubs?.size() - } - - - void "Test findAllWhere method combined with named query"() { - given: - def now = new Date() - (1..5).each {num -> - 3.times { - assert Publication.newInstance(title: "Book Number ${num}", - datePublished: now).save() - } - } - - when: - def pubs = Publication.recentPublications.findAllWhere(title: 'Book Number 2') - then: - assert 3 == pubs?.size() - } - - void "Test findAllWhere method with named query and disjunction"() { - - given: - def now = new Date() - def oldDate = now - 2000 - - assert Publication.newInstance(title: 'New Paperback', datePublished: now, paperback: true).save() - assert Publication.newInstance(title: 'New Paperback', datePublished: now, paperback: true).save() - assert Publication.newInstance(title: 'Old Paperback', datePublished: oldDate, paperback: true).save() - assert Publication.newInstance(title: 'New Hardback', datePublished: now, paperback: false).save() - assert Publication.newInstance(title: 'Old Hardback', datePublished: oldDate, paperback: false).save(flush:true) - session.clear() - - when: - def publications = Publication.paperbackOrRecent.findAllWhere(title: 'Old Paperback') - then: - assert 1 == publications?.size() - - when: - publications = Publication.paperbackOrRecent.findAllWhere(title: 'Old Hardback') - then: - assert 0 == publications?.size() - - when: - publications = Publication.paperbackOrRecent.findAllWhere(title: 'New Paperback') - then: - assert 2 == publications?.size() - } - - void "Test get with parameterized named query"() { - - given: - def now = new Date() - def recentPub = Publication.newInstance(title: "Some Title", - datePublished: now).save() - def oldPub = Publication.newInstance(title: "Some Title", - datePublished: now - 900).save() - - when: - def pub = Publication.recentPublicationsByTitle('Some Title').get(oldPub.id) - then: - pub == null - - when: - pub = Publication.recentPublicationsByTitle('Some Title').get(recentPub.id) - then: - assert recentPub.id == pub?.id - } - - void "Test named query with one parameter"() { - - given: - def now = new Date() - (1..5).each {num -> - 3.times { - assert Publication.newInstance(title: "Book Number ${num}", - datePublished: now).save() - } - } - - when: - def pubs = Publication.recentPublicationsByTitle('Book Number 2').list() - - then: - assert 3 == pubs?.size() - } - - void "Test named query with multiple parameters"() { - - given: - def now = new Date() - (1..5).each {num -> - assert Publication.newInstance(title: "Book Number ${num}", - datePublished: ++now).save() - } - - when: - def pubs = Publication.publishedBetween(now-2, now).list() - - then: - assert 3 == pubs?.size() - } - - void "Test named query with multiple parameters and dynamic finder"() { - given: - def now = new Date() - (1..5).each {num -> - assert Publication.newInstance(title: "Book Number ${num}", - datePublished: now + num).save() - assert Publication.newInstance(title: "Another Book Number ${num}", - datePublished: now + num).save() - } - - when: - def pubs = Publication.publishedBetween(now, now + 2).findAllByTitleLike('Book%') - - then: - 2 == pubs?.size() - } - - void "Test named query with multiple parameters and map"() { - - given: - def now = new Date() - (1..10).each {num -> - assert Publication.newInstance(title: "Book Number ${num}", - datePublished: ++now).save() - } - - when: - def pubs = Publication.publishedBetween(now-8, now-2).list(offset:2, max: 4) - - then: - 4 == pubs?.size() - } - - void "Test findWhere with named query"() { - - given: - def now = new Date() - (1..5).each {num -> - 3.times { - assert Publication.newInstance(title: "Book Number ${num}", - datePublished: now).save() - } - } - - when: - def pub = Publication.recentPublications.findWhere(title: 'Book Number 2') - then: - assert 'Book Number 2' == pub.title - } - */ -} -class PlantCategory implements Serializable{ - String id - Long version - Set plants - String name - - static hasMany = [plants:Plant] - - static namedQueries = { -// withPlantsInPatch { -// plants { -// eq 'goesInPatch', true -// } -// } -// withPlantsThatStartWithG { -// plants { -// like 'name', 'G%' -// } -// } -// withPlantsInPatchThatStartWithG { -// withPlantsInPatch() -// withPlantsThatStartWithG() -// } - } -} -class Plant implements Serializable{ - String id - Long version - boolean goesInPatch - String name -} - -class Publication implements Serializable { - String id - Long version - String title - Date datePublished - Boolean paperback = true - - static mapping = { - title index:true - paperback index:true - datePublished index:true - } - - static namedQueries = { - lastPublishedBefore { date -> - uniqueResult = true - le 'datePublished', date - order 'datePublished', 'desc' - } - - recentPublications { - def now = new Date() - gt 'datePublished', now - 365 - } - - publicationsWithBookInTitle { - like 'title', 'Book%' - } - - recentPublicationsByTitle { title -> - recentPublications() - eq 'title', title - } - - latestBooks { - maxResults(10) - order("datePublished", "desc") - } - - publishedBetween { start, end -> - between 'datePublished', start, end - } - - publishedAfter { date -> - gt 'datePublished', date - } - - paperbackOrRecent { - or { - def now = new Date() - gt 'datePublished', now - 365 - paperbacks() - } - } - - paperbacks { - eq 'paperback', true - } - - paperbackAndRecent { - paperbacks() - recentPublications() - } - - thisWeeksPaperbacks() { - paperbacks() - def today = new Date() - publishedBetween(today - 7, today) - } - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/NegationSpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/NegationSpec.groovy deleted file mode 100644 index d4ccdf5b8..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/NegationSpec.groovy +++ /dev/null @@ -1,73 +0,0 @@ -package grails.gorm.tests - -class NegationSpec extends GormDatastoreSpec { - - def cleanup() { - def nativeSession = session.nativeInterface - def wp = nativeSession.getWorkspace(); - def qm = wp.getQueryManager(); - - def q = qm.createQuery("//Book", javax.jcr.query.Query.XPATH); - def qr = q.execute() - def itr = qr.getNodes(); - itr.each { it.remove() } - } - - void "Test negation in dynamic finder"() { - given: - new Book(title:"The Stand", author:"Stephen King").save() - new Book(title:"The Shining", author:"Stephen King").save() - new Book(title:"Along Came a Spider", author:"James Patterson").save() - - when: - def results = Book.findAllByAuthorNotEqual("James Patterson") - def author = Book.findByAuthorNotEqual("Stephen King") - - then: - results.size() == 2 - results[0].author == "Stephen King" - results[1].author == "Stephen King" - - author != null - author.author == "James Patterson" - } - - void "Test simple negation in criteria"() { - given: - new Book(title:"The Stand", author:"Stephen King").save() - new Book(title:"The Shining", author:"Stephen King").save() - new Book(title:"Along Came a Spider", author:"James Patterson").save() - - when: - def results = Book.withCriteria { ne("author", "James Patterson" ) } - def author = Book.createCriteria().get { ne("author", "Stephen King" ) } - - then: - results.size() == 2 - results[0].author == "Stephen King" - results[1].author == "Stephen King" - - author != null - author.author == "James Patterson" - } - - void "Test complex negation in criteria"() { - given: - new Book(title:"The Stand", author:"Stephen King").save() - new Book(title:"The Shining", author:"Stephen King").save() - new Book(title:"Along Came a Spider", author:"James Patterson").save() - new Book(title:"The Girl with the Dragon Tattoo", author:"Stieg Larsson").save() - - when: - def results = Book.withCriteria { - not { - eq 'title', 'The Stand' - eq 'author', 'James Patterson' - } - } - then: - results.size() == 2 - results.find { it.author == "Stieg Larsson" } != null - results.find { it.author == "Stephen King" && it.title == "The Shining" } != null - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/OrderBySpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/OrderBySpec.groovy deleted file mode 100644 index 0d1d00cbd..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/OrderBySpec.groovy +++ /dev/null @@ -1,74 +0,0 @@ -package grails.gorm.tests - -/** - * Abstract base test for order by queries. Subclasses should do the necessary setup to configure GORM - */ -class OrderBySpec extends GormDatastoreSpec { - - def cleanup() { - def nativeSession = session.nativeInterface - def wp = nativeSession.getWorkspace(); - def qm = wp.getQueryManager(); - - def q = qm.createQuery("//Child", javax.jcr.query.Query.XPATH); - def qr = q.execute() - def itr = qr.getNodes(); - itr.each { it.remove() } - - q = qm.createQuery("//TestEntity", javax.jcr.query.Query.XPATH); - qr = q.execute() - itr = qr.getNodes(); - itr.each { it.remove() } - nativeSession.save() - } - - void "Test order by with list() method"() { - given: - def age = 40 - - ["Bob", "Fred", "Barney", "Frank", "Joe", "Ernie"].each { - new TestEntity(name: it, age: age++, child: new ChildEntity(name: "$it Child")).save() - } - - when: - def results = TestEntity.list(sort: "age") - - then: - 40 == results[0].age - 41 == results[1].age - 42 == results[2].age - - when: - results = TestEntity.list(sort: "age", order: "desc") - - then: - 45 == results[0].age - 44 == results[1].age - 43 == results[2].age - } - - void "Test order by property name with dynamic finder"() { - given: - def age = 40 - - ["Bob", "Fred", "Barney", "Frank", "Joe", "Ernie"].each { - new TestEntity(name: it, age: age++, child: new ChildEntity(name: "$it Child")).save() - } - - when: - def results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort: "age"]) - - then: - 40 == results[0].age - 41 == results[1].age - 42 == results[2].age - - when: - results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort: "age", order: "desc"]) - - then: - 45 == results[0].age - 44 == results[1].age - 43 == results[2].age - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Person.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Person.groovy deleted file mode 100644 index 8aef99a94..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Person.groovy +++ /dev/null @@ -1,15 +0,0 @@ -import grails.gorm.tests.Pet - -@grails.persistence.Entity -class Person implements Serializable { - String id - String firstName - String lastName - Set pets = [] - static hasMany = [pets:Pet] - - static mapping = { - firstName index:true - lastName index:true - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/PersonEvent.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/PersonEvent.groovy deleted file mode 100644 index ef2685088..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/PersonEvent.groovy +++ /dev/null @@ -1,26 +0,0 @@ -@grails.persistence.Entity -class PersonEvent implements Serializable { - String id - Long version - String name - Date dateCreated - Date lastUpdated - - static STORE = [updated:0, inserted:0] - - static void resetStore() { - STORE = [updated:0, inserted:0] - } - - def beforeDelete() { - STORE["deleted"] = true - } - - def beforeUpdate() { - STORE["updated"]++ - } - - def beforeInsert() { - STORE["inserted"]++ - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Pet.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Pet.groovy deleted file mode 100644 index 10aa367bc..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Pet.groovy +++ /dev/null @@ -1,11 +0,0 @@ -import grails.gorm.tests.Person -import grails.gorm.tests.PetType - -@grails.persistence.Entity -class Pet implements Serializable { - String id - String name - Date birthDate = new Date() - PetType type - Person owner -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/PetType.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/PetType.groovy deleted file mode 100644 index 7d605c0e3..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/PetType.groovy +++ /dev/null @@ -1,5 +0,0 @@ -@grails.persistence.Entity -class PetType implements Serializable { - String id - String name -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Plant.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Plant.groovy deleted file mode 100644 index 14d3f2979..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Plant.groovy +++ /dev/null @@ -1,9 +0,0 @@ -@grails.persistence.Entity -class Plant implements Serializable{ - String id - Long version - boolean goesInPatch - String name - - -} \ No newline at end of file diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Publication.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Publication.groovy deleted file mode 100644 index 9a26eec9a..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Publication.groovy +++ /dev/null @@ -1,72 +0,0 @@ -@grails.persistence.Entity -class Publication implements Serializable { - String id - Long version - String title - Date datePublished - Boolean paperback = true - - static mapping = { - title index:true - paperback index:true - datePublished index:true - } - - static namedQueries = { - lastPublishedBefore { date -> - uniqueResult = true - le 'datePublished', date - order 'datePublished', 'desc' - } - - recentPublications { - def now = new Date() - gt 'datePublished', now - 365 - } - - publicationsWithBookInTitle { - like 'title', 'Book%' - } - - recentPublicationsByTitle { title -> - recentPublications() - eq 'title', title - } - - latestBooks { - maxResults(10) - order("datePublished", "desc") - } - - publishedBetween { start, end -> - between 'datePublished', start, end - } - - publishedAfter { date -> - gt 'datePublished', date - } - - paperbackOrRecent { - or { - def now = new Date() - gt 'datePublished', now - 365 - paperbacks() - } - } - - paperbacks { - eq 'paperback', true - } - - paperbackAndRecent { - paperbacks() - recentPublications() - } - - thisWeeksPaperbacks() { - paperbacks() - def today = new Date() - publishedBetween(today - 7, today) - } - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/SaveAllSpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/SaveAllSpec.groovy deleted file mode 100644 index a7f263b50..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/SaveAllSpec.groovy +++ /dev/null @@ -1,50 +0,0 @@ -package grails.gorm.tests - -class SaveAllSpec extends GormDatastoreSpec { - - def cleanup() { - println 'cleanup' - def nativeSession = session.nativeInterface - def wp = nativeSession.getWorkspace(); - def qm = wp.getQueryManager(); - - def q = qm.createQuery("//Person", javax.jcr.query.Query.XPATH); - def qr = q.execute() - def itr = qr.getNodes(); - itr.each { it.remove() } - } - - def "Test that many objects can be saved at once using multiple arguments"() { - given: - def bob = new Person(firstName:"Bob", lastName:"Builder") - def fred = new Person(firstName:"Fred", lastName:"Flintstone") - def joe = new Person(firstName:"Joe", lastName:"Doe") - - Person.saveAll(bob, fred, joe) - - when: - def total = Person.count() - def results = Person.list() - - then: - total == 3 - results.every { it.id != null } == true - } - - def "Test that many objects can be saved at once using a list"() { - given: - def bob = new Person(firstName:"Bob", lastName:"Builder") - def fred = new Person(firstName:"Fred", lastName:"Flintstone") - def joe = new Person(firstName:"Joe", lastName:"Doe") - - Person.saveAll(*[bob, fred, joe]) - - when: - def total = Person.count() - def results = Person.list() - - then: - total == 3 - results.every { it.id != null } == true - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Task.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Task.groovy deleted file mode 100644 index c6c262fe9..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/Task.groovy +++ /dev/null @@ -1,13 +0,0 @@ -@grails.persistence.Entity -class Task implements Serializable { - String id - Set tasks - Task task - String name - - static mapping = { - name index:true - } - - static hasMany = [tasks:Task] -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/TestEntity.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/TestEntity.groovy deleted file mode 100644 index ffc4da5fa..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/TestEntity.groovy +++ /dev/null @@ -1,22 +0,0 @@ -package grails.gorm.tests - -/** - * Override from GORM TCK to test String based Id - * - * @author Erawat Chamanont - * @since 1.0 - */ -@grails.persistence.Entity -class TestEntity implements Serializable { - String id //for supporting String datatype such as JCR - String name - Integer age - - ChildEntity child - - static mapping = { - name index:true - age index:true - child index:true - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/UpdateWithProxyPresentSpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/UpdateWithProxyPresentSpec.groovy deleted file mode 100644 index cb6840bbb..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/UpdateWithProxyPresentSpec.groovy +++ /dev/null @@ -1,64 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -import org.grails.datastore.gorm.proxy.GroovyProxyFactory - -class UpdateWithProxyPresentSpec extends GormDatastoreSpec { - - void "Test update entity with association proxies"() { - given: - session.mappingContext.setProxyFactory(new GroovyProxyFactory()) - def person = new Person(firstName:"Bob", lastName:"Builder") - def petType = new PetType(name:"snake") - def pet = new Pet(name:"Fred", type:petType, owner:person) - person.pets << pet - person.save(flush:true) - session.clear() - - when: - person = Person.get(person.id) - person.firstName = "changed" - person.save(flush:true) - session.clear() - person = Person.get(person.id) - def personPet = person.pets.iterator().next() - - then: - person.firstName == "changed" - personPet.name == "Fred" - personPet.id == pet.id - personPet.owner.id == person.id - personPet.type.name == 'snake' - personPet.type.id == petType.id - } -} - -@Entity -class Pet implements Serializable { - String id - String name - Date birthDate = new Date() - PetType type - Person owner -} - -@Entity -class Person implements Serializable { - String id - String firstName - String lastName - Set pets = [] - static hasMany = [pets:Pet] - - static mapping = { - firstName index:true - lastName index:true - } -} - -@Entity -class PetType implements Serializable { - String id - String name -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy b/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy deleted file mode 100644 index 3f20a1560..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy +++ /dev/null @@ -1,92 +0,0 @@ -package grails.gorm.tests - -import org.grails.datastore.mapping.validation.ValidatingInterceptor -import org.springframework.validation.Errors - -/** - * Abstract base class for testing validation semantics - */ -class ValidationSpec extends GormDatastoreSpec{ - - def cleanup() { - def nativeSession = session.nativeInterface - def wp = nativeSession.getWorkspace(); - def qm = wp.getQueryManager(); - - def q = qm.createQuery("//TestEntity", javax.jcr.query.Query.XPATH); - def qr = q.execute() - def itr = qr.getNodes(); - itr.each { it.remove() } - } - - void "Test disable validation"() { - session.datastore.addEntityInterceptor(new ValidatingInterceptor()) - // test assumes name cannot be blank - given: - def t - - when: - t = new TestEntity(name:"", child:new ChildEntity(name:"child")) - Errors errors = t.errors - - then: - t.validate() == false - t.hasErrors() == true - errors != null - errors.hasErrors() == true - - when: - t.save(validate:false, flush:true) - - then: - t.id != null - !t.hasErrors() - } - - void "Test validate() method"() { - // test assumes name cannot be blank - given: - def t - - when: - t = new TestEntity(name:"") - Errors errors = t.errors - - then: - t.validate() == false - t.hasErrors() == true - errors != null - errors.hasErrors() == true - - when: - t.clearErrors() - - then: - t.hasErrors() == false - } - - void "Test that validate is called on save()"() { - - given: - def t - - when: - t = new TestEntity(name:"") - - then: - t.save() == null - t.hasErrors() == true - 0 == TestEntity.count() - - when: - t.clearErrors() - t.name = "Bob" - t.age = 45 - t.child = new ChildEntity(name:"Fred") - t = t.save() - - then: - t != null - 1 == TestEntity.count() - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-jcr/src/test/groovy/org/grails/datastore/gorm/Setup.groovy deleted file mode 100644 index 3cc9f5eb7..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package org.grails.datastore.gorm - -import org.grails.datastore.gorm.jcr.JcrGormEnhancer -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.jcr.JcrDatastore -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager -import org.springframework.util.StringUtils -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -/** - * @author Erawat Chamanont - * @since 1.0 - */ -class Setup { - static jcr - - static destroy() { - jcr?.destroy() - } - - static Session setup(classes) { - - jcr = new JcrDatastore() - for (cls in classes) { - jcr.mappingContext.addPersistentEntity(cls) - } - - PersistentEntity entity = jcr.mappingContext.persistentEntities.find { - PersistentEntity e -> e.name.contains("TestEntity") - } - - jcr.mappingContext.addEntityValidator(entity, [ - supports: { Class c -> true }, - validate: { Object o, Errors errors -> - if (!StringUtils.hasText(o.name)) { - errors.rejectValue("name", "name.is.blank") - } - } - ] as Validator) - - def enhancer = new JcrGormEnhancer(jcr, new DatastoreTransactionManager(datastore: jcr)) - enhancer.enhance() - - jcr.mappingContext.addMappingContextListener({ e -> - enhancer.enhance e - } as MappingContext.Listener) - - jcr.connect([username:"username", - password:"password", - workspace:"default", - configuration:"classpath:repository.xml", - homeDir:"/temp/repo"]) - } -} diff --git a/grails-datastore-gorm-jcr/src/test/groovy/org/grails/datastore/gorm/jcr/JcrTestSuite.groovy b/grails-datastore-gorm-jcr/src/test/groovy/org/grails/datastore/gorm/jcr/JcrTestSuite.groovy deleted file mode 100644 index fa75839da..000000000 --- a/grails-datastore-gorm-jcr/src/test/groovy/org/grails/datastore/gorm/jcr/JcrTestSuite.groovy +++ /dev/null @@ -1,59 +0,0 @@ -package org.grails.datastore.gorm.jcr - -import org.junit.runner.RunWith -import org.junit.runners.Suite -import org.junit.runners.Suite.SuiteClasses - -import grails.gorm.tests.CrudOperationsSpec -import grails.gorm.tests.GormEnhancerSpec -import grails.gorm.tests.ProxyLoadingSpec -import grails.gorm.tests.FindByMethodSpec -import grails.gorm.tests.DomainEventsSpec -import grails.gorm.tests.QueryAfterPropertyChangeSpec -import grails.gorm.tests.GroovyProxySpec -import grails.gorm.tests.CriteriaBuilderSpec -import grails.gorm.tests.CommonTypesPersistenceSpec -import grails.gorm.tests.CircularOneToManySpec -import grails.gorm.tests.InheritanceSpec -import grails.gorm.tests.ListOrderBySpec -import grails.gorm.tests.OrderBySpec -import grails.gorm.tests.ValidationSpec -import grails.gorm.tests.UpdateWithProxyPresentSpec -import grails.gorm.tests.AttachMethodSpec -import grails.gorm.tests.WithTransactionSpec -import grails.gorm.tests.RangeQuerySpec -import grails.gorm.tests.NamedQuerySpec -import grails.gorm.tests.OneToManySpec -import grails.gorm.tests.SaveAllSpec -import grails.gorm.tests.NegationSpec - -/** - * @author Erawat - */ -@RunWith(Suite) -@SuiteClasses([ -// DomainEventsSpec, // not yet passed -// ProxyLoadingSpec, // passed -// QueryAfterPropertyChangeSpec, -// CircularOneToManySpec, // StackOverflow -// InheritanceSpec, // still doesn't support inheritance -// FindByMethodSpec, // passed -// ListOrderBySpec, // passed -// GroovyProxySpec, // passed -// CommonTypesPersistenceSpec, // passed -// GormEnhancerSpec, //passed -// CriteriaBuilderSpec, //passed -// NegationSpec, //passes - NamedQuerySpec, -// OrderBySpec, //passed -// RangeQuerySpec, -// ValidationSpec, -// UpdateWithProxyPresentSpec, -// AttachMethodSpec, // passed -// WithTransactionSpec, -// CrudOperationsSpec // passed -// OneToManySpec -// SaveAllSpec // passed -]) -class JcrTestSuite { -} diff --git a/grails-datastore-gorm-jpa/build.gradle b/grails-datastore-gorm-jpa/build.gradle deleted file mode 100644 index 012175580..000000000 --- a/grails-datastore-gorm-jpa/build.gradle +++ /dev/null @@ -1,51 +0,0 @@ -version = "1.0.0.BUILD-SNAPSHOT" - -configurations { - grails -} - -dependencies { - grails("org.grails:grails-core:$grailsVersion") { - transitive = false - } - grails("org.grails:grails-bootstrap:$grailsVersion") { - transitive = false - } - compile project(":grails-datastore-gorm"), { - exclude group:"org.grails", module:"grails-datastore-core" - } - compile project(":grails-datastore-gorm-plugin-support"), - project(":grails-datastore-jpa"), - project(":grails-datastore-core"), - project(":grails-datastore-web") - - testCompile 'org.hibernate:hibernate-entitymanager:3.4.0.GA', - 'hsqldb:hsqldb:1.8.0.10' - testCompile('org.hibernate:hibernate-commons-annotations:3.2.0.Final'){ - exclude group: 'org.slf4j', module:'slf4j-api' - exclude group: 'commons-logging', module:'commons-logging' - } - testCompile('org.hibernate:hibernate-validator:4.1.0.Final') { - exclude group:'commons-logging', module:'commons-logging' - exclude group:'commons-collections', module:'commons-collections' - exclude group:'org.slf4j', module:'slf4j-api' - } - testCompile('org.hibernate:hibernate-core:3.6.10.Final') { - exclude group:'commons-logging', module:'commons-logging' - exclude group:'commons-collections', module:'commons-collections' - exclude group:'org.slf4j', module:'slf4j-api' - exclude group:'xml-apis', module:'xml-apis' - exclude group:'dom4j', module:'dom4j' - exclude group:'antlr', module: 'antlr' - } - testCompile project(":grails-datastore-gorm-tck") -} - -sourceSets { - main { - compileClasspath += configurations.grails - } - test { - compileClasspath += configurations.grails - } -} diff --git a/grails-datastore-gorm-jpa/src/main/groovy/grails/gorm/JpaEntity.java b/grails-datastore-gorm-jpa/src/main/groovy/grails/gorm/JpaEntity.java deleted file mode 100644 index ba3dca84e..000000000 --- a/grails-datastore-gorm-jpa/src/main/groovy/grails/gorm/JpaEntity.java +++ /dev/null @@ -1,20 +0,0 @@ -package grails.gorm; - -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; - -/** - * AST transformation for transforming a GORM entity into a JPA entity - * - * @author Graeme Rocher - * @since 1.0 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@GroovyASTTransformationClass("org.grails.datastore.gorm.jpa.GormToJpaTransform") -public @interface JpaEntity { -} diff --git a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/EntityInterceptorInvokingEntityListener.java b/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/EntityInterceptorInvokingEntityListener.java deleted file mode 100644 index 3a15ea168..000000000 --- a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/EntityInterceptorInvokingEntityListener.java +++ /dev/null @@ -1,186 +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.jpa; - -import javax.persistence.PostLoad; -import javax.persistence.PostPersist; -import javax.persistence.PostRemove; -import javax.persistence.PostUpdate; -import javax.persistence.PrePersist; -import javax.persistence.PreRemove; -import javax.persistence.PreUpdate; - -import org.grails.datastore.gorm.events.DomainEventListener; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.ConnectionNotFoundException; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; -import org.grails.datastore.mapping.engine.event.PostDeleteEvent; -import org.grails.datastore.mapping.engine.event.PostInsertEvent; -import org.grails.datastore.mapping.engine.event.PostLoadEvent; -import org.grails.datastore.mapping.engine.event.PostUpdateEvent; -import org.grails.datastore.mapping.engine.event.PreDeleteEvent; -import org.grails.datastore.mapping.engine.event.PreInsertEvent; -import org.grails.datastore.mapping.engine.event.PreUpdateEvent; -import org.grails.datastore.mapping.jpa.JpaDatastore; -import org.grails.datastore.mapping.jpa.JpaSession; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.transactions.Transaction; -import org.springframework.transaction.NoTransactionException; -import org.springframework.transaction.interceptor.TransactionAspectSupport; - -/** - * Adapts JPA events to the Datastore abstraction event API - * - * @author Graeme Rocher - * @since 1.0 - */ -public class EntityInterceptorInvokingEntityListener { - - @PrePersist - public void prePersist(final Object o) { - doWithSession(o, new JpaSessionTemplate() { - public void doWithSession(final JpaSession session, final PersistentEntity entity, final EntityAccess ea) { - PreInsertEvent event = new PreInsertEvent(session.getDatastore(), entity, ea); - event.addExcludedListenerName(DomainEventListener.class.getName()); - publishEvent(session, event); - if (event.isCancelled()) { - rollbackTransaction(session); - } - } - }); - } - - @PreUpdate - public void preUpdate(final Object o) { - doWithSession(o, new JpaSessionTemplate() { - public void doWithSession(final JpaSession session, final PersistentEntity entity, final EntityAccess ea) { - PreUpdateEvent event = new PreUpdateEvent(session.getDatastore(), entity, ea); - event.addExcludedListenerName(DomainEventListener.class.getName()); - session.getDatastore().getApplicationEventPublisher().publishEvent(event); - if (event.isCancelled()) { - rollbackTransaction(session); - } - } - }); - } - - @PreRemove - public void preRemove(final Object o) { - doWithSession(o, new JpaSessionTemplate() { - public void doWithSession(final JpaSession session, final PersistentEntity entity, final EntityAccess ea) { - PreDeleteEvent event = new PreDeleteEvent(session.getDatastore(), entity, ea); - event.addExcludedListenerName(DomainEventListener.class.getName()); - session.getDatastore().getApplicationEventPublisher().publishEvent(event); - if (event.isCancelled()) { - rollbackTransaction(session); - } - } - }); - } - - @PostPersist - public void postPersist(final Object o) { - doWithSession(o, new JpaSessionTemplate() { - public void doWithSession(final JpaSession session, final PersistentEntity entity, final EntityAccess ea) { - PostInsertEvent event = new PostInsertEvent(session.getDatastore(), entity, ea); - event.addExcludedListenerName(DomainEventListener.class.getName()); - session.getDatastore().getApplicationEventPublisher().publishEvent(event); - } - }); - } - - @PostUpdate - public void postUpdate(final Object o) { - doWithSession(o, new JpaSessionTemplate() { - public void doWithSession(final JpaSession session, final PersistentEntity entity, final EntityAccess ea) { - PostUpdateEvent event = new PostUpdateEvent(session.getDatastore(), entity, ea); - event.addExcludedListenerName(DomainEventListener.class.getName()); - session.getDatastore().getApplicationEventPublisher().publishEvent(event); - } - }); - } - - @PostRemove - public void postRemove(final Object o) { - doWithSession(o, new JpaSessionTemplate() { - public void doWithSession(final JpaSession session, final PersistentEntity entity, final EntityAccess ea) { - PostDeleteEvent event = new PostDeleteEvent(session.getDatastore(), entity, ea); - event.addExcludedListenerName(DomainEventListener.class.getName()); - session.getDatastore().getApplicationEventPublisher().publishEvent(event); - } - }); - } - - @PostLoad - public void postLoad(final Object o) { - doWithSession(o, new JpaSessionTemplate() { - public void doWithSession(final JpaSession session, final PersistentEntity entity, final EntityAccess ea) { - - session.getDatastore().getApplicationContext().getAutowireCapableBeanFactory().autowireBeanProperties( - o, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false); - - PostLoadEvent event = new PostLoadEvent(session.getDatastore(), entity, ea); - event.addExcludedListenerName(DomainEventListener.class.getName()); - session.getDatastore().getApplicationEventPublisher().publishEvent(event); - } - }); - } - - void rollbackTransaction(JpaSession jpaSession) { - final Transaction transaction = jpaSession.getTransaction(); - if (transaction != null) { - transaction.rollback(); - } - else { - try { - TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); - } - catch (NoTransactionException e) { - // ignore - } - } - } - - private void doWithSession(Object o, JpaSessionTemplate template) { - try { - final Session session = AbstractDatastore.retrieveSession(JpaDatastore.class); - if (!(session instanceof JpaSession)) { - return; - } - - JpaSession jpaSession = (JpaSession)session; - final PersistentEntity entity = session.getMappingContext().getPersistentEntity(o.getClass().getName()); - if (entity == null) { - return; - } - - template.doWithSession(jpaSession, entity, new EntityAccess(entity, o)); - } - catch (ConnectionNotFoundException e) { - // ignore, shouldn't happen - } - } - - private void publishEvent(final JpaSession session, final AbstractPersistenceEvent event) { - session.getDatastore().getApplicationEventPublisher().publishEvent(event); - } - - private static interface JpaSessionTemplate { - void doWithSession(JpaSession session, PersistentEntity entity, EntityAccess entityAccess); - } -} diff --git a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/GormToJpaTransform.java b/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/GormToJpaTransform.java deleted file mode 100644 index dc396f024..000000000 --- a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/GormToJpaTransform.java +++ /dev/null @@ -1,696 +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.jpa; - -import grails.gorm.JpaEntity; -import groovy.lang.Binding; -import groovy.lang.GroovyShell; - -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.persistence.Basic; -import javax.persistence.CascadeType; -import javax.persistence.Embeddable; -import javax.persistence.Embedded; -import javax.persistence.Entity; -import javax.persistence.EntityListeners; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; -import javax.persistence.PostLoad; -import javax.persistence.PostPersist; -import javax.persistence.PostRemove; -import javax.persistence.PostUpdate; -import javax.persistence.PrePersist; -import javax.persistence.PreRemove; -import javax.persistence.PreUpdate; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; -import javax.persistence.Version; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.ast.ASTNode; -import org.codehaus.groovy.ast.AnnotatedNode; -import org.codehaus.groovy.ast.AnnotationNode; -import org.codehaus.groovy.ast.ClassNode; -import org.codehaus.groovy.ast.FieldNode; -import org.codehaus.groovy.ast.MethodNode; -import org.codehaus.groovy.ast.PropertyNode; -import org.codehaus.groovy.ast.expr.ArgumentListExpression; -import org.codehaus.groovy.ast.expr.BooleanExpression; -import org.codehaus.groovy.ast.expr.ClassExpression; -import org.codehaus.groovy.ast.expr.ClosureExpression; -import org.codehaus.groovy.ast.expr.ConstantExpression; -import org.codehaus.groovy.ast.expr.Expression; -import org.codehaus.groovy.ast.expr.ListExpression; -import org.codehaus.groovy.ast.expr.MapEntryExpression; -import org.codehaus.groovy.ast.expr.MapExpression; -import org.codehaus.groovy.ast.expr.MethodCallExpression; -import org.codehaus.groovy.ast.expr.NamedArgumentListExpression; -import org.codehaus.groovy.ast.expr.PropertyExpression; -import org.codehaus.groovy.ast.expr.TupleExpression; -import org.codehaus.groovy.ast.stmt.BlockStatement; -import org.codehaus.groovy.ast.stmt.ExpressionStatement; -import org.codehaus.groovy.ast.stmt.Statement; -import org.codehaus.groovy.control.CompilePhase; -import org.codehaus.groovy.control.SourceUnit; -import org.codehaus.groovy.control.messages.SimpleMessage; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.codehaus.groovy.grails.compiler.injection.DefaultGrailsDomainClassInjector; -import org.codehaus.groovy.runtime.DefaultGroovyMethods; -import org.codehaus.groovy.transform.ASTTransformation; -import org.codehaus.groovy.transform.GroovyASTTransformation; -import org.grails.datastore.mapping.model.MappingFactory; -import org.springframework.util.ClassUtils; - -/** - * A AST transformation that turns a GORM entity into a JPA entity. - * - * @author Graeme Rocher - * @since 1.0 - */ -@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) -public class GormToJpaTransform implements ASTTransformation { - - private static Log LOG = LogFactory.getLog(GormToJpaTransform.class); - private static final AnnotationNode ANNOTATION_VERSION = new AnnotationNode(new ClassNode(Version.class)); - private static final AnnotationNode ANNOTATION_ID = new AnnotationNode(new ClassNode(Id.class)); - private static final AnnotationNode ANNOTATION_ENTITY = new AnnotationNode(new ClassNode(Entity.class)); - private static final AnnotationNode ANNOTATION_BASIC = new AnnotationNode(new ClassNode(Basic.class)); - - private static final PropertyExpression EXPR_CASCADE_ALL = new PropertyExpression( - new ClassExpression(new ClassNode(CascadeType.class)), "ALL"); - private static final PropertyExpression EXPR_CASCADE_PERSIST = new PropertyExpression( - new ClassExpression(new ClassNode(CascadeType.class)), "PERSIST"); - - private static final ClassNode MY_TYPE = new ClassNode(JpaEntity.class); - private static final String MY_TYPE_NAME = "@" + MY_TYPE.getNameWithoutPackage(); - - @SuppressWarnings("serial") - private static final Map gormEventMethodToJpaAnnotation = new HashMap() {{ - put("beforeInsert", new AnnotationNode(new ClassNode(PrePersist.class))); - put("afterInsert", new AnnotationNode(new ClassNode(PostPersist.class))); - put("beforeUpdate", new AnnotationNode(new ClassNode(PreUpdate.class))); - put("afterUpdate", new AnnotationNode(new ClassNode(PostUpdate.class))); - put("beforeDelete", new AnnotationNode(new ClassNode(PreRemove.class))); - put("afterDelete", new AnnotationNode(new ClassNode(PostRemove.class))); - put("onSave", new AnnotationNode(new ClassNode(PrePersist.class))); - put("afterLoad", new AnnotationNode(new ClassNode(PostLoad.class))); - }}; - public static final String ERRORS = "errors"; - - public void visit(ASTNode[] astNodes, SourceUnit source) { - if (!(astNodes[0] instanceof AnnotationNode) || !(astNodes[1] instanceof AnnotatedNode)) { - throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class"); - } - - AnnotatedNode parent = (AnnotatedNode) astNodes[1]; - AnnotationNode node = (AnnotationNode) astNodes[0]; - if (!MY_TYPE.equals(node.getClassNode()) || !(parent instanceof ClassNode)) { - return; - } - - ClassNode cNode = (ClassNode) parent; - String cName = cNode.getName(); - if (cNode.isInterface()) { - throw new RuntimeException("Error processing interface '" + cName + "'. " + - MY_TYPE_NAME + " not allowed for interfaces."); - } - - try { - transformEntity(source, cNode); - } catch (Exception e) { - String message = "Error occured transfoming GORM entity to JPA entity: " + e.getMessage(); - LOG.error(message,e); - source.getErrorCollector().addFatalError(new SimpleMessage(message, source)); - } - } - - public static void transformEntity(SourceUnit source, ClassNode classNode) { - - // add the JPA @Entity annotation - classNode.addAnnotation(ANNOTATION_ENTITY); - final AnnotationNode entityListenersAnnotation = new AnnotationNode( - new ClassNode(EntityListeners.class)); - entityListenersAnnotation.addMember("value", new ClassExpression( - new ClassNode(EntityInterceptorInvokingEntityListener.class))); - classNode.addAnnotation(entityListenersAnnotation); - - PropertyNode mappingNode = classNode.getProperty(GrailsDomainClassProperty.MAPPING); - Map> propertyMappings = new HashMap>(); - if (mappingNode != null && mappingNode.isStatic()) { - populateConfigurationMapFromClosureExpression( - classNode, mappingNode, propertyMappings); - } - - // annotate the id property with @Id - String idPropertyName = GrailsDomainClassProperty.IDENTITY; - String generationType = GenerationType.AUTO.toString(); - - final PropertyNode errorsProperty = classNode.getProperty("errors"); - if (errorsProperty == null) { - if (ClassUtils.isPresent("org.codehaus.groovy.grails.compiler.injection.ASTValidationErrorsHelper", Thread.currentThread().getContextClassLoader())) { - addErrorsProperty(classNode); - } - } - - if (propertyMappings.containsKey(GrailsDomainClassProperty.IDENTITY)) { - final Map idConfig = propertyMappings.get(GrailsDomainClassProperty.IDENTITY); - if (idConfig.containsKey("name")) { - idPropertyName = idConfig.get("name").toString(); - } - if (idConfig.containsKey("generator")) { - String generatorName = idConfig.get("generator").toString(); - if ("assigned".equals(generatorName)) { - generationType = null; - } - else if ("sequence".equals(generatorName)) { - generationType = GenerationType.SEQUENCE.toString(); - } - else if ("identity".equals(generatorName)) { - generationType = GenerationType.IDENTITY.toString(); - } - } - } - - PropertyNode idProperty = classNode.getProperty(idPropertyName); - if (idProperty == null) { - new DefaultGrailsDomainClassInjector().performInjectionOnAnnotatedEntity(classNode); - idProperty = classNode.getProperty(GrailsDomainClassProperty.IDENTITY); - } - - if (!idPropertyName.equals(GrailsDomainClassProperty.IDENTITY)) { - PropertyNode toDiscard = classNode.getProperty(GrailsDomainClassProperty.IDENTITY); - if (toDiscard != null && toDiscard.getType().equals("java.lang.Long")) { - classNode.getProperties().remove(toDiscard); - } - } - - if (idProperty != null) { - final FieldNode idField = idProperty.getField(); - - idField.addAnnotation(ANNOTATION_ID); - if (generationType != null) { - final AnnotationNode generatedValueAnnotation = new AnnotationNode(new ClassNode(GeneratedValue.class)); - generatedValueAnnotation.addMember("strategy", new PropertyExpression(new ClassExpression(new ClassNode(GenerationType.class)), generationType)); - idField.addAnnotation(generatedValueAnnotation); - } - } - - // annotate the version property with @Version - PropertyNode versionProperty = classNode.getProperty(GrailsDomainClassProperty.VERSION); - if (versionProperty != null) { - if (propertyMappings.containsKey(GrailsDomainClassProperty.VERSION)) { - final Map versionSettings = propertyMappings.get(GrailsDomainClassProperty.VERSION); - final Object enabledObject = versionSettings.get("enabled"); - if (enabledObject instanceof Boolean) { - if (((Boolean)enabledObject).booleanValue()) { - versionProperty.addAnnotation(ANNOTATION_VERSION); - } - } - } - else { - versionProperty.addAnnotation(ANNOTATION_VERSION); - } - } - - final List methods = classNode.getMethods(); - for (MethodNode methodNode : methods) { - if (methodNode.isStatic() || !methodNode.isPublic() || methodNode.isAbstract()) { - continue; - } - - final AnnotationNode annotationNode = gormEventMethodToJpaAnnotation.get(methodNode.getName()); - if (annotationNode == null) { - continue; - } - - //methodNode.setReturnType(new ClassNode(void.class)); - methodNode.addAnnotation(annotationNode); - } - - Map hasManyMap = lookupStringToClassNodeMap(classNode, GrailsDomainClassProperty.HAS_MANY); - Map hasOneMap = lookupStringToClassNodeMap(classNode, GrailsDomainClassProperty.HAS_ONE); - Map belongsToMap = lookupStringToClassNodeMap(classNode, GrailsDomainClassProperty.BELONGS_TO); - Map mappedByMap = lookupStringToStringMap(classNode, GrailsDomainClassProperty.MAPPED_BY); - - final List properties = classNode.getProperties(); - for (PropertyNode propertyNode : properties) { - if (!propertyNode.isPublic() || propertyNode.isStatic()) { - continue; - } - - if (propertyNode == idProperty || propertyNode == versionProperty) { - continue; - } - - final String typeName = propertyNode.getType().getName(); - - if (typeName.equals("java.util.Date") || typeName.equals("java.util.Calendar")) { - AnnotationNode temporalAnnotation = new AnnotationNode(new ClassNode(Temporal.class)); - temporalAnnotation.addMember("value", new PropertyExpression( - new ClassExpression(new ClassNode(TemporalType.class)), "DATE")); - propertyNode.getField().addAnnotation(temporalAnnotation); - } - else if (MappingFactory.isSimpleType(typeName)) { - propertyNode.getField().addAnnotation(ANNOTATION_BASIC); - } - else { - final String propertyName = propertyNode.getName(); - if (!belongsToMap.containsKey(propertyName) && - !hasOneMap.containsKey(propertyName)&& - !hasManyMap.containsKey(propertyName)) { - handleToOne(classNode, belongsToMap, propertyName); - } - } - } - - final PropertyNode transientsProp = classNode.getProperty(GrailsDomainClassProperty.TRANSIENT); - List propertyNameList = new ArrayList(); - populateConstantList(propertyNameList, transientsProp); - annotateAllProperties(classNode, propertyNameList, Transient.class); - - propertyNameList.clear(); - final PropertyNode embeddedProp = classNode.getProperty(GrailsDomainClassProperty.EMBEDDED); - populateConstantList(propertyNameList, embeddedProp); - annotateAllProperties(classNode, propertyNameList, Embedded.class); - - if (embeddedProp != null) { - for (String propertyName : propertyNameList) { - final PropertyNode property = classNode.getProperty(propertyName); - if (property == null) { - continue; - } - - ClassNode embeddedType = property.getField().getType(); - annotateIfNecessary(embeddedType, Embeddable.class); - } - } - - if (!belongsToMap.isEmpty()) { - for (String propertyName : belongsToMap.keySet()) { - handleToOne(classNode, belongsToMap, propertyName); - } - } - - if (!hasOneMap.isEmpty()) { - for (String propertyName : hasOneMap.keySet()) { - final AnnotationNode oneToOneAnnotation = new AnnotationNode(new ClassNode(OneToOne.class)); - oneToOneAnnotation.addMember("optional", ConstantExpression.FALSE); - oneToOneAnnotation.addMember("cascade", EXPR_CASCADE_ALL); - annotateProperty(classNode, propertyName, oneToOneAnnotation); - } - } - - if (!hasManyMap.isEmpty()) { - for (String propertyName : hasManyMap.keySet()) { - ClassNode associatedClass = hasManyMap.get(propertyName); - final Map inverseBelongsToMap = lookupStringToClassNodeMap( - associatedClass, GrailsDomainClassProperty.BELONGS_TO); - final Map inverseHasManyMap = lookupStringToClassNodeMap( - associatedClass, GrailsDomainClassProperty.HAS_MANY); - - final AnnotationNode oneToManyAnnotation = new AnnotationNode( - new ClassNode(OneToMany.class)); - oneToManyAnnotation.addMember("targetEntity", new ClassExpression(associatedClass)); - - if (mappedByMap.containsKey(propertyName)) { - oneToManyAnnotation.addMember("mappedBy", new ConstantExpression( - mappedByMap.get(propertyName))); - oneToManyAnnotation.addMember("cascade", EXPR_CASCADE_PERSIST); - annotateProperty(classNode, propertyName, oneToManyAnnotation); - } - else { - if (inverseHasManyMap.containsValue(classNode)) { - // many-to-many association - List belongsToList = getBelongsToList(classNode); - - final AnnotationNode manyToManyAnnotation = new AnnotationNode(new ClassNode(ManyToMany.class)); - manyToManyAnnotation.addMember("targetEntity", new ClassExpression(associatedClass)); - if (belongsToList.contains(associatedClass)) { - for (String inversePropertyName : inverseHasManyMap.keySet()) { - if (classNode.equals(inverseHasManyMap.get(inversePropertyName))) { - manyToManyAnnotation.addMember("mappedBy", new ConstantExpression(inversePropertyName)); - } - } - } - else { - manyToManyAnnotation.addMember("cascade", EXPR_CASCADE_ALL); - } - annotateProperty(classNode, propertyName, manyToManyAnnotation); - } - // Try work out the other side of the association - else if (inverseBelongsToMap.containsValue(classNode)) { - for (String inversePropertyName : inverseBelongsToMap.keySet()) { - if (classNode.equals(inverseBelongsToMap.get(inversePropertyName))) { - oneToManyAnnotation.addMember("mappedBy", new ConstantExpression(inversePropertyName)); - oneToManyAnnotation.addMember("cascade", EXPR_CASCADE_ALL); - } - } - annotateProperty(classNode, propertyName, oneToManyAnnotation); - } - else { - PropertyNode inverseClosestMatch = findClosestInverstTypeMatch(classNode, associatedClass); - if (inverseClosestMatch != null) { - oneToManyAnnotation.addMember("mappedBy", new ConstantExpression(inverseClosestMatch.getName())); - } - // unidrectional one-to-many - oneToManyAnnotation.addMember("cascade", EXPR_CASCADE_ALL); - annotateProperty(classNode, propertyName, oneToManyAnnotation); - } - } - } - } - } - - private static String addErrorsScript = null; - private static void addErrorsProperty(ClassNode classNode) { - // Horrible to have to do this, but only way to support both Grails 1.3.7 and Grails 2.0 - if (addErrorsScript == null) { - URL resource = GormToJpaTransform.class.getResource("/org/grails/datastore/gorm/jpa/AddErrors.script"); - try { - if (resource != null) { - addErrorsScript = DefaultGroovyMethods.getText(resource); - } - } catch (IOException e) { - // ignore - } - } - - if (addErrorsScript != null) { - Binding b = new Binding(); - b.setVariable("classNode", classNode); - new GroovyShell(b).evaluate(addErrorsScript); - } - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private static void populateConfigurationMapFromClosureExpression(ClassNode classNode, - PropertyNode mappingNode, Map propertyMappings) { - ClosureExpression ce = (ClosureExpression) mappingNode.getInitialExpression(); - final Statement code = ce.getCode(); - if (!(code instanceof BlockStatement)) { - return; - } - final List statements = ((BlockStatement)code).getStatements(); - for (Statement statement : statements) { - if (!(statement instanceof ExpressionStatement)) { - continue; - } - ExpressionStatement es = (ExpressionStatement) statement; - final Expression expression = es.getExpression(); - if (!(expression instanceof MethodCallExpression)) { - continue; - } - MethodCallExpression mce = (MethodCallExpression) expression; - final String methodName = mce.getMethodAsString(); - Map propertyMapping = new HashMap(); - propertyMappings.put(methodName, propertyMapping); - - final Expression arguments = mce.getArguments(); - if (arguments instanceof ArgumentListExpression) { - if (methodName.equals("table")) { - ArgumentListExpression ale = (ArgumentListExpression) arguments; - final List expressions = ale.getExpressions(); - if (!expressions.isEmpty()) { - final String tableName = expressions.get(0).getText(); - final AnnotationNode tableAnnotation = new AnnotationNode(new ClassNode(Table.class)); - tableAnnotation.addMember("name", new ConstantExpression(tableName)); - classNode.addAnnotation(tableAnnotation); - } - } - else if (methodName.equals("version")) { - ArgumentListExpression ale = (ArgumentListExpression) arguments; - final List expressions = ale.getExpressions(); - if (!expressions.isEmpty()) { - final Expression expr = expressions.get(0); - if (expr instanceof BooleanExpression) { - propertyMapping.put("enabled", Boolean.valueOf(expr.getText())); - } - } - } - } - else if (arguments instanceof TupleExpression) { - final List tupleExpressions = ((TupleExpression)arguments).getExpressions(); - for (Expression te : tupleExpressions) { - if (!(te instanceof NamedArgumentListExpression)) { - continue; - } - - NamedArgumentListExpression nale = (NamedArgumentListExpression) te; - for (MapEntryExpression mee : nale.getMapEntryExpressions()) { - String settingName = mee.getKeyExpression().getText(); - - final Expression valueExpression = mee.getValueExpression(); - if (!(valueExpression instanceof ConstantExpression)) { - continue; - } - - if (valueExpression instanceof BooleanExpression) { - propertyMapping.put(settingName, Boolean.valueOf(valueExpression.getText())); - } - else { - propertyMapping.put(settingName, valueExpression.getText()); - } - } - } - } - } - } - - private static PropertyNode findClosestInverstTypeMatch( - ClassNode classNode, ClassNode associatedClass) { - for (PropertyNode inverseProperty : associatedClass.getProperties()) { - if (inverseProperty.isPublic() && inverseProperty.getType().equals(classNode)) { - return inverseProperty; - } - } - return null; - } - - static void handleToOne(ClassNode classNode, - Map belongsToMap, String propertyName) { - ClassNode associatedClass = belongsToMap.get(propertyName); - - final Map inverseHasManyMap = lookupStringToClassNodeMap( - associatedClass, GrailsDomainClassProperty.HAS_MANY); - final Map inverseHasOneMap = lookupStringToClassNodeMap( - associatedClass, GrailsDomainClassProperty.HAS_ONE); - - if (inverseHasManyMap.containsValue(classNode)) { - for (String inversePropertyName : inverseHasManyMap.keySet()) { - if (classNode.equals(inverseHasManyMap.get(inversePropertyName))) { - final AnnotationNode manyToOneAnnotation = new AnnotationNode( - new ClassNode(ManyToOne.class)); - manyToOneAnnotation.addMember("cascade", EXPR_CASCADE_PERSIST); - annotateProperty(classNode, propertyName, manyToOneAnnotation); - } - } - } - else if (inverseHasOneMap.containsValue(classNode)) { - for (String inversePropertyName : inverseHasOneMap.keySet()) { - if (classNode.equals(inverseHasOneMap.get(inversePropertyName))) { - final AnnotationNode oneToOneAnnotation = new AnnotationNode( - new ClassNode(OneToOne.class)); - oneToOneAnnotation.addMember("mappedBy", new ConstantExpression(inversePropertyName)); - annotateProperty(classNode, propertyName, oneToOneAnnotation); - } - } - } - else { - AnnotationNode annotationNode = new AnnotationNode(new ClassNode(ManyToOne.class)); - annotationNode.addMember("cascade", EXPR_CASCADE_ALL); - annotateProperty(classNode, propertyName, annotationNode); - } - } - - private static List getBelongsToList(ClassNode classNode) { - PropertyNode propertyNode = classNode.getProperty(GrailsDomainClassProperty.BELONGS_TO); - - List classNodes = new ArrayList(); - if (propertyNode != null && propertyNode.isStatic()) { - final Expression initialExpression = propertyNode.getInitialExpression(); - if (initialExpression instanceof ListExpression) { - for (Expression expr : ((ListExpression) initialExpression).getExpressions()) { - if (expr instanceof ClassExpression) { - classNodes.add(expr.getType()); - } - } - } - else if (initialExpression instanceof ClassExpression) { - classNodes.add(initialExpression.getType()); - } - } - return classNodes; - } - - private static Map lookupStringToStringMap( - ClassNode classNode, String mapName) { - - final PropertyNode mapProperty = classNode.getProperty(mapName); - if (mapProperty == null) { - return Collections.emptyMap(); - } - - final Expression initialExpression = mapProperty.getInitialExpression(); - if (!(initialExpression instanceof MapExpression)) { - return Collections.emptyMap(); - } - - Map stringToClassNodeMap = new HashMap(); - MapExpression mapExpr = (MapExpression) initialExpression; - final List mapEntryExpressions = mapExpr.getMapEntryExpressions(); - for (MapEntryExpression mapEntryExpression : mapEntryExpressions) { - final Expression keyExpression = mapEntryExpression.getKeyExpression(); - if (!(keyExpression instanceof ConstantExpression)) { - continue; - } - ConstantExpression ce = (ConstantExpression) keyExpression; - String propertyName = ce.getValue().toString(); - final Expression valueExpression = mapEntryExpression.getValueExpression(); - if (valueExpression instanceof ConstantExpression) { - stringToClassNodeMap.put(propertyName, ((ConstantExpression) valueExpression).getValue().toString()); - } - } - return stringToClassNodeMap; - } - - private static Map lookupStringToClassNodeMap( - ClassNode classNode, String mapName) { - - if (classNode == null) { - return Collections.emptyMap(); - } - - final PropertyNode mapProperty = classNode.getProperty(mapName); - if (mapProperty == null) { - return Collections.emptyMap(); - } - - final Expression initialExpression = mapProperty.getInitialExpression(); - if (!(initialExpression instanceof MapExpression)) { - return Collections.emptyMap(); - } - - Map stringToClassNodeMap = new HashMap(); - MapExpression mapExpr = (MapExpression) initialExpression; - final List mapEntryExpressions = mapExpr.getMapEntryExpressions(); - for (MapEntryExpression mapEntryExpression : mapEntryExpressions) { - final Expression keyExpression = mapEntryExpression.getKeyExpression(); - if (!(keyExpression instanceof ConstantExpression)) { - continue; - } - ConstantExpression ce = (ConstantExpression) keyExpression; - String propertyName = ce.getValue().toString(); - final Expression valueExpression = mapEntryExpression.getValueExpression(); - if (valueExpression instanceof ClassExpression) { - ClassExpression clsExpr = (ClassExpression) valueExpression; - stringToClassNodeMap.put(propertyName, clsExpr.getType()); - } - } - return stringToClassNodeMap; - } - - private static void annotateIfNecessary(ClassNode classNode, Class annotationClass) { - AnnotationNode ann = new AnnotationNode(new ClassNode(annotationClass)); - - final List annotations = classNode.getAnnotations(); - if (annotations != null) { - for (AnnotationNode annotationNode : annotations) { - if (annotationNode.equals(ann)) return; - } - } - - classNode.addAnnotation(ann); - } - - protected static void annotateAllProperties(ClassNode classNode, - List propertyNames, final Class annotation) { - final AnnotationNode annotationNode = new AnnotationNode(new ClassNode(annotation)); - annotateAllProperties(classNode, propertyNames, annotationNode); - } - - protected static void annotateAllProperties(ClassNode classNode, - Collection propertyNames, final AnnotationNode annotationNode) { - for (String propertyName : propertyNames) { - annotateProperty(classNode, propertyName, annotationNode); - } - } - - protected static void annotateProperty(ClassNode classNode, String propertyName, Class annotation) { - annotateProperty(classNode,propertyName,new AnnotationNode(new ClassNode(annotation))); - } - - protected static void annotateProperty(ClassNode classNode, - String propertyName, final AnnotationNode annotationNode) { - final PropertyNode prop = classNode.getProperty(propertyName); - if (prop == null) { - return; - } - - final FieldNode fieldNode = prop.getField(); - if (fieldNode == null) { - return; - } - - final List annotations = fieldNode.getAnnotations(annotationNode.getClassNode()); - if (annotations == null || annotations.isEmpty()) { - fieldNode.addAnnotation(annotationNode); - } - } - - protected static void populateConstantList(List theList, - final PropertyNode theProperty) { - if (theProperty == null) { - return; - } - - final Expression initialExpression = theProperty.getInitialExpression(); - if (initialExpression instanceof ListExpression) { - ListExpression listExpression = (ListExpression) initialExpression; - final List entries = listExpression.getExpressions(); - for (Expression expression : entries) { - if (expression instanceof ConstantExpression) { - addConstantExpressionToList(theList, expression); - } - } - } - else if (initialExpression instanceof ConstantExpression) { - addConstantExpressionToList(theList, initialExpression); - } - } - - protected static void addConstantExpressionToList(List theList, - Expression expression) { - final Object val = ((ConstantExpression) expression).getValue(); - if (val != null) { - theList.add(val.toString()); - } - } -} diff --git a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/JpaGormEnhancer.groovy b/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/JpaGormEnhancer.groovy deleted file mode 100644 index 5ace97f83..000000000 --- a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/JpaGormEnhancer.groovy +++ /dev/null @@ -1,338 +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.jpa - -import static org.grails.datastore.mapping.validation.ValidatingEventListener.* - -import javax.persistence.EntityManager -import javax.persistence.Query - -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.core.SessionCallback -import org.grails.datastore.mapping.core.VoidSessionCallback -import org.grails.datastore.mapping.jpa.JpaSession -import org.springframework.core.convert.ConversionService -import org.springframework.orm.jpa.JpaCallback -import org.springframework.orm.jpa.JpaTemplate -import org.springframework.transaction.PlatformTransactionManager - -/** - * Extends the default {@link GormEnhancer} adding supporting for JPQL methods. - * - * @author Graeme Rocher - * @since 1.0 - */ -class JpaGormEnhancer extends GormEnhancer { - - JpaGormEnhancer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - JpaGormEnhancer(Datastore datastore) { - super(datastore) - } - - protected GormInstanceApi getInstanceApi(Class cls) { - final api = new JpaInstanceApi(cls, datastore) - api.failOnError = failOnError - return api - } - - protected GormStaticApi getStaticApi(Class cls) { - return new JpaStaticApi(cls, datastore, finders) - } -} - -class JpaInstanceApi extends GormInstanceApi { - - JpaInstanceApi(Class persistentClass, Datastore datastore) { - super(persistentClass, datastore) - } - - @Override - protected void execute(VoidSessionCallback callback) { - def session = datastore.connect() - callback.doInSession(session) - } - - @Override - protected def T execute(SessionCallback callback) { - def session = datastore.connect() - callback.doInSession(session) - } - - D merge(instance, Map params) { - def merged - doSave(instance, params) { session -> - merged = session.merge(instance) - } - merged - } - - D save(instance, Map params) { - doSave(instance, params) { session -> - session.persist(instance) - } - } - - private D doSave(instance, Map params, Closure callable) { - execute (new SessionCallback() { - def doInSession(Session session) { - boolean hasErrors = false - boolean validate = params?.containsKey("validate") ? params.validate : true - if (instance.respondsTo('validate') && validate) { - session.datastore.setSkipValidation(instance, false) - hasErrors = !instance.validate() - } - else { - session.datastore.setSkipValidation(instance, true) - instance.clearErrors() - } - - if (hasErrors) { - if (params?.failOnError) { - throw getValidationException().newInstance( - "Validation error occured during call to save()", instance.errors) - } - rollbackTransaction(session) - return null - } - - callable.call(session) - if (params?.flush) { - session.flush() - } - return instance - } - }) - } - - private void rollbackTransaction(JpaSession jpaSession) { - jpaSession.getTransaction()?.rollback() - } -} - -class JpaStaticApi extends GormStaticApi { - - JpaStaticApi(Class persistentClass, Datastore datastore, List finders) { - super(persistentClass, datastore, finders) - } - - def withEntityManager(Closure callable) { - execute (new SessionCallback() { - def doInSession(Session session) { - JpaTemplate jpaTemplate = session.getNativeInterface() - jpaTemplate.execute({ EntityManager em -> callable.call(em) } as JpaCallback) - } - }) - } - - @Override - protected void execute(VoidSessionCallback callback) { - def session = datastore.connect() - callback.doInSession(session) - } - - @Override - protected def T execute(SessionCallback callback) { - def session = datastore.connect() - callback.doInSession(session) - } - - @Override - List executeQuery(String query) { - doQuery query - } - - @Override - List executeQuery(String query, Map args) { - doQuery query, null, args - } - - @Override - List executeQuery(String query, Map params, Map args) { - doQuery query, params, args, false - } - - @Override - List executeQuery(String query, Collection params) { - doQuery query, params - } - - @Override - List executeQuery(String query, Collection params, Map args) { - doQuery query, params, args - } - - @Override - Integer executeUpdate(String query) { - doUpdate query - } - - @Override - Integer executeUpdate(String query, Map args) { - doUpdate query, null, args - } - - @Override - Integer executeUpdate(String query, Map params, Map args) { - doUpdate query, params, args - } - - @Override - Integer executeUpdate(String query, Collection params) { - doUpdate query, params - } - - @Override - Integer executeUpdate(String query, Collection params, Map args) { - doUpdate query, params, args - } - - @Override - D find(String query) { - doQuery query, null, null, true - } - - @Override - D find(String query, Map args) { - doQuery query, null, args, true - } - - @Override - D find(String query, Map params, Map args) { - doQuery query, params, args, true - } - - @Override - D find(String query, Collection params) { - doQuery query, params, null, true - } - - @Override - D find(String query, Collection params, Map args) { - doQuery query, params, args, true - } - - @Override - List findAll(String query) { - doQuery query - } - - @Override - List findAll(String query, Map args) { - doQuery query, null, args - } - - @Override - List findAll(String query, Map params, Map args) { - doQuery query, params, args - } - - @Override - List findAll(String query, Collection params) { - doQuery query, params - } - - @Override - List findAll(String query, Collection params, Map args) { - doQuery query, params, args - } - - private Integer doUpdate(String query, params = null, args = null) { - execute (new SessionCallback() { - Integer doInSession(Session session) { - JpaTemplate jpaTemplate = session.getNativeInterface() - jpaTemplate.execute({ EntityManager em -> - Query q = em.createQuery(query) - populateQueryArguments(datastore, q, params) - populateQueryArguments(datastore, q, args) - handleParamsAndArguments(q, params, args) - - q.executeUpdate() - } as JpaCallback) - } - }) - } - - private doQuery(String query, params = null, args = null, boolean singleResult = false) { - execute (new SessionCallback() { - def doInSession(Session session) { - JpaTemplate jpaTemplate = session.getNativeInterface() - jpaTemplate.execute({ EntityManager em -> - Query q = em.createQuery(query) - populateQueryArguments(datastore, q, args) - populateQueryArguments(datastore, q, params) - handleParamsAndArguments(q, params, args) - - if (singleResult) { - doSingleResult(q) - } - else { - return q.resultList - } - } as JpaCallback) - } - }) - } - - private Query handleParamsAndArguments(Query q, params, args) { - if (params || args) { - if (params instanceof Collection) { - params.eachWithIndex { val, i -> - q.setParameter i+1, val - } - } - else { - if (params) { - for (entry in params) { - q.setParameter entry.key, entry.value - } - } - if (args) { - for (entry in args) { - q.setParameter entry.key, entry.value - } - } - } - } - return q - } - - private doSingleResult(Query q) { - q.setMaxResults 1 - q.resultList[0] - } - - private void populateQueryArguments(Datastore datastore, Query q, args) { - if (!(args instanceof Map)) { - return - } - - ConversionService conversionService = datastore.mappingContext.conversionService - if (args?.max) { - q.setMaxResults(conversionService.convert(args.remove('max'), Integer)) - } - if (args?.offset) { - q.setFirstResult(conversionService.convert(args.remove('offset'), Integer)) - } - } -} diff --git a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/bean/factory/JpaDatastoreFactoryBean.groovy b/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/bean/factory/JpaDatastoreFactoryBean.groovy deleted file mode 100644 index 1e5d2987d..000000000 --- a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/bean/factory/JpaDatastoreFactoryBean.groovy +++ /dev/null @@ -1,46 +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.jpa.bean.factory - -import javax.persistence.EntityManagerFactory - -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.mapping.jpa.JpaDatastore -import org.grails.datastore.mapping.model.MappingContext -import org.springframework.beans.factory.FactoryBean -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware -import org.springframework.context.ConfigurableApplicationContext -import org.springframework.orm.jpa.JpaTransactionManager - -class JpaDatastoreFactoryBean implements FactoryBean, ApplicationContextAware { - - MappingContext mappingContext - ApplicationContext applicationContext - - JpaDatastore getObject() { - JpaTransactionManager transactionManager = applicationContext.getBean(JpaTransactionManager) - EntityManagerFactory entityManagerFactory = applicationContext.getBean(EntityManagerFactory) - def datastore = new JpaDatastore(mappingContext, entityManagerFactory, transactionManager, (ConfigurableApplicationContext)applicationContext) - applicationContext.addApplicationListener new DomainEventListener(datastore) - applicationContext.addApplicationListener new AutoTimestampEventListener(datastore) - datastore - } - - Class getObjectType() { JpaDatastore } - - boolean isSingleton() { true } -} diff --git a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/bean/factory/JpaMappingContextFactoryBean.groovy b/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/bean/factory/JpaMappingContextFactoryBean.groovy deleted file mode 100644 index 3af709e5b..000000000 --- a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/bean/factory/JpaMappingContextFactoryBean.groovy +++ /dev/null @@ -1,33 +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.jpa.bean.factory - -import org.grails.datastore.gorm.bean.factory.AbstractMappingContextFactoryBean -import org.grails.datastore.mapping.jpa.config.JpaMappingContext -import org.grails.datastore.mapping.model.MappingContext - -/** - * Constructs a {@link JpaMappingContext} instance - * - * @author Graeme Rocher - * @since 1.0 - */ -class JpaMappingContextFactoryBean extends AbstractMappingContextFactoryBean { - - @Override - protected MappingContext createMappingContext() { - return new JpaMappingContext() - } -} diff --git a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/plugin/support/JpaMethodsConfigurer.groovy b/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/plugin/support/JpaMethodsConfigurer.groovy deleted file mode 100644 index 2e7b1ef24..000000000 --- a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/plugin/support/JpaMethodsConfigurer.groovy +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2012 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.jpa.plugin.support - -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.jpa.JpaGormEnhancer -import org.grails.datastore.gorm.jpa.JpaInstanceApi -import org.grails.datastore.gorm.jpa.JpaStaticApi -import org.grails.datastore.gorm.plugin.support.DynamicMethodsConfigurer -import org.grails.datastore.mapping.core.Datastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * @author Graeme Rocher - * @since 1.0 - */ -class JpaMethodsConfigurer extends DynamicMethodsConfigurer { - - JpaMethodsConfigurer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { - return "jpa" - } - - @Override - protected GormStaticApi createGormStaticApi(Class cls, List finders) { - return new JpaStaticApi(cls, datastore,finders) - } - - @Override - protected GormInstanceApi createGormInstanceApi(Class cls) { - def api = new JpaInstanceApi(cls, datastore) - api.failOnError = failOnError - api - } - - @Override - protected GormEnhancer createEnhancer() { - def ge = new JpaGormEnhancer(datastore, transactionManager) - ge.failOnError = failOnError - ge - } -} diff --git a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/plugin/support/JpaOnChangeHandler.groovy b/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/plugin/support/JpaOnChangeHandler.groovy deleted file mode 100644 index 28080a041..000000000 --- a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/plugin/support/JpaOnChangeHandler.groovy +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2012 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.jpa.plugin.support - -import org.grails.datastore.gorm.plugin.support.OnChangeHandler -import org.grails.datastore.mapping.core.Datastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * @author Graeme Rocher - * @since 1.0 - */ -class JpaOnChangeHandler extends OnChangeHandler{ - JpaOnChangeHandler(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { - return "jpa" - } -} diff --git a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/plugin/support/JpaSpringConfigurer.groovy b/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/plugin/support/JpaSpringConfigurer.groovy deleted file mode 100644 index c5897f7c3..000000000 --- a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/plugin/support/JpaSpringConfigurer.groovy +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (C) 2012 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.jpa.plugin.support - -import org.grails.datastore.gorm.jpa.bean.factory.JpaDatastoreFactoryBean -import org.grails.datastore.gorm.jpa.bean.factory.JpaMappingContextFactoryBean -import org.grails.datastore.gorm.jpa.support.JpaPersistenceContextInterceptor -import org.grails.datastore.gorm.plugin.support.SpringConfigurer -import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor - -/** - * Configures JPA. Assumes an entityManagerFactory bean has been configured by the application. - * - * @author Graeme Rocher - * @since 1.0 - */ -class JpaSpringConfigurer extends SpringConfigurer { - - @Override - String getDatastoreType() { "jpa" } - - @Override - protected Closure configureSpring(Closure customizer) { - - return { - jpaMappingContext(JpaMappingContextFactoryBean) - jpaDatastore(JpaDatastoreFactoryBean) { - mappingContext = jpaMappingContext - } - jpaPersistenceInterceptor(JpaPersistenceContextInterceptor, ref("jpaDatastore")) - - if (manager?.hasGrailsPlugin("controllers")) { - String interceptorName = "jpaOpenSessionInViewInterceptor" - "${interceptorName}"(OpenEntityManagerInViewInterceptor) { bean -> - bean.autowire = true - } - if (getSpringConfig().containsBean("controllerHandlerMappings")) { - controllerHandlerMappings.interceptors << ref(interceptorName) - } - if (getSpringConfig().containsBean("annotationHandlerMapping")) { - if (annotationHandlerMapping.interceptors) { - annotationHandlerMapping.interceptors << ref(interceptorName) - } - else { - annotationHandlerMapping.interceptors = [ref(interceptorName)] - } - } - } - } - } - - @Override - Closure getSpringCustomizer() { - return null // do nothing, handled by configureSpring - } -} diff --git a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/support/JpaPersistenceContextInterceptor.java b/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/support/JpaPersistenceContextInterceptor.java deleted file mode 100644 index f5093bb32..000000000 --- a/grails-datastore-gorm-jpa/src/main/groovy/org/grails/datastore/gorm/jpa/support/JpaPersistenceContextInterceptor.java +++ /dev/null @@ -1,77 +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.jpa.support; - -import javax.persistence.EntityManager; -import javax.persistence.FlushModeType; - -import org.codehaus.groovy.grails.support.PersistenceContextInterceptor; -import org.grails.datastore.mapping.jpa.JpaDatastore; -import org.grails.datastore.mapping.jpa.JpaSession; -import org.springframework.orm.jpa.EntityManagerFactoryUtils; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public class JpaPersistenceContextInterceptor implements PersistenceContextInterceptor { - - private JpaDatastore jpaDatastore; - private EntityManager entityManager; - - public JpaPersistenceContextInterceptor(JpaDatastore datastore) { - this.jpaDatastore= datastore; - } - - public void init() { - entityManager = EntityManagerFactoryUtils.getTransactionalEntityManager(jpaDatastore.getEntityManagerFactory()); - } - - public void destroy() { - entityManager = null; - } - - public void disconnect() { - if (entityManager != null) { - EntityManagerFactoryUtils.closeEntityManager(entityManager); - } - } - - public void reconnect() { - entityManager = EntityManagerFactoryUtils.getTransactionalEntityManager(jpaDatastore.getEntityManagerFactory()); - } - - public void flush() { - if (JpaSession.hasTransaction()) { - entityManager.flush(); - } - } - - public void clear() { - entityManager.clear(); - } - - public void setReadOnly() { - entityManager.setFlushMode(FlushModeType.COMMIT); - } - - public void setReadWrite() { - entityManager.setFlushMode(FlushModeType.AUTO); - } - - public boolean isOpen() { - return entityManager != null && entityManager.isOpen(); - } -} diff --git a/grails-datastore-gorm-jpa/src/main/resources/org/grails/datastore/gorm/jpa/AddErrors.script b/grails-datastore-gorm-jpa/src/main/resources/org/grails/datastore/gorm/jpa/AddErrors.script deleted file mode 100644 index 73d64b3c1..000000000 --- a/grails-datastore-gorm-jpa/src/main/resources/org/grails/datastore/gorm/jpa/AddErrors.script +++ /dev/null @@ -1,25 +0,0 @@ -import org.codehaus.groovy.grails.compiler.injection.ASTErrorsHelper; -import org.codehaus.groovy.grails.compiler.injection.ASTValidationErrorsHelper; -import javax.persistence.Transient; -import org.codehaus.groovy.ast.ClassNode; -import org.codehaus.groovy.ast.FieldNode; -import org.codehaus.groovy.ast.AnnotatedNode; -import org.codehaus.groovy.ast.AnnotationNode; -import org.codehaus.groovy.ast.ASTNode; -import org.codehaus.groovy.ast.expr.ConstantExpression; -import java.lang.reflect.Modifier -import org.springframework.validation.Errors - -def errorsHelper = new ASTValidationErrorsHelper() { - protected void addErrorsField(ClassNode paramTypeClassNode) { - final ASTNode errorsField = paramTypeClassNode.getField("errors") - if (errorsField == null) { - FieldNode field = new FieldNode("errors", Modifier.PUBLIC, - new ClassNode(Errors.class), paramTypeClassNode, new ConstantExpression(null)); - - field.addAnnotation(new AnnotationNode(new ClassNode(Transient.class))); - paramTypeClassNode.addField(field); - } - } -}; -errorsHelper.injectErrorsCode(classNode); diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/AttachMethodSpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/AttachMethodSpec.groovy deleted file mode 100644 index 349024e45..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/AttachMethodSpec.groovy +++ /dev/null @@ -1,8 +0,0 @@ -package grails.gorm.tests - -class AttachMethodSpec extends GormDatastoreSpec { - - void "Test attach method"() { - // JPA doesn't support the attach method. Ignore - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Book.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Book.groovy deleted file mode 100644 index 4a68a9c66..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Book.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class Book implements Serializable { - String author - String title - Boolean published - - static mapping = { - published index:true - title index:true - author index:true - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Child.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Child.groovy deleted file mode 100644 index a7e15db91..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Child.groovy +++ /dev/null @@ -1,12 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -/** - * @author Graeme Rocher - */ - -@JpaEntity -class Child { - String name -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ChildEntity.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ChildEntity.groovy deleted file mode 100644 index 5f1acb937..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ChildEntity.groovy +++ /dev/null @@ -1,12 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class ChildEntity implements Serializable { - String name - - static mapping = { name index:true } - - static belongsTo = [TestEntity] -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/City.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/City.groovy deleted file mode 100644 index e2dc8becd..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/City.groovy +++ /dev/null @@ -1,9 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class City extends Location { - BigDecimal latitude - BigDecimal longitude -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy deleted file mode 100644 index 54321a9b7..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity -import javax.persistence.Transient - -@JpaEntity -class ClassWithListArgBeforeValidate { - Long id - Long version - - @Transient - def listArgCounter = 0 - - @Transient - def propertiesPassedToBeforeValidate - - String name - - def beforeValidate(List properties) { - ++listArgCounter - propertiesPassedToBeforeValidate = properties - } - - static constraints = { - name blank: false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy deleted file mode 100644 index d350f21e9..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity -import javax.persistence.Transient - -@JpaEntity -class ClassWithNoArgBeforeValidate { - Long id - Long version - - @Transient - def noArgCounter = 0 - - String name - - def beforeValidate() { - ++noArgCounter - } - - static constraints = { - name blank: false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy deleted file mode 100644 index 27df7a31b..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy +++ /dev/null @@ -1,32 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity -import javax.persistence.Transient - -@JpaEntity -class ClassWithOverloadedBeforeValidate { - Long id - Long version - - @Transient - def noArgCounter = 0 - - @Transient - def listArgCounter = 0 - - @Transient - def propertiesPassedToBeforeValidate - - String name - def beforeValidate() { - ++noArgCounter - } - def beforeValidate(List properties) { - ++listArgCounter - propertiesPassedToBeforeValidate = properties - } - - static constraints = { - name blank: false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/CommonTypes.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/CommonTypes.groovy deleted file mode 100644 index d3df45f66..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/CommonTypes.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class CommonTypes implements Serializable { - Long l - Byte b - Short s - Boolean bool - Integer i - URL url - Date date - Calendar c - BigDecimal bd - BigInteger bi - Double d - Float f - TimeZone tz - Locale loc - Currency cur - byte[] ba -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ConstrainedEntity.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ConstrainedEntity.groovy deleted file mode 100644 index 072bbec7e..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ConstrainedEntity.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class ConstrainedEntity implements Serializable { - - static final MAX_VALUE = 1000 - static final List ALLOWABLE_VALUES = ['ABC','DEF','GHI'] - - Long id - Integer num - String str - - static constraints = { - num(maxSize:MAX_VALUE) /*Must be MyDomainClass.MAX_VALUE in order work with redis*/ - str validator: { val, obj -> - if (val != null && !ALLOWABLE_VALUES.contains(val)) {/*Must be MyDomainClass.ALLOWABLE_VALUES in order work with redis */ - return ['not.valid'] - } - } - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Country.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Country.groovy deleted file mode 100644 index 474b1f118..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Country.groovy +++ /dev/null @@ -1,10 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class Country extends Location { - Integer population - - static hasMany = [residents:Person] -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Dog.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Dog.groovy deleted file mode 100644 index f38a57c16..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Dog.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class Dog implements Serializable{ - int age - int deathAge - String name - - static mapping = { - age index:true - name index:true - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/DomainEventsSpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/DomainEventsSpec.groovy deleted file mode 100644 index af97911bd..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/DomainEventsSpec.groovy +++ /dev/null @@ -1,292 +0,0 @@ -package grails.gorm.tests - -import groovy.transform.NotYetImplemented -import org.grails.datastore.mapping.core.Session -import grails.gorm.DetachedCriteria -import spock.lang.Issue - -/** - * @author graemerocher - */ -class DomainEventsSpec extends GormDatastoreSpec { - - def setup() { - PersonEvent.resetStore() - } - @Issue('GPMONGODB-262') - @NotYetImplemented - void "Test that returning false from beforeUpdate evicts the event"() { - when:"An entity is saved" - def p = new PersonEvent(name: "Fred") - p.save(flush: true) - session.clear() - p = PersonEvent.get(p.id) - then:"The person is saved" - p != null - - when:"The beforeUpdate event returns false" - p.name = "Bad" - p.save(flush: true) - session.clear() - - then:"The person is never updated" - PersonEvent.get(p.id).name == "Fred" - } - - @Issue('GPMONGODB-262') - @NotYetImplemented - void "Test that returning false from beforeInsert evicts the event"() { - when:"false is returned from a beforeInsert event" - def p = new PersonEvent(name: "Bad") - try { - p.save() - session.flush() - } catch (e) { - // ignore hibernate related flush errors - } - session.clear() - - then:"The person is never saved" - !PersonEvent.get(p.id) - } - - @Issue('GPMONGODB-262') - @NotYetImplemented - void "Test that returning false from beforeDelete evicts the event"() { - when:"a new person is saved" - def p = new PersonEvent(name: "DontDelete") - p.save(flush: true) - session.clear() - p = PersonEvent.get(p.id) - - - then:"The person exists" - p != null - - when:"The beforeDelete event returns false" - p.delete(flush: true) - session.clear() - - then:"The event was cancelled" - PersonEvent.get(p.id) - } - - void "Test modify property before save"() { - given: - session.datastore.mappingContext.addPersistentEntity(ModifyPerson) - def p = new ModifyPerson(name:"Bob").save(flush:true) - session.clear() - - when:"An object is queried by id" - p = ModifyPerson.get(p.id) - - then: "the correct object is returned" - p.name == "Fred" - - when:"An object is queried by the updated value" - p = ModifyPerson.findByName("Fred") - - then:"The correct person is returned" - p.name == "Fred" - } - - void "Test auto time stamping working"() { - - given: - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - sleep(2000) - - p.dateCreated == p.lastUpdated - - when: - p.name = "Wilma" - p.save(flush:true) - - then: - p.dateCreated.before(p.lastUpdated) - } - - void "Test delete events"() { - given: - def p = new PersonEvent() - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - 0 == PersonEvent.STORE.beforeDelete - 0 == PersonEvent.STORE.afterDelete - - when: - p.delete(flush:true) - - then: - 1 == PersonEvent.STORE.beforeDelete - 1 == PersonEvent.STORE.afterDelete - } - - void "Test multi-delete events"() { - given: - def freds = (1..3).collect { - new PersonEvent(name: "Fred$it").save(flush:true) - } - session.clear() - - when: - freds = PersonEvent.findAllByIdInList(freds*.id) - - then: - 3 == freds.size() - 0 == PersonEvent.STORE.beforeDelete - 0 == PersonEvent.STORE.afterDelete - - when: - new DetachedCriteria(PersonEvent).build { - 'in'('id', freds*.id) - }.deleteAll() - session.flush() - - then: - 0 == PersonEvent.count() - 0 == PersonEvent.list().size() - - // removed the below assertions because in the case of batch DML statements neither Hibernate nor JPA triggers delete events for individual entities -// 3 == PersonEvent.STORE.beforeDelete -// 3 == PersonEvent.STORE.afterDelete - } - - void "Test before update event"() { - given: - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - 0 == PersonEvent.STORE.beforeUpdate - 0 == PersonEvent.STORE.afterUpdate - - when: - p.name = "Bob" - p.save(flush:true) - session.clear() - p = PersonEvent.get(p.id) - - then: - "Bob" == p.name - 1 == PersonEvent.STORE.beforeUpdate - 1 == PersonEvent.STORE.afterUpdate - } - - void "Test insert events"() { - given: - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - 0 == PersonEvent.STORE.beforeUpdate - 1 == PersonEvent.STORE.beforeInsert - 0 == PersonEvent.STORE.afterUpdate - 1 == PersonEvent.STORE.afterInsert - - when: - p.name = "Bob" - p.save(flush:true) - session.clear() - p = PersonEvent.get(p.id) - - then: - "Bob" == p.name - 1 == PersonEvent.STORE.beforeUpdate - 1 == PersonEvent.STORE.beforeInsert - 1 == PersonEvent.STORE.afterUpdate - 1 == PersonEvent.STORE.afterInsert - } - - void "Test load events"() { - given: - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - if (!'JpaSession'.equals(session.getClass().simpleName)) { - // JPA doesn't seem to support a pre-load event - 1 == PersonEvent.STORE.beforeLoad - } - 1 == PersonEvent.STORE.afterLoad - } - - void "Test multi-load events"() { - given: - def freds = (1..3).collect { - new PersonEvent(name: "Fred$it").save(flush:true) - } - session.clear() - - when: - freds = PersonEvent.findAllByIdInList(freds*.id) - - then: - 3 == freds.size() - if (!'JpaSession'.equals(session.getClass().simpleName)) { - // JPA doesn't seem to support a pre-load event - 3 == PersonEvent.STORE.beforeLoad - } - 3 == PersonEvent.STORE.afterLoad - } - - void "Test bean autowiring"() { - given: - def personService = new Object() - session.datastore.applicationContext.beanFactory.registerSingleton 'personService', personService - - def p = new PersonEvent() - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - personService.is p.personService - } - - - def cleanup() { - session.datastore.applicationContext.beanFactory.destroySingleton 'personService' - } -} - diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/EmbeddedAssociationSpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/EmbeddedAssociationSpec.groovy deleted file mode 100644 index c4d9da9f0..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/EmbeddedAssociationSpec.groovy +++ /dev/null @@ -1,45 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity -import javax.persistence.Embeddable - -class EmbeddedAssociationSpec extends GormDatastoreSpec { - - static { - GormDatastoreSpec.TEST_CLASSES << Individual << Address - } - - void "Test persistence of embedded entities"() { - given: - def i = new Individual(name:"Bob", address: new Address(postCode:"30483")) - - i.save(flush:true) - session.clear() - - when: - i = Individual.findByName("Bob") - - then: - i != null - i.name == 'Bob' - i.address != null - i.address.postCode == '30483' - } - -} -@JpaEntity -class Individual { - String name - Address address - static embedded = ['address'] - - static mapping = { - name index:true - } -} - -@JpaEntity -@Embeddable -class Address { - String postCode -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/EnumSpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/EnumSpec.groovy deleted file mode 100644 index 997c01fd3..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/EnumSpec.groovy +++ /dev/null @@ -1,6 +0,0 @@ -package grails.gorm.tests - -class EnumSpec extends GormDatastoreSpec { - // TODO get this working with JPA - all the real tests fail - void testNothing() {} -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/EnumThing.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/EnumThing.groovy deleted file mode 100644 index e1fa84e6d..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/EnumThing.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -import javax.persistence.EnumType -import javax.persistence.Enumerated - -//@JpaEntity -class EnumThing { - String name - - @Enumerated(EnumType.STRING) - TestEnum en -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Face.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Face.groovy deleted file mode 100644 index 5fe1a64d7..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Face.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class Face implements Serializable { - Long id - String name - Nose nose - static hasOne = [nose: Nose] -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/GroovyProxySpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/GroovyProxySpec.groovy deleted file mode 100644 index 6baefc651..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/GroovyProxySpec.groovy +++ /dev/null @@ -1,8 +0,0 @@ -package grails.gorm.tests - -class GroovyProxySpec extends GormDatastoreSpec { - - void "Test creation and behavior of Groovy proxies"() { - // Not implemented since we rely on the JPA provides proxying mechanism - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/GroupWithin.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/GroupWithin.groovy deleted file mode 100644 index e06cc4808..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/GroupWithin.groovy +++ /dev/null @@ -1,13 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class GroupWithin implements Serializable{ - Long id - String name - String org - static constraints = { - name unique:"org" - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Highway.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Highway.groovy deleted file mode 100644 index 0806ebe15..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Highway.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class Highway implements Serializable { - Boolean bypassed - String name - - static mapping = { - bypassed index:true - name index:true - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Location.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Location.groovy deleted file mode 100644 index a2a497ac1..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Location.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class Location implements Serializable { - String name - String code - - def namedAndCode() { - "$name - $code" - } - - static mapping = { - name index:true - code index:true - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy deleted file mode 100644 index 374f3cece..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class ModifyPerson implements Serializable { - Long version - - String name - - void beforeInsert() { - name = "Fred" - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Nose.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Nose.groovy deleted file mode 100644 index 9699f2cbf..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Nose.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class Nose implements Serializable { - Long id - boolean hasFreckles - Face face - static belongsTo = [face: Face] -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/NotNullQuerySpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/NotNullQuerySpec.groovy deleted file mode 100644 index 18d196501..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/NotNullQuerySpec.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity -import grails.persistence.Entity - -class NotNullQuerySpec extends GormDatastoreSpec { - - static { - GormDatastoreSpec.TEST_CLASSES << NullMe - } - - void "Test query of null value with dynamic finder"() { - given: - new NullMe(name:"Bob", job:"Builder").save() - new NullMe(name:"Fred").save() - - when: - def results = NullMe.findAllByJobIsNull() - - then: - results.size() == 1 - results[0].name == "Fred" - - when: - results = NullMe.findAllByJobIsNotNull() - - then: - results.size() == 1 - results[0].name == "Bob" - } - - void "Test query of null value with criteria query"() { - given: - new NullMe(name:"Bob", job:"Builder").save() - new NullMe(name:"Fred").save() - - when: - def results = NullMe.withCriteria { isNull "job" } - - then: - results.size() == 1 - results[0].name == "Fred" - - when: - results = NullMe.withCriteria { isNotNull "job" } - - then: - results.size() == 1 - results[0].name == "Bob" - } -} - -@JpaEntity -class NullMe { - String name - String job - - static constraints = { - job nullable:true - } - - static mapping = { - job index:true - } -} - diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/OneToManySpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/OneToManySpec.groovy deleted file mode 100644 index adef8b5ee..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/OneToManySpec.groovy +++ /dev/null @@ -1,34 +0,0 @@ -package grails.gorm.tests - -class OneToManySpec extends GormDatastoreSpec { - - void "test save and return unidirectional one to many"() { - given: - Person p = new Person(firstName: "Fred", lastName: "Flinstone") - Country c = new Country(name:"Dinoville") - .addToResidents(p) - .save(flush:true) - - session.clear() - - when: - c = Country.findByName("Dinoville") - - then: - - c != null - c.residents != null - c.residents.size() == 1 - - when: - c.addToResidents(new Person(firstName:"Barney", lastName:"Rubble")) - c.save(flush:true) - session.clear() - c = Country.findByName("Dinoville") - - then: - c != null - c.residents != null - c.residents.size() == 2 - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy deleted file mode 100644 index 96702b291..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy +++ /dev/null @@ -1,9 +0,0 @@ -package grails.gorm.tests - -/** - * @author Burt Beckwith - */ -class OptimisticLockingSpec { - // TODO implement optimistic locking for JPA and delete this - void testNothing() {} -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Parent.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Parent.groovy deleted file mode 100644 index 37a16d6aa..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Parent.groovy +++ /dev/null @@ -1,13 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -/** - * @author Graeme Rocher - */ -@JpaEntity -class Parent { - String name - Set children = [] - static hasMany = [children: Child] -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Person.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Person.groovy deleted file mode 100644 index 0827186e7..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Person.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class Person implements Serializable { - String firstName - String lastName - Integer age = 0 - static hasMany = [pets:Pet] - - static mapping = { - firstName index:true - lastName index:true - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/PersonEvent.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/PersonEvent.groovy deleted file mode 100644 index caafe6bb9..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/PersonEvent.groovy +++ /dev/null @@ -1,59 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -import javax.persistence.Transient - -@JpaEntity -class PersonEvent implements Serializable { - String name - Date dateCreated - Date lastUpdated - - @Transient - def personService - - static STORE_INITIAL = [ - beforeDelete: 0, afterDelete: 0, - beforeUpdate: 0, afterUpdate: 0, - beforeInsert: 0, afterInsert: 0, - beforeLoad: 0, afterLoad: 0] - - static STORE = [:] + STORE_INITIAL - - static void resetStore() { - STORE = [:] + STORE_INITIAL - } - - void beforeDelete() { - STORE.beforeDelete++ - } - - void afterDelete() { - STORE.afterDelete++ - } - - void beforeUpdate() { - STORE.beforeUpdate++ - } - - void afterUpdate() { - STORE.afterUpdate++ - } - - void beforeInsert() { - STORE.beforeInsert++ - } - - void afterInsert() { - STORE.afterInsert++ - } - - void beforeLoad() { - STORE.beforeLoad++ - } - - void afterLoad() { - STORE.afterLoad++ - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Pet.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Pet.groovy deleted file mode 100644 index 5e9f7b4cf..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Pet.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class Pet implements Serializable { - String name - Date birthDate = new Date() - PetType type - Person owner -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/PetType.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/PetType.groovy deleted file mode 100644 index 2c12dac20..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/PetType.groovy +++ /dev/null @@ -1,8 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class PetType implements Serializable { - String name -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Plant.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Plant.groovy deleted file mode 100644 index 9d2361fc0..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Plant.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class Plant implements Serializable { - boolean goesInPatch - String name - - static mapping = { - name index:true - goesInPatch index:true - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/PlantCategory.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/PlantCategory.groovy deleted file mode 100644 index 111e58e3b..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/PlantCategory.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class PlantCategory implements Serializable { - String name - - static hasMany = [plants:Plant] - - static namedQueries = { -// withPlantsInPatch { -// plants { -// eq 'goesInPatch', true -// } -// } -// withPlantsThatStartWithG { -// plants { -// like 'name', 'G%' -// } -// } -// withPlantsInPatchThatStartWithG { -// withPlantsInPatch() -// withPlantsThatStartWithG() -// } - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Publication.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Publication.groovy deleted file mode 100644 index 8f87b0891..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Publication.groovy +++ /dev/null @@ -1,74 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class Publication implements Serializable { - String title - Date datePublished - Boolean paperback = true - - static mapping = { - title index:true - paperback index:true - datePublished index:true - } - - static namedQueries = { - lastPublishedBefore { date -> - uniqueResult = true - le 'datePublished', date - order 'datePublished', 'desc' - } - - recentPublications { - def now = new Date() - gt 'datePublished', now - 365 - } - - publicationsWithBookInTitle { - like 'title', 'Book%' - } - - recentPublicationsByTitle { title -> - recentPublications() - eq 'title', title - } - - latestBooks { - maxResults(10) - order("datePublished", "desc") - } - - publishedBetween { start, end -> - between 'datePublished', start, end - } - - publishedAfter { date -> - gt 'datePublished', date - } - - paperbackOrRecent { - or { - def now = new Date() - gt 'datePublished', now - 365 - paperbacks() - } - } - - paperbacks { - eq 'paperback', true - } - - paperbackAndRecent { - paperbacks() - recentPublications() - } - - thisWeeksPaperbacks() { - paperbacks() - def today = new Date() - publishedBetween(today - 7, today) - } - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/QueryAssociationSpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/QueryAssociationSpec.groovy deleted file mode 100644 index de8f74a53..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/QueryAssociationSpec.groovy +++ /dev/null @@ -1,308 +0,0 @@ -package grails.gorm.tests - -class QueryAssociationSpec extends GormDatastoreSpec{ - - void "Test query one-to-one association"() { - given: - new TestEntity(name:"Bob", age: 44, child:new ChildEntity(name:"Nick")).save(flush:true) - new TestEntity(name:"Fred", age: 32, child:new ChildEntity(name:"Jeff")).save(flush:true) - new TestEntity(name:"Charlie", age: 38, child:new ChildEntity(name:"Rosie")).save(flush:true) - new TestEntity(name:"Joe", age: 38, child:new ChildEntity(name:"Jake")).save(flush:true) - - when: "A query on the child association with an equals criterion is executed" - def results = TestEntity.withCriteria { - child { - eq 'name', 'Jeff' - } - } - then: "Check that the entity named Fred is returned" - TestEntity.count() == 4 - results.size() == 1 - results[0].name == "Fred" - - when: "A like criterion is executed on the child association" - results = TestEntity.withCriteria { - child { - like 'name', 'J%' - } - order "name" - } - - then: "Check that we get 2 results back" - results.size() == 2 - results[0].name == "Fred" - results[1].name == "Joe" - - when: "A not equals criterion is executed in a child association" - results = TestEntity.withCriteria { - child { - ne 'name', 'Rosie' - } - order "name" - } - - then: "Check that we get 3 results back" - results.size() == 3 - results[0].name == "Bob" - results[1].name == "Fred" - results[2].name == "Joe" - - when: "A between query is used" - results = TestEntity.withCriteria { - child { - between 'id', 1L, 2L - } - order "name" - } - - then: "Check we get the correct results" - results.size() == 2 - results[0].name == "Bob" - results[1].name == "Fred" - - when: "A greater than query is used" - results = TestEntity.withCriteria { - child { - gt 'id', 2L - } - order "name" - } - - then: "Check we get the correct results" - results.size() == 2 - results[0].name == "Charlie" - results[1].name == "Joe" - - when: "A less than query is used" - results = TestEntity.withCriteria { - child { - lt 'id', 3L - } - order "name" - } - - then: "Check we get the correct results" - results.size() == 2 - results[0].name == "Bob" - results[1].name == "Fred" - - when: "An in query is used" - results = TestEntity.withCriteria { - child { - inList 'name', ["Nick", "Rosie"] - } - order "name" - } - - then: "We get Bob and Charlie back" - - results.size() == 2 - results[0].name == "Bob" - results[1].name == "Charlie" - - when: "Multiple child criterion are used" - results = TestEntity.withCriteria { - child { - inList 'name', ["Nick", "Rosie"] - gt 'id', 2L - } - order "name" - } - - then: "We get the expected results back" - results.size() == 1 - results[0].name == "Charlie" - - when: "A disjunction is used" - results = TestEntity.withCriteria { - child { - or { - inList 'name', ["Nick", "Rosie"] - gt 'id', 2L - } - } - order "name" - } - - then: "We get the expected results back" - - results.size() == 3 - results[0].name == "Bob" - results[1].name == "Charlie" - results[2].name == "Joe" - - when: "A conjuntion is used" - results = TestEntity.withCriteria { - child { - and { - inList 'name', ["Nick", "Rosie"] - gt 'id', 2L - } - } - order "name" - } - - then: "We get the expected results back" - results.size() == 1 - results[0].name == "Charlie" - } - - void "Test query one-to-many association"() { - given: - new PlantCategory(name:"Tropical") - .addToPlants(name:"Pineapple") - .addToPlants(name:"Mango") - .addToPlants(name:"Lychee") - .save() - new PlantCategory(name:"Veg") - .addToPlants(name:"Cabbage", goesInPatch:true) - .addToPlants(name:"Carrot", goesInPatch:true) - .addToPlants(name:"Pumpkin", goesInPatch:true) - .addToPlants(name:"Tomatoe") - .save(flush:true) - new PlantCategory(name:"Nuts") - .addToPlants(name:"Walnut") - .addToPlants(name:"Coconut") - .save(flush:true) - - when: "The session is cleared" - session.clear() - def categories = PlantCategory.list(sort:"name") - - then: "Check that the state of the data is correct" - - categories.size() == 3 - categories[0] instanceof PlantCategory - categories[0].plants?.size() == 2 - - when: "A query on the child association with an equals criterion is executed" - def results = PlantCategory.withCriteria { - plants { - eq 'name', 'Mango' - } - } - - then: "Check that the Tropical plant is returned" - results.size() == 1 - results[0].name == "Tropical" - - when: "A like criterion is executed on the child association" - results = PlantCategory.withCriteria { - plants { - like 'name', 'P%' - } - order "name" - } - - then: "Check that we get 2 results back" - results.size() == 2 - results[0].name == "Tropical" - results[1].name == "Veg" - - when: "A not equals criterion is executed in a child association" - results = PlantCategory.withCriteria { - plants { - ne 'name', 'Carrot' - } - order "name" - } - - then: "Check that we get 3 results back" - results.size() == 3 - - when: "A between query is used" - results = PlantCategory.withCriteria { - plants { - between 'id', 3L, 5L - } - order "name" - } - - then: "Check we get the correct results" - results.size() == 2 - results[0].name == "Tropical" - results[1].name == "Veg" - - when: "A greater than query is used" - results = PlantCategory.withCriteria { - plants { - gt 'id', 5L - } - order "name" - } - - then: "Check we get the correct results" - results.size() == 2 - results[0].name == "Nuts" - results[1].name == "Veg" - - when: "A less than query is used" - results = PlantCategory.withCriteria { - plants { - lt 'id', 5L - } - order "name" - } - - then: "Check we get the correct results" - results.size() == 2 - results[0].name == "Tropical" - results[1].name == "Veg" - - when: "An in query is used" - results = PlantCategory.withCriteria { - plants { - inList 'name', ['Mango', 'Walnut'] - } - order "name" - } - then: "We get Tropical and Nuts back" - results.size() == 2 - results[0].name == "Nuts" - results[1].name == "Tropical" - - when: "Multiple child criterion are used" - results = PlantCategory.withCriteria { - plants { - like 'name', 'P%' - eq 'goesInPatch', true - } - order "name" - } - - then: "We get the expected results back" - results.size() == 1 - results[0].name == 'Veg' - - when: "A disjunction is used" - results = PlantCategory.withCriteria { - plants { - or { - like 'name', 'P%' - eq 'goesInPatch', true - } - } - order "name" - } - - then: "We get the expected results back" - results.size() == 2 - results[0].name == 'Tropical' - results[1].name == 'Veg' - - when: "A conjuntion is used" - results = PlantCategory.withCriteria { - plants { - and { - like 'name', 'P%' - eq 'goesInPatch', true - } - } - order "name" - } - - then: "We get the expected results back" - results.size() == 1 - results[0].name == 'Veg' - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Record.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Record.groovy deleted file mode 100644 index e7a0942b7..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Record.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -/** - * @author Graeme Rocher - */ -@JpaEntity -class Record { - Long id - String name - Date dateCreated - Date lastUpdated - - static mapping = { - autoTimestamp false - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/SessionCreationEventSpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/SessionCreationEventSpec.groovy deleted file mode 100644 index 5cb50c64d..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/SessionCreationEventSpec.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package grails.gorm.tests - -import org.springframework.context.event.SmartApplicationListener -import org.springframework.context.ApplicationEvent -import org.grails.datastore.mapping.core.SessionCreationEvent -import org.grails.datastore.mapping.core.Session -import spock.lang.Ignore - -/** - * Test case that session creation events are fired. - */ -@Ignore -class SessionCreationEventSpec extends GormDatastoreSpec { - - Listener listener - - def setup() { - listener = new Listener() - session.datastore.applicationContext.addApplicationListener(listener) - } - - void "test event for new session"() { - when:"Using existing session" - TestEntity.withSession { s -> - s.flush() - } - then: - listener.events.empty - - when:"Creating new session" - def newSession = null - def isDatastoreSession = false - TestEntity.withNewSession { s -> - newSession = s - isDatastoreSession = s instanceof Session - } - then: - !isDatastoreSession || listener.events.size() == 1 - !isDatastoreSession || listener.events[0].session == newSession - } - - - static class Listener implements SmartApplicationListener { - List events = [] - - @Override - int getOrder() { - Integer.MAX_VALUE / 2 - } - - @Override - void onApplicationEvent(ApplicationEvent event) { - events << event - } - - @Override - boolean supportsSourceType(Class sourceType) { - return true - } - - @Override - boolean supportsEventType(Class eventType) { - return eventType == SessionCreationEvent - } - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Simples.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Simples.groovy deleted file mode 100644 index 4d9562a77..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Simples.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -/** - * @author Graeme Rocher - */ -@JpaEntity -class Simples { - String name -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy deleted file mode 100644 index 082db7656..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.tests.GormDatastoreSpec -import org.junit.Ignore - -/** - * Tests for querying the size of collections etc. - */ -class SizeQuerySpec extends GormDatastoreSpec { - - @Ignore - void "Test sizeEq criterion"() { - // TODO: implement sizeEq query operations - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/StringBasedQuerySpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/StringBasedQuerySpec.groovy deleted file mode 100644 index 19b86a4c1..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/StringBasedQuerySpec.groovy +++ /dev/null @@ -1,61 +0,0 @@ -package grails.gorm.tests - -class StringBasedQuerySpec extends GormDatastoreSpec { - - void "Test findAll method that takes a JPQL string"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - when: - def people = TestEntity.findAll("select te from TestEntity as te") - - then: - people.size() == 4 - - when: - people = TestEntity.findAll("select te from TestEntity as te", [max:2]) - - then: - people.size() == 2 - - when: - people = TestEntity.findAll("select te from TestEntity as te where te.name like ?1", ["B%"]) - - then: - people.size() == 2 - - when: - people = TestEntity.findAll("select te from TestEntity as te where te.name like :name", [name:"B%"]) - - then: - people.size() == 2 - - } - - void "Test find method that takes a JPQL string"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - when: - def person = TestEntity.find("select te from TestEntity as te") - - then: - person != null - - when: - person = TestEntity.find("select te from TestEntity as te where te.name = ?1", ["Bob"]) - - then: - person != null - person.name == "Bob" - - when: - person = TestEntity.find("select te from TestEntity as te where te.name = :name", [name:"Frank"]) - - then: - person != null - person.name == "Frank" - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Task.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Task.groovy deleted file mode 100644 index 099a78144..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/Task.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class Task implements Serializable { - Task task - String name - - static mapping = { - name index:true - } - - static hasMany = [tasks:Task] -} \ No newline at end of file diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/TestEntity.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/TestEntity.groovy deleted file mode 100644 index ff8b5ec56..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/TestEntity.groovy +++ /dev/null @@ -1,22 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class TestEntity { - String name - Integer age - - ChildEntity child - - static mapping = { - name index:true - age index:true - child index:true - } - - static constraints = { - name blank:false - child nullable:true - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/UniqueGroup.groovy b/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/UniqueGroup.groovy deleted file mode 100644 index 369c3d67e..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/grails/gorm/tests/UniqueGroup.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.JpaEntity - -@JpaEntity -class UniqueGroup implements Serializable{ - Long id - String name - static constraints = { - name unique:true - } - static mapping = { - table 'groups_table' - name index:true - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/JpaMappingConfigurationSpec.groovy b/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/JpaMappingConfigurationSpec.groovy deleted file mode 100644 index 4108fe7af..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/JpaMappingConfigurationSpec.groovy +++ /dev/null @@ -1,63 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.JpaEntity - -import javax.persistence.OneToMany -import javax.persistence.OneToOne - -import org.grails.datastore.mapping.jpa.config.JpaMappingConfigurationStrategy -import org.grails.datastore.mapping.jpa.config.JpaMappingContext -import org.grails.datastore.mapping.jpa.config.JpaMappingFactory - -import spock.lang.Specification - -class JpaMappingConfigurationSpec extends Specification { - - void "Test that a JPA entity is detected as such"() { - - when: - def configStrategy = new JpaMappingConfigurationStrategy() - - then: - configStrategy.isPersistentEntity(JpaDomain.class) == true - configStrategy.isPersistentEntity(JpaMappingConfigurationSpec) == false - } - - void "Test persistent properties are valid"() { - when: - def configStrategy = new JpaMappingConfigurationStrategy(new JpaMappingFactory()) - final context = new JpaMappingContext() - context.addPersistentEntity(JpaDomain) - def properties = configStrategy.getPersistentProperties(JpaDomain, context).sort { it.name } - - then: - properties.size() == 3 - - properties[0] instanceof org.grails.datastore.mapping.model.types.OneToMany - properties[0].name == "many" - - properties[1].name == "name" - properties[2].name == "other" - properties[2] instanceof org.grails.datastore.mapping.model.types.OneToOne - } -} - -@JpaEntity -class JpaDomain { - Long id - - String name - - @OneToOne - JpaOther other - - @OneToMany - Set many -} - -@JpaEntity -class JpaOther { - Long id - - String name -} 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 deleted file mode 100644 index 08af12bff..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/JpaSuite.groovy +++ /dev/null @@ -1,68 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.AttachMethodSpec -import grails.gorm.tests.CircularOneToManySpec -import grails.gorm.tests.CommonTypesPersistenceSpec -import grails.gorm.tests.CriteriaBuilderSpec -import grails.gorm.tests.CrudOperationsSpec -import grails.gorm.tests.DomainEventsSpec -import grails.gorm.tests.FindByMethodSpec -import grails.gorm.tests.GormEnhancerSpec -import grails.gorm.tests.GroovyProxySpec -import grails.gorm.tests.InheritanceSpec -import grails.gorm.tests.ListOrderBySpec -import grails.gorm.tests.NamedQuerySpec -import grails.gorm.tests.NegationSpec -import grails.gorm.tests.OneToManySpec -import grails.gorm.tests.OrderBySpec -import grails.gorm.tests.PersistenceEventListenerSpec -import grails.gorm.tests.ProxyLoadingSpec -import grails.gorm.tests.QueryAfterPropertyChangeSpec -import grails.gorm.tests.RangeQuerySpec -import grails.gorm.tests.SaveAllSpec -import grails.gorm.tests.UpdateWithProxyPresentSpec -import grails.gorm.tests.ValidationSpec -import grails.gorm.tests.WithTransactionSpec -import org.junit.runner.RunWith -import org.junit.runners.Suite -import org.junit.runners.Suite.SuiteClasses -import grails.gorm.tests.DetachedCriteriaSpec -import grails.gorm.tests.UniqueConstraintSpec -import grails.gorm.tests.DeleteAllSpec -//import grails.gorm.tests.WhereMethodSpec - -@RunWith(Suite) -@SuiteClasses([ -// DetachedCriteriaSpec -// OneToManySpec, -// SaveAllSpec, -// GormEnhancerSpec, -// DomainEventsSpec -// ProxyLoadingSpec, -// QueryAfterPropertyChangeSpec, -// CircularOneToManySpec, -// InheritanceSpec, -// FindByMethodSpec, -// ListOrderBySpec, -// GroovyProxySpec, -// CommonTypesPersistenceSpec, -// CriteriaBuilderSpec, -// NegationSpec, -// NamedQuerySpec, -// OrderBySpec, -// RangeQuerySpec, -// ValidationSpec, -// UpdateWithProxyPresentSpec, -// AttachMethodSpec, -// WithTransactionSpec, -// CrudOperationsSpec - // WhereMethodSpec -//UniqueConstraintSpec, -//SaveAllSpec, -//DeleteAllSpec -// PersistenceEventListenerSpec -UpdateWithProxyPresentSpec -]) -class JpaSuite { - -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/JpaTransformTest.groovy b/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/JpaTransformTest.groovy deleted file mode 100644 index 12f95ddba..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/JpaTransformTest.groovy +++ /dev/null @@ -1,321 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.JpaEntity - -import javax.persistence.Basic -import javax.persistence.CascadeType -import javax.persistence.Embedded -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id -import javax.persistence.ManyToMany -import javax.persistence.ManyToOne -import javax.persistence.OneToMany -import javax.persistence.OneToOne -import javax.persistence.PostLoad -import javax.persistence.PostPersist -import javax.persistence.PostRemove -import javax.persistence.PostUpdate -import javax.persistence.PrePersist -import javax.persistence.PreRemove -import javax.persistence.PreUpdate -import javax.persistence.Table -import javax.persistence.Temporal -import javax.persistence.Transient -import javax.persistence.Version - -class JpaTransformTest extends GroovyTestCase { - - void testSimpleAnnotatedEntity() { - - def ann = Simple.getAnnotation(Entity) - - assert ann != null - - def idField = Simple.getDeclaredField("id") - - assert idField != null - - def idAnn = idField.getAnnotation(Id.class) - - assert idAnn != null - - GeneratedValue genAnn = idField.getAnnotation(GeneratedValue.class) - - assert genAnn != null - assert genAnn.strategy() == GenerationType.AUTO - - def ageField = Simple.getDeclaredField("age") - - assert ageField != null - - def ageAnn = ageField.getAnnotation(Transient) - - assert ageAnn != null - - def nameField = Simple.getDeclaredField("name") - - assert nameField != null - - def nameAnn = nameField.getAnnotation(Basic) - - assert nameAnn != null - - def dateCreatedField = Simple.getDeclaredField("dateCreated") - - assert dateCreatedField != null - - def dateCreatedAnn = dateCreatedField.getAnnotation(Temporal) - - assert dateCreatedAnn != null - - def addressField = Simple.class.getDeclaredField("address") - - assert addressField != null - - def addressAnn = addressField.getAnnotation(Embedded) - - assert addressAnn != null - - def personField = Simple.class.getDeclaredField("person") - - assert personField != null - - def personAnn = personField.getAnnotation(ManyToOne) - - assert personAnn != null - } - - void testBidirectionalOneToMany() { - def petsField = Person.class.getDeclaredField("pets") - - assert petsField != null - - OneToMany petsAnn = petsField.getAnnotation(OneToMany) - - assert petsAnn != null - - assert petsAnn.targetEntity() == Pet - assert petsAnn.mappedBy() == "owner" - assert petsAnn.cascade() - assert petsAnn.cascade()[0] == CascadeType.ALL - - def ownerField = Pet.class.getDeclaredField("owner") - - assert ownerField != null - def ownerAnn = ownerField.getAnnotation(ManyToOne) - assert ownerAnn != null - } - - void testUnidirectionalOneToMany() { - def addressesField = Person.class.getDeclaredField("addresses") - - assert addressesField != null - OneToMany addressAnn = addressesField.getAnnotation(OneToMany) - assert addressAnn != null - - assert addressAnn.targetEntity() == Address - assert addressAnn.cascade() - assert addressAnn.cascade()[0] == CascadeType.ALL - } - - void testOneToOne() { - def carField = Person.class.getDeclaredField("car") - - assert carField != null - - OneToOne carAnn = carField.getAnnotation(OneToOne) - - assert carAnn != null - - assert carAnn.optional() == false - assert carAnn.cascade() - assert carAnn.cascade()[0] == CascadeType.ALL - - def ownerField = Car.class.getDeclaredField("owner") - - assert ownerField != null - OneToOne ownerAnn = ownerField.getAnnotation(OneToOne) - - assert ownerAnn != null - assert ownerAnn.mappedBy() == "car" - } - - void testManyToMany() { - def contractsField = Person.class.getDeclaredField("contracts") - - assert contractsField != null - - ManyToMany contractsAnn = contractsField.getAnnotation(ManyToMany) - - assert contractsAnn != null - assert contractsAnn.targetEntity() == Contract - assert contractsAnn.cascade() - assert contractsAnn.cascade()[0] == CascadeType.ALL - assert contractsAnn.mappedBy() == "" - - def peopleField = Contract.class.getDeclaredField("people") - - assert peopleField != null - - ManyToMany peopleAnn = peopleField.getAnnotation(ManyToMany) - - assert peopleAnn != null - assert peopleAnn.mappedBy() == "contracts" - assert peopleAnn.targetEntity() == Person.class - } - - void testJpaEventMethods() { - def beforeInsert = Simple.class.getDeclaredMethod("beforeInsert", null) - - assert beforeInsert != null - assert beforeInsert.getAnnotation(PrePersist) != null - - def afterInsert = Simple.class.getDeclaredMethod("afterInsert", null) - - assert afterInsert != null - assert afterInsert.getAnnotation(PostPersist) != null - - def afterLoad = Simple.class.getDeclaredMethod("afterLoad", null) - - assert afterLoad != null - assert afterLoad.getAnnotation(PostLoad) != null - - def beforeUpdate = Simple.class.getDeclaredMethod("beforeUpdate", null) - - assert beforeUpdate != null - assert beforeUpdate.getAnnotation(PreUpdate) != null - - def afterUpdate = Simple.class.getDeclaredMethod("afterUpdate", null) - - assert afterUpdate != null - assert afterUpdate.getAnnotation(PostUpdate) != null - - def beforeDelete = Simple.class.getDeclaredMethod("beforeDelete", null) - - assert beforeDelete != null - assert beforeDelete.getAnnotation(PreRemove) != null - - def afterDelete = Simple.class.getDeclaredMethod("afterDelete", null) - - assert afterDelete != null - assert afterDelete.getAnnotation(PostRemove) != null - } - - void testCustomColumnMappingAndIdMapping() { - Table tableAnn = Force.class.getAnnotation(Table) - - assert tableAnn != null - assert tableAnn.name() == "the_force" - def myIdField = Force.class.getDeclaredField("myId") - - assert myIdField.getAnnotation(Id) != null - assert myIdField.getAnnotation(GeneratedValue) == null - - def versionField = Force.class.getDeclaredField("version") - - assert versionField != null - assert versionField.getAnnotation(Version) == null - - shouldFail { - Force.class.getDeclaredField("id") - } - } -} - -@JpaEntity -class Simple { - Long id - Long version - - String name - Integer age - Address address - Person person - Date dateCreated - - static transients = ['age'] - static embedded = ["address"] - - def beforeInsert() { - - } - - def afterInsert() { - - } - - def afterLoad() { - - } - - def beforeUpdate() { - - } - - def afterUpdate() { - - } - - def beforeDelete() { - - } - - def afterDelete() { - - } -} -@JpaEntity -class Address {} - -@JpaEntity -class Person { - Long id - - Set pets - Set addresses - Set contracts - Car car - static hasOne = [car:Car] - static hasMany = [pets:Pet,addresses:Address, contracts:Contract] -} - -@JpaEntity -class Contract { - Set people - static hasMany = [people:Person] - static belongsTo = Person -} - -@JpaEntity -class Car { - Person owner - Integer doors = 4 - static belongsTo = [owner:Person] -} - -@JpaEntity -class Pet { - Person owner - static belongsTo = [ owner: Person ] -} - -@JpaEntity -class Force { - String myId - Long version - String name - - static constraints = { - name size:5..15, nullable:true - } - - static mapping = { - table "the_force" - id name:"myId", generator:"assigned" - - name column:"the_name" - version false - } -} diff --git a/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/Setup.groovy deleted file mode 100644 index 275123b75..000000000 --- a/grails-datastore-gorm-jpa/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ /dev/null @@ -1,82 +0,0 @@ -package org.grails.datastore.gorm - -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.gorm.jpa.JpaGormEnhancer -import org.hibernate.dialect.HSQLDialect -import org.hibernate.ejb.Ejb3Configuration -import org.hsqldb.jdbcDriver -import org.springframework.context.support.GenericApplicationContext -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.jpa.JpaDatastore -import org.grails.datastore.mapping.jpa.config.JpaMappingContext -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.springframework.orm.jpa.JpaTransactionManager -import org.springframework.util.StringUtils -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -class Setup { - - static jpaDatastore - static trans - - static destroy() { - trans.commit() - JpaDatastore.retrieveSession().disconnect() - } - - static Session setup(classes) { - - def config = new Ejb3Configuration() - config.setProperty "hibernate.dialect", HSQLDialect.name - config.setProperty "hibernate.connection.driver_class", jdbcDriver.name - config.setProperty "hibernate.connection.url", "jdbc:hsqldb:mem:devDB" - config.setProperty "hibernate.connection.username", "sa" - config.setProperty "hibernate.connection.password", "" - config.setProperty "hibernate.hbm2ddl.auto", "create-drop" - config.setProperty "hibernate.show_sql", "true" - config.setProperty "hibernate.format_sql", "true" - - def context = new JpaMappingContext() - for (Class c in classes) { - config.addAnnotatedClass c - context.addPersistentEntity c - } - - def entityManagerFactory = config.buildEntityManagerFactory() - - def txMgr = new JpaTransactionManager(entityManagerFactory) - - def ctx = new GenericApplicationContext() - ctx.refresh() - jpaDatastore = new JpaDatastore(context, entityManagerFactory, txMgr, ctx) - - PersistentEntity entity = jpaDatastore.mappingContext.persistentEntities.find { PersistentEntity e -> e.name.contains("TestEntity")} - - jpaDatastore.mappingContext.addEntityValidator(entity, [ - supports: { Class c -> true }, - validate: { Object o, Errors errors -> - if (!StringUtils.hasText(o.name)) { - errors.rejectValue("name", "name.is.blank") - } - } - ] as Validator) - - def enhancer = new JpaGormEnhancer(jpaDatastore, txMgr) - enhancer.enhance() - - jpaDatastore.mappingContext.addMappingContextListener({ e -> - enhancer.enhance e - } as MappingContext.Listener) - - jpaDatastore.applicationContext.addApplicationListener new DomainEventListener(jpaDatastore) - jpaDatastore.applicationContext.addApplicationListener new AutoTimestampEventListener(jpaDatastore) - - def session = jpaDatastore.connect() - - trans = session.beginTransaction() - return session - } -} diff --git a/grails-datastore-gorm-mongo/build.gradle b/grails-datastore-gorm-mongo/build.gradle deleted file mode 100644 index 801530466..000000000 --- a/grails-datastore-gorm-mongo/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -version = "1.3.0.BUILD-SNAPSHOT" -configurations { - grails -} - -dependencies { - compile("com.gmongo:gmongo:1.2") { - transitive = false - } - grails("org.grails:grails-core:$grailsVersion") - grails("org.grails:grails-bootstrap:$grailsVersion") { - transitive = false - } - compile project(":grails-datastore-gorm"), - project(":grails-datastore-gorm-plugin-support"), - project(":grails-datastore-mongo"), - project(":grails-datastore-core") - testCompile project(":grails-datastore-gorm-test"), - project(":grails-datastore-gorm-tck") - - testRuntime "javax.servlet:servlet-api:2.5" - testRuntime "org.grails:grails-web:$grailsVersion" -} - -sourceSets { - main { - compileClasspath += configurations.grails - } -} diff --git a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/MongoCriteriaBuilder.java b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/MongoCriteriaBuilder.java deleted file mode 100644 index 0b662cf95..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/MongoCriteriaBuilder.java +++ /dev/null @@ -1,111 +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; - -import grails.gorm.CriteriaBuilder; - -import java.util.List; -import java.util.Map; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.mongo.query.MongoQuery.Near; -import org.grails.datastore.mapping.mongo.query.MongoQuery.WithinBox; -import org.grails.datastore.mapping.mongo.query.MongoQuery.WithinPolygon; -import org.grails.datastore.mapping.mongo.query.MongoQuery.WithinCircle; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.Criteria; -import org.grails.datastore.mapping.query.api.QueryArgumentsAware; - -/** - * Extends the default CriteriaBuilder implementation with Geolocation methods - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class MongoCriteriaBuilder extends CriteriaBuilder { - - public MongoCriteriaBuilder(final Class targetClass, final Session session, final Query query) { - super(targetClass, session, query); - } - - public MongoCriteriaBuilder(final Class targetClass, final Session session) { - super(targetClass, session); - } - - /** - * Geospacial query for values near the given two dimensional list - * - * @param property The property - * @param value A two dimensional list of values - * @return this Criterion - */ - public Criteria near(String property, List value) { - validatePropertyName(property, "near"); - addToCriteria(new Near(property, value)); - return this; - } - - /** - * Geospacial query for values within a given box. A box is defined as a multi-dimensional list in the form - * - * [[40.73083, -73.99756], [40.741404, -73.988135]] - * - * @param property The property - * @param value A multi-dimensional list of values - * @return this Criterion - */ - public Criteria withinBox(String property, List value) { - validatePropertyName(property, "withinBox"); - addToCriteria(new WithinBox(property, value)); - return this; - } - - /** - * Geospacial query for values within a given polygon. A polygon is defined as a multi-dimensional list in the form - * - * [[0, 0], [3, 6], [6, 0]] - * - * @param property The property - * @param value A multi-dimensional list of values - * @return this Criterion - */ - public Criteria withinPolygon(String property, List value) { - validatePropertyName(property, "withinPolygon"); - addToCriteria(new WithinPolygon(property, value)); - return this; - } - - /** - * Geospacial query for values within a given circle. A circle is defined as a multi-dimensial list containing the position of the center and the radius: - * - * [[50, 50], 10] - * - * @param property The property - * @param value A multi-dimensional list of values - * @return this Criterion - */ - public Criteria withinCircle(String property, List value) { - validatePropertyName(property, "withinBox"); - addToCriteria(new WithinCircle(property, value)); - return this; - } - - public Criteria arguments(Map arguments) { - ((QueryArgumentsAware)this.query).setArguments(arguments); - return this; - } -} diff --git a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/MongoGormEnhancer.groovy b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/MongoGormEnhancer.groovy deleted file mode 100644 index 756dbda34..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/MongoGormEnhancer.groovy +++ /dev/null @@ -1,277 +0,0 @@ -/* Copyright (C) 2010 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 - -import com.gmongo.internal.DBCollectionPatcher -import com.mongodb.BasicDBObject -import com.mongodb.DB -import com.mongodb.DBCollection -import com.mongodb.DBObject -import org.grails.datastore.gorm.finders.DynamicFinder -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.core.SessionCallback -import org.grails.datastore.mapping.core.SessionImplementor -import org.grails.datastore.mapping.mongo.MongoSession -import org.grails.datastore.mapping.mongo.engine.MongoEntityPersister -import org.grails.datastore.mapping.mongo.MongoDatastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * GORM enhancer for Mongo. - * - * @author Graeme Rocher - */ -class MongoGormEnhancer extends GormEnhancer { - - MongoGormEnhancer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - - DynamicFinder.registerNewMethodExpression(Near) - DynamicFinder.registerNewMethodExpression(WithinBox) - DynamicFinder.registerNewMethodExpression(WithinPolygon) - DynamicFinder.registerNewMethodExpression(WithinCircle) - } - - MongoGormEnhancer(Datastore datastore) { - this(datastore, null) - } - - protected GormStaticApi getStaticApi(Class cls) { - return new MongoGormStaticApi(cls, datastore, getFinders()) - } - - protected GormInstanceApi getInstanceApi(Class cls) { - final api = new MongoGormInstanceApi(cls, datastore) - api.failOnError = failOnError - return api - } -} - -class MongoGormInstanceApi extends GormInstanceApi { - - MongoGormInstanceApi(Class persistentClass, Datastore datastore) { - super(persistentClass, datastore) - } - - /** - * Allows accessing to dynamic properties with the dot operator - * - * @param instance The instance - * @param name The property name - * @return The property value - */ - def propertyMissing(D instance, String name) { - getAt(instance, name) - } - - /** - * Allows setting a dynamic property via the dot operator - * @param instance The instance - * @param name The property name - * @param val The value - */ - def propertyMissing(D instance, String name, val) { - putAt(instance, name, val) - } - /** - * Allows subscript access to schemaless attributes. - * - * @param instance The instance - * @param name The name of the field - */ - void putAt(D instance, String name, value) { - if (instance.hasProperty(name)) { - instance.setProperty(name, value) - } - else { - execute (new SessionCallback() { - DBObject doInSession(Session session) { - SessionImplementor si = (SessionImplementor)session - - if (si.isStateless(persistentEntity)) { - MongoDatastore ms = (MongoDatastore)datastore - def template = ms.getMongoTemplate(persistentEntity) - - def coll = template.getCollection(ms.getCollectionName(persistentEntity)) - MongoEntityPersister persister = session.getPersister(instance) - def id = persister.getObjectIdentifier(instance) - final updateObject = new BasicDBObject('$set', new BasicDBObject(name, value)) - coll.update(new BasicDBObject(MongoEntityPersister.MONGO_ID_FIELD,id), updateObject) - return updateObject - } - else { - final dbo = getDbo(instance) - dbo?.put name, value - return dbo - } - } - }) - - } - } - - /** - * Allows subscript access to schemaless attributes. - * - * @param instance The instance - * @param name The name of the field - * @return the value - */ - def getAt(D instance, String name) { - if (instance.hasProperty(name)) { - return instance.getProperty(name) - } - - def dbo = getDbo(instance) - if (dbo != null && dbo.containsField(name)) { - return dbo.get(name) - } - return null - } - - /** - * Return the DBObject instance for the entity - * - * @param instance The instance - * @return The DBObject instance - */ - DBObject getDbo(D instance) { - execute (new SessionCallback() { - DBObject doInSession(Session session) { - - if (!session.contains(instance) && !instance.save()) { - throw new IllegalStateException( - "Cannot obtain DBObject for transient instance, save a valid instance first") - } - - MongoEntityPersister persister = session.getPersister(instance) - def id = persister.getObjectIdentifier(instance) - def dbo = session.getCachedEntry(persister.getPersistentEntity(), id) - if (dbo == null) { - MongoDatastore ms = (MongoDatastore)datastore - def template = ms.getMongoTemplate(persistentEntity) - - def coll = template.getCollection(ms.getCollectionName(persistentEntity)) - dbo = coll.findOne( id ) - - } - return dbo - } - }) - } -} - -class MongoGormStaticApi extends GormStaticApi { - - MongoGormStaticApi(Class persistentClass, Datastore datastore, List finders) { - super(persistentClass, datastore, finders) - } - - @Override - MongoCriteriaBuilder createCriteria() { - return new MongoCriteriaBuilder(persistentClass, datastore.currentSession) - } - - /** - * @return The database for this domain class - */ - DB getDB() { - MongoSession ms = (MongoSession)datastore.currentSession - ms.getMongoTemplate(persistentEntity).getDb() - } - - /** - * @return The name of the Mongo collection that entity maps to - */ - String getCollectionName() { - MongoSession ms = (MongoSession)datastore.currentSession - ms.getCollectionName(persistentEntity) - } - - /** - * The actual collection that this entity maps to. - * - * @return The actual collection - */ - DBCollection getCollection() { - MongoSession ms = (MongoSession)datastore.currentSession - def template = ms.getMongoTemplate(persistentEntity) - - def coll = template.getCollection(ms.getCollectionName(persistentEntity)) - DBCollectionPatcher.patch(coll) - return coll - } - - /** - * Use the given collection for this entity for the scope of the closure call - * @param collectionName The collection name - * @param callable The callable - * @return The result of the closure - */ - def withCollection(String collectionName, Closure callable) { - MongoSession ms = (MongoSession)datastore.currentSession - final previous = ms.useCollection(persistentEntity, collectionName) - try { - callable.call(ms) - } - finally { - ms.useCollection(persistentEntity, previous) - } - } - - /** - * Use the given collection for this entity for the scope of the session - * - * @param collectionName The collection name - * @return The previous collection name - */ - String useCollection(String collectionName) { - MongoSession ms = (MongoSession)datastore.currentSession - ms.useCollection(persistentEntity, collectionName) - } - - /** - * Use the given database for this entity for the scope of the closure call - * @param databaseName The collection name - * @param callable The callable - * @return The result of the closure - */ - def withDatabase(String databaseName, Closure callable) { - MongoSession ms = (MongoSession)datastore.currentSession - final previous = ms.useDatabase(persistentEntity, databaseName) - try { - callable.call(ms) - } - finally { - ms.useDatabase(persistentEntity, previous) - } - } - - /** - * Use the given database for this entity for the scope of the session - * - * @param databaseName The collection name - * @return The previous database name - */ - String useDatabase(String databaseName) { - MongoSession ms = (MongoSession)datastore.currentSession - ms.useDatabase(persistentEntity, databaseName) - } -} diff --git a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/Near.java b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/Near.java deleted file mode 100644 index 506456260..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/Near.java +++ /dev/null @@ -1,47 +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; - -import java.util.Collection; -import java.util.List; - -import org.grails.datastore.gorm.finders.MethodExpression; -import org.grails.datastore.mapping.mongo.query.MongoQuery; -import org.grails.datastore.mapping.query.Query.Criterion; -import org.springframework.util.Assert; - -public class Near extends MethodExpression { - - public Near(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Criterion createCriterion() { - return new MongoQuery.Near(propertyName, (List) arguments[0]); - } - - @Override - public void setArguments(Object[] arguments) { - Assert.isTrue(arguments.length > 0 && arguments[0] instanceof List, - "Only a list of elements is supported in an 'near' query"); - - Collection argument = (Collection) arguments[0]; - Assert.isTrue(argument.size() == 2, - "A 'near' query requires a two dimensional list of values"); - - super.setArguments(arguments); - } -} diff --git a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/WithinBox.java b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/WithinBox.java deleted file mode 100644 index 7a0cf3ee1..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/WithinBox.java +++ /dev/null @@ -1,54 +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; - -import java.util.Collection; -import java.util.List; - -import org.grails.datastore.gorm.finders.MethodExpression; -import org.grails.datastore.mapping.mongo.query.MongoQuery; -import org.grails.datastore.mapping.query.Query.Criterion; -import org.springframework.util.Assert; - -/** - * Dynamic finder expression for within box queries - * - * @author Graeme Rocher - * @since 1.0 - */ -public class WithinBox extends MethodExpression { - - public WithinBox(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Criterion createCriterion() { - return new MongoQuery.WithinBox(propertyName, (List) arguments[0]); - } - - @Override - public void setArguments(Object[] arguments) { - Assert.isTrue(arguments.length > 0 && arguments[0] instanceof List, - "Only a list of elements is supported in a 'withinBox' query"); - - Collection argument = (Collection) arguments[0]; - Assert.isTrue(argument.size() == 2, - "A 'withinBox' query requires a two dimensional list of values"); - - super.setArguments(arguments); - } -} diff --git a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/WithinCircle.java b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/WithinCircle.java deleted file mode 100644 index baba1d0f3..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/WithinCircle.java +++ /dev/null @@ -1,54 +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; - -import java.util.Collection; -import java.util.List; - -import org.grails.datastore.gorm.finders.MethodExpression; -import org.grails.datastore.mapping.mongo.query.MongoQuery; -import org.grails.datastore.mapping.query.Query.Criterion; -import org.springframework.util.Assert; - -/** - * A dynamic finder method expression that adds the ability to query within a circle - * - * @author Graeme Rocher - * @since 1.0 - */ -public class WithinCircle extends MethodExpression { - - public WithinCircle(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Criterion createCriterion() { - return new MongoQuery.WithinCircle(propertyName, (List) arguments[0]); - } - - @Override - public void setArguments(Object[] arguments) { - Assert.isTrue(arguments.length > 0 && arguments[0] instanceof List, - "Only a list of elements is supported in a 'WithinCircle' query"); - - Collection argument = (Collection) arguments[0]; - Assert.isTrue(argument.size() == 2, - "A 'WithinCircle' query requires a two dimensional list of values"); - - super.setArguments(arguments); - } -} diff --git a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/WithinPolygon.java b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/WithinPolygon.java deleted file mode 100644 index e7954a69b..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/WithinPolygon.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.grails.datastore.gorm.mongo; - -import java.util.Collection; -import java.util.List; - -import org.grails.datastore.gorm.finders.MethodExpression; -import org.grails.datastore.mapping.mongo.query.MongoQuery; -import org.grails.datastore.mapping.query.Query.Criterion; -import org.springframework.util.Assert; - -/** - * Dynamic finder expression for within polygon queries - * - * @author Sergei Shushkevich - */ -public class WithinPolygon extends MethodExpression { - - public WithinPolygon(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Criterion createCriterion() { - return new MongoQuery.WithinPolygon(propertyName, (List) arguments[0]); - } - - @Override - public void setArguments(Object[] arguments) { - Assert.isTrue(arguments.length > 0 && arguments[0] instanceof List, - "Only a list of elements is supported in a 'withinPolygon' query"); - - Collection argument = (Collection) arguments[0]; - Assert.isTrue(argument.size() == 2, - "A 'withinPolygon' query requires a two dimensional list of values"); - - super.setArguments(arguments); - } -} diff --git a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/bean/factory/GMongoFactoryBean.java b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/bean/factory/GMongoFactoryBean.java deleted file mode 100644 index 2f12996e3..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/bean/factory/GMongoFactoryBean.java +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright (C) 2010 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.bean.factory; - -import java.net.UnknownHostException; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.grails.datastore.mapping.model.DatastoreConfigurationException; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -import com.gmongo.GMongo; -import com.mongodb.MongoOptions; -import com.mongodb.ServerAddress; - -/** - * A Factory bean for initializing a {@link GMongo} instance - * - * @author Graeme Rocher - */ -public class GMongoFactoryBean implements FactoryBean, InitializingBean/*, - PersistenceExceptionTranslator*/ { - - /** - * Logger, available to subclasses. - */ - protected final Log logger = LogFactory.getLog(getClass()); - - private GMongo mongo; - private MongoOptions mongoOptions; - private String host; - private Integer port; - private List replicaSetSeeds; - private List replicaPair; - - public void setReplicaPair(List replicaPair) { - this.replicaPair = replicaPair; - } - - public void setReplicaSetSeeds(List replicaSetSeeds) { - this.replicaSetSeeds = replicaSetSeeds; - } - - public void setMongoOptions(MongoOptions mongoOptions) { - this.mongoOptions = mongoOptions; - } - - public void setHost(String host) { - this.host = host; - } - - public void setPort(int port) { - this.port = port; - } - - public GMongo getObject() throws Exception { - Assert.notNull(mongo, "Mongo must not be null"); - return mongo; - } - - public Class getObjectType() { - return GMongo.class; - } - - public boolean isSingleton() { - return false; - } - - public void afterPropertiesSet() throws UnknownHostException { - // apply defaults - convenient when used to configure for tests - // in an application context - if (mongo != null) { - return; - } - - ServerAddress defaultOptions = new ServerAddress(); - if (mongoOptions == null) mongoOptions = new MongoOptions(); - if (replicaPair != null) { - if (replicaPair.size() < 2) { - throw new DatastoreConfigurationException("A replica pair must have two server entries"); - } - mongo = new GMongo(replicaPair.get(0), replicaPair.get(1), mongoOptions); - } - else if (replicaSetSeeds != null) { - mongo = new GMongo(replicaSetSeeds, mongoOptions); - } - else { - String mongoHost = host != null ? host : defaultOptions.getHost(); - if (port != null) { - mongo = new GMongo(new ServerAddress(mongoHost, port), mongoOptions); - } - else { - mongo = new GMongo(mongoHost, mongoOptions); - } - } - } - -} diff --git a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/bean/factory/MongoDatastoreFactoryBean.groovy b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/bean/factory/MongoDatastoreFactoryBean.groovy deleted file mode 100644 index 515dbf447..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/bean/factory/MongoDatastoreFactoryBean.groovy +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (C) 2010 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.bean.factory - -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.springframework.beans.factory.FactoryBean -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.mongo.MongoDatastore - -import com.mongodb.Mongo - -/** - * Factory bean for constructing a {@link MongoDatastore} instance. - * - * @author Graeme Rocher - */ -class MongoDatastoreFactoryBean implements FactoryBean, ApplicationContextAware { - - Mongo mongo - MappingContext mappingContext - Map config = [:] - ApplicationContext applicationContext - - MongoDatastore getObject() { - - MongoDatastore datastore - if (mongo) { - datastore = new MongoDatastore(mappingContext, mongo, config, applicationContext) - } - else { - datastore = new MongoDatastore(mappingContext, config, applicationContext) - } - - applicationContext.addApplicationListener new DomainEventListener(datastore) - applicationContext.addApplicationListener new AutoTimestampEventListener(datastore) - - datastore.afterPropertiesSet() - datastore - } - - Class getObjectType() { MongoDatastore } - - boolean isSingleton() { true } -} diff --git a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/bean/factory/MongoMappingContextFactoryBean.groovy b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/bean/factory/MongoMappingContextFactoryBean.groovy deleted file mode 100644 index 37fa4ff9b..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/bean/factory/MongoMappingContextFactoryBean.groovy +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (C) 2010 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.bean.factory - -import groovy.transform.Canonical - -import org.grails.datastore.gorm.bean.factory.AbstractMappingContextFactoryBean -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.mongo.config.MongoMappingContext -import org.springframework.util.Assert - -/** - * Factory bean for construction the Mongo DocumentMappingContext. - * - * @author Graeme Rocher - */ -class MongoMappingContextFactoryBean extends AbstractMappingContextFactoryBean { - - String defaultDatabaseName - DefaultMappingHolder defaultMapping - - @Override - protected MappingContext createMappingContext() { - Assert.hasText(defaultDatabaseName, "Property [defaultDatabaseName] must be set!") - return new MongoMappingContext(defaultDatabaseName, defaultMapping?.defaultMapping) - } -} - -@Canonical -class DefaultMappingHolder { - Closure defaultMapping -} diff --git a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/config/MongoDatastoreConfigurer.groovy b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/config/MongoDatastoreConfigurer.groovy deleted file mode 100644 index 0ccc99d5a..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/config/MongoDatastoreConfigurer.groovy +++ /dev/null @@ -1,73 +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 - */ -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-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoMethodsConfigurer.groovy b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoMethodsConfigurer.groovy deleted file mode 100644 index eedbfdad0..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoMethodsConfigurer.groovy +++ /dev/null @@ -1,114 +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.plugin.support - -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.mongo.MongoGormEnhancer -import org.grails.datastore.gorm.mongo.MongoGormInstanceApi -import org.grails.datastore.gorm.mongo.MongoGormStaticApi -import org.grails.datastore.gorm.plugin.support.DynamicMethodsConfigurer -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.mongo.MongoDatastore -import org.grails.datastore.mapping.mongo.engine.MongoEntityPersister -import org.grails.datastore.mapping.mongo.query.MongoQuery -import org.springframework.transaction.PlatformTransactionManager - -import com.mongodb.BasicDBObject -import com.mongodb.DBCursor -import com.mongodb.DBObject - -/** - * Mongo specific dynamic methods configurer. - * - * @author Graeme Rocher - * @since 1.0 - */ -class MongoMethodsConfigurer extends DynamicMethodsConfigurer{ - - MongoMethodsConfigurer(MongoDatastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - void configure() { - super.configure() - def asTypeHook = { Class cls -> - MongoEntityPersister p = datastore.currentSession.getPersister(cls) - if (p != null) { - if (delegate instanceof DBCursor) { - def mongoResults = new MongoQuery.MongoResultList(delegate,0, p) - if (!mongoResults.isEmpty()) { - return mongoResults.get(0) - } - else { - return null - } - } - else { - DBObject dbo = delegate - def key = dbo.get(MongoEntityPersister.MONGO_ID_FIELD) - return p.createObjectFromNativeEntry(p.persistentEntity, key, dbo) - } - } - else { - throw new IllegalArgumentException("Cannot convert DBOject [$delegate] to target type $cls. Type is not a persistent entity") - } - } - DBObject.metaClass.asType = asTypeHook - BasicDBObject.metaClass.asType = asTypeHook - DBCursor.metaClass.asType = asTypeHook - DBCursor.metaClass.toList = { Class cls -> - MongoEntityPersister p = datastore.currentSession.getPersister(cls) - if (p) - return new MongoQuery.MongoResultList(delegate,0,p) - else { - throw new IllegalArgumentException("Cannot convert DBCursor [$delegate] to target type $cls. Type is not a persistent entity") - } - } - } - - @Override - String getDatastoreType() { - return "Mongo" - } - - @Override - protected GormStaticApi createGormStaticApi(Class cls, List finders) { - new MongoGormStaticApi(cls, datastore, finders) - } - - @Override - protected GormInstanceApi createGormInstanceApi(Class cls) { - final api = new MongoGormInstanceApi(cls, datastore) - api.failOnError = failOnError - api - } - - @Override - protected GormEnhancer createEnhancer() { - def ge - if (transactionManager == null) { - ge = new MongoGormEnhancer(datastore) - } - else { - ge = new MongoGormEnhancer(datastore, transactionManager) - } - ge.failOnError = failOnError - ge - } -} diff --git a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoOnChangeHandler.groovy b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoOnChangeHandler.groovy deleted file mode 100644 index c9b546e66..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoOnChangeHandler.groovy +++ /dev/null @@ -1,34 +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.plugin.support - -import org.grails.datastore.gorm.plugin.support.OnChangeHandler -import org.grails.datastore.mapping.core.Datastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * On change handler for MongoDB - */ -class MongoOnChangeHandler extends OnChangeHandler{ - - MongoOnChangeHandler(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { - return "Mongo" - } -} diff --git a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoSpringConfigurer.groovy b/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoSpringConfigurer.groovy deleted file mode 100644 index 30a2e9e23..000000000 --- a/grails-datastore-gorm-mongo/src/main/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoSpringConfigurer.groovy +++ /dev/null @@ -1,101 +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.plugin.support - -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.gorm.plugin.support.SpringConfigurer -import org.springframework.beans.factory.config.MethodInvokingFactoryBean -import org.springframework.data.mongodb.core.MongoOptionsFactoryBean - -import com.mongodb.DBAddress - -/** - * Mongo specific configuration logic for Spring - * - * @author Graeme Rocher - * @since 1.0 - */ -class MongoSpringConfigurer extends SpringConfigurer { - @Override - String getDatastoreType() { - return "Mongo" - } - - @Override - Closure getSpringCustomizer() { - return { - def mongoConfig = application.config?.grails?.mongo.clone() - def databaseName = mongoConfig?.remove("databaseName") ?: application.metadata.getApplicationName() - "${databaseName}DB"(MethodInvokingFactoryBean) { bean -> - bean.scope = "request" - targetObject = ref("mongo") - targetMethod = "getDB" - arguments = [databaseName] - } - - mongoMappingContext(MongoMappingContextFactoryBean) { - defaultDatabaseName = databaseName - grailsApplication = ref('grailsApplication') - pluginManager = ref('pluginManager') - if (mongoConfig.default.mapping instanceof Closure) { - defaultMapping = new DefaultMappingHolder((Closure)mongoConfig.default.mapping) - } - } - - mongoOptions(MongoOptionsFactoryBean) { - if (mongoConfig?.options) { - for (option in mongoConfig.remove("options")) { - setProperty(option.key, option.value) - } - } - } - - mongo(GMongoFactoryBean) { - mongoOptions = mongoOptions - def mongoHost = mongoConfig?.remove("host") - - if (mongoConfig?.replicaSet) { - def set = [] - for (server in mongoConfig.remove("replicaSet")) { - set << new DBAddress(server.indexOf("/") > 0 ? server : "$server/$databaseName") - } - - replicaSetSeeds = set - } - else if (mongoConfig?.replicaPair) { - def pair = [] - for (server in mongoConfig.remove("replicaPair")) { - pair << new DBAddress(server.indexOf("/") > 0 ? server : "$server/$databaseName") - } - replicaPair = pair - } - else if (mongoHost) { - host = mongoHost - def mongoPort = mongoConfig?.remove("port") - if (mongoPort) port = mongoPort - } - } - mongoBean(mongo: "getMongo") - mongoDatastore(MongoDatastoreFactoryBean) { - mongo = ref("mongoBean") - mappingContext = mongoMappingContext - config = mongoConfig.toProperties() - } - } - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/grails/gorm/tests/DirtyCheckEmbeddedCollectionSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/grails/gorm/tests/DirtyCheckEmbeddedCollectionSpec.groovy deleted file mode 100644 index 485f2b4a3..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/grails/gorm/tests/DirtyCheckEmbeddedCollectionSpec.groovy +++ /dev/null @@ -1,90 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -import org.bson.types.ObjectId - -class DirtyCheckEmbeddedCollectionSpec extends GormDatastoreSpec { - - def "Test that changes to basic collections are detected"() { - given:"A valid bar instance" - def bar = createBar() - session.clear() - when:"A basic collection is modified" - bar = Bar.get(bar.id) - bar.strings.add("hello") - bar.save(flush:true) - session.clear() - bar = Bar.get(bar.id) - then:"The changes are reflected correctly in the persisted instance" - bar.strings.size() == 3 - - when:"A basic collection is cleared" - bar.strings.clear() - bar.save(flush:true) - session.clear() - bar = Bar.get(bar.id) - - then:"The collection is empty" - bar.strings.size() == 0 - } - - def "Test that an embedded collection can be cleared"() { - given:"valid foo and bar instances" - def foo = createFooBar() - session.clear() - - when:"foo is looked up" - foo == Foo.get(foo.id) - - then:"It has 1 bar" - foo.bars.size() == 1 - - when:"The collection is cleared" - foo.bars.clear() - foo.save(flush:true) - session.clear() - - foo == Foo.get(foo.id) - then:"The collection is empty on nexted lookup" - foo.bars.size() == 0 - } - - protected createBar() { - Bar bar = new Bar(foo: 'foo') - bar.strings.add("test") - bar.save(flush: true) - //bar is correctly saved - bar = Bar.get(bar.id) - bar.strings.add("test2") - bar.save(flush:true) - } - - protected createFooBar() { - def bar = new Bar(foo:"test") - def foo = new Foo(testProperty:"test") - foo.bars.add(bar) - foo.save(flush:true) - } - - @Override - List getDomainClasses() { - [Foo, Bar] - } -} - -@Entity -class Foo { - ObjectId id - String testProperty - Set bars = [] - static hasMany = [bars:Bar] - static embedded = ['bars'] -} - -@Entity -class Bar { - ObjectId id - String foo - List strings = [] -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy deleted file mode 100644 index 082db7656..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.tests.GormDatastoreSpec -import org.junit.Ignore - -/** - * Tests for querying the size of collections etc. - */ -class SizeQuerySpec extends GormDatastoreSpec { - - @Ignore - void "Test sizeEq criterion"() { - // TODO: implement sizeEq query operations - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/Setup.groovy deleted file mode 100644 index 9dcca8e6d..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ /dev/null @@ -1,111 +0,0 @@ - -package org.grails.datastore.gorm - -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.gorm.mongo.Birthday -import org.grails.datastore.gorm.mongo.MongoGormEnhancer -import org.grails.datastore.gorm.mongo.plugin.support.MongoMethodsConfigurer -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.engine.types.AbstractMappingAwareCustomTypeMarshaller -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.mongo.MongoDatastore -import org.grails.datastore.mapping.mongo.MongoSession -import org.grails.datastore.mapping.mongo.query.MongoQuery -import org.grails.datastore.mapping.query.Query.Between -import org.grails.datastore.mapping.query.Query.PropertyCriterion -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager -import org.springframework.context.support.GenericApplicationContext -import org.springframework.util.StringUtils -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -import com.mongodb.BasicDBObject -import com.mongodb.DBObject - -/** - * @author graemerocher - */ -class Setup { - - static MongoDatastore mongo - static MongoSession session - - static destroy() { - session.nativeInterface.dropDatabase() - session.disconnect() - mongo.destroy() - } - - static Session setup(classes) { - mongo = new MongoDatastore() - def ctx = new GenericApplicationContext() - ctx.refresh() - mongo.applicationContext = ctx - mongo.afterPropertiesSet() - - mongo.mappingContext.mappingFactory.registerCustomType(new AbstractMappingAwareCustomTypeMarshaller(Birthday) { - @Override - protected Object writeInternal(PersistentProperty property, String key, Birthday value, DBObject nativeTarget) { - final converted = value.date.time - nativeTarget.put(key, converted) - return converted - } - - @Override - protected void queryInternal(PersistentProperty property, String key, PropertyCriterion criterion, DBObject nativeQuery) { - if (criterion instanceof Between) { - def dbo = new BasicDBObject() - dbo.put(MongoQuery.MONGO_GTE_OPERATOR, criterion.getFrom().date.time) - dbo.put(MongoQuery.MONGO_LTE_OPERATOR, criterion.getTo().date.time) - nativeQuery.put(key, dbo) - } - else { - nativeQuery.put(key, criterion.value.date.time) - } - } - - @Override - protected Birthday readInternal(PersistentProperty property, String key, DBObject nativeSource) { - final num = nativeSource.get(key) - if (num instanceof Long) { - return new Birthday(new Date(num)) - } - return null - } - }) - - for (cls in classes) { - mongo.mappingContext.addPersistentEntity(cls) - } - - PersistentEntity entity = mongo.mappingContext.persistentEntities.find { PersistentEntity e -> e.name.contains("TestEntity")} - - mongo.mappingContext.addEntityValidator(entity, [ - supports: { Class c -> true }, - validate: { Object o, Errors errors -> - if (!StringUtils.hasText(o.name)) { - errors.rejectValue("name", "name.is.blank") - } - } - ] as Validator) - - def txMgr = new DatastoreTransactionManager(datastore: mongo) - MongoMethodsConfigurer methodsConfigurer = new MongoMethodsConfigurer(mongo, txMgr) - methodsConfigurer.configure() - - def enhancer = new MongoGormEnhancer(mongo, txMgr) - mongo.mappingContext.addMappingContextListener({ e -> - enhancer.enhance e - } as MappingContext.Listener) - - mongo.applicationContext.addApplicationListener new DomainEventListener(mongo) - mongo.applicationContext.addApplicationListener new AutoTimestampEventListener(mongo) - - session = mongo.connect() - - return session - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/AssignedIdentifierSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/AssignedIdentifierSpec.groovy deleted file mode 100644 index 06f6bc55e..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/AssignedIdentifierSpec.groovy +++ /dev/null @@ -1,130 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import org.springframework.dao.DataIntegrityViolationException - -import spock.lang.Issue - -/** - * Tests for usage of assigned identifiers - */ -class AssignedIdentifierSpec extends GormDatastoreSpec { - - void "Test that entities can be saved, retrieved and updated with assigned ids"() { - when:"An entity is saved with an assigned id" - def r = new River(name:"Amazon", country: "Brazil") - r.save flush:true - session.clear() - r = River.get("Amazon") - - then:"The entity can be retrieved" - r != null - r.name == "Amazon" - r.country == "Brazil" - - when:"The entity is updated" - r.country = "Argentina" - r.save flush:true - session.clear() - r = River.get("Amazon") - - then:"The update is applied" - r != null - r.name == "Amazon" - r.country == "Argentina" - - when:"The entity is deleted" - r.delete(flush:true) - - then:"It is gone" - River.count() == 0 - River.get("Amazon") == null - } - - @Issue("GPMONGODB-152") - void "Test that saving a second object with an assigned identifier produces an error"() { - when:"An entity is saved with an assigned id" - def r = new River(name:"Amazon", country: "Brazil") - r.save flush:true - session.clear() - r = River.get("Amazon") - - then:"The entity can be retrieved" - r != null - r.name == "Amazon" - r.country == "Brazil" - - when:"A second object with the same id is saved" - r = new River(name:"Amazon", country: "Brazil") - r.save flush:true - - then:"An error is produced" - River.count() == 1 - thrown DataIntegrityViolationException - - when:"A new session is created" - def totalRivers = 0 - River.withNewSession { - r = new River(name:"Nile", country: "Egype") - r.save flush:true - totalRivers = River.count() - } - - then:"It is possible to save new instances" - totalRivers == 2 - } - - @Issue("GPMONGODB-170") - void "Test that assigned identifiers work with the constructor"() { - when:"An entity is saved with an assigned id" - def l = new Lake(id: "Lake Ontario", country: "Canada") - l.save flush: true - session.clear() - l = Lake.get("Lake Ontario") - - then:"The object is correctly retrieved by assigned id" - l != null - l.id == "Lake Ontario" - l.country == "Canada" - } - - @Issue("GPMONGODB-170") - void "Test that assigned identifiers work with property setting"() { - when:"An entity is saved with an assigned id" - def l = new Lake(country: "Canada") - l.id = "Lake Ontario" - l.save flush: true - session.clear() - l = Lake.get("Lake Ontario") - - then:"The object is correctly retrieved by assigned id" - l != null - l.id == "Lake Ontario" - l.country == "Canada" - } - - @Override - List getDomainClasses() { - [River, Lake] - } -} - -@Entity -class River { - String name - String country - static mapping = { - id name:'name', generator:'assigned' - } -} - -@Entity -class Lake { - String id - String country - static mapping = { - id generator:'assigned' - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/AutowireServicesSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/AutowireServicesSpec.groovy deleted file mode 100644 index 36c67044a..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/AutowireServicesSpec.groovy +++ /dev/null @@ -1,60 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import org.springframework.context.support.GenericApplicationContext - -class AutowireServicesSpec extends GormDatastoreSpec { - - void "Test that services can be autowired"() { - given:"A service registered in the application context" - GenericApplicationContext context = session.datastore.applicationContext - context.beanFactory.registerSingleton("orderService", new OrderService()) - - when:"An instance is created and saved" - OrderService orderService = context.getBean("orderService") - def p = new Pizza(name:"Ham and Cheese", orderService: orderService) - p.save flush:true - - then:"The service is called correctly" - orderService.orders.size() == 1 - - when:"The instance is loaded" - session.clear() - p = Pizza.get(p.id) - - then:"The order service is autowired" - p.orderService != null - - when:"The entity is deleted" - p.delete flush:true - - then:"The order is correctly removed" - orderService.orders.size() == 0 - } - - @Override - List getDomainClasses() { - [Pizza] - } -} - -@Entity -class Pizza { - String id - String name - OrderService orderService - def afterInsert() { - orderService.placeOrder(this.name) - } - def afterDelete() { - orderService.removeOrder(this.name) - } -} - -class OrderService { - def orders = [] - def removeOrder(String name) { orders.remove(name)} - def placeOrder(String name) { orders << name } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BasicArraySpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BasicArraySpec.groovy deleted file mode 100644 index 51eca684e..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BasicArraySpec.groovy +++ /dev/null @@ -1,71 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import org.bson.types.ObjectId - -import com.mongodb.DBObject - -/** - * @author Graeme Rocher - */ -class BasicArraySpec extends GormDatastoreSpec{ - - void "Test that arrays are saved correctly"() { - when:"An entity with an array is saved" - Data data = new Data(str: "foo", strArray: ["foo", "bar"] as String[]).save(flush:true) - session.clear() - data = Data.findByStr("foo") - - then:"The array is saved correct" - data.str == "foo" - data.strArray[0] == "foo" - data.strArray[1] == 'bar' - } - - void "Test that arrays of convertible properties are saved correctly"() { - when:"An entity with an array is saved" - Data data = new Data(str: "bar", locArray: [Locale.US, Locale.CANADA_FRENCH] as Locale[]).save(flush:true) - session.clear() - data = Data.findByStr("bar") - - then:"The array is saved correct" - data.str == "bar" - data.locArray[0] == Locale.US - data.locArray[1] == Locale.CANADA_FRENCH - } - - void "Test that byte arrays are saved as binary"() { - when:"An entity with an array is saved" - Data data = new Data(str: "baz", byteArray: 'hello'.bytes).save(flush:true) - session.clear() - data = Data.findByStr("baz") - DBObject dbo = data.dbo - - then:"The array is saved correct" - data.str == "baz" - data.byteArray == 'hello'.bytes - dbo.byteArray == 'hello'.bytes - } - - @Override - List getDomainClasses() { - [Data] - } -} - -@Entity -class Data { - - ObjectId id - String str - String[] strArray - Locale[] locArray - byte[] byteArray - - @Override - String toString() { - "Data{id=$id, str='$str', strArray=${(strArray == null ? null : Arrays.asList(strArray))}, locArray=${(locArray == null ? null : Arrays.asList(locArray))}}" - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BasicCollectionTypeSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BasicCollectionTypeSpec.groovy deleted file mode 100644 index 860fde6a7..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BasicCollectionTypeSpec.groovy +++ /dev/null @@ -1,72 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class BasicCollectionTypeSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [MyCollections] - } - - def "Test persist basic collection types"() { - given:"An entity persisted with basic collection types" - def mc = new MyCollections(names:['Bob', 'Charlie'], pets:[chuck:"Dog", eddie:'Parrot']) - mc.save(flush:true) - - session.clear() - - when:"When the object is read" - mc = MyCollections.get(mc.id) - - then:"The basic collection types are populated correctly" - mc.names != null - mc.names == ['Bob', 'Charlie'] - mc.names.size() > 0 - mc.pets != null - mc.pets.size() == 2 - mc.pets.chuck == "Dog" - - when:"The object is updated" - mc.names << "Fred" - mc.pets.joe = "Turtle" - mc.save(flush:true) - session.clear() - mc = MyCollections.get(mc.id) - - then:"The basic collection types are correctly updated" - mc.names != null - mc.names == ['Bob', 'Charlie', 'Fred'] - mc.names.size() > 0 - mc.pets != null - mc.pets.size() == 3 - mc.pets.chuck == "Dog" - - when:"An entity is queried by a basic collection type" - session.clear() - mc = MyCollections.findByNames("Bob") - - then:"The correct result is returned" - - mc.names != null - mc.names == ['Bob', 'Charlie', 'Fred'] - mc.names.size() > 0 - mc.pets != null - mc.pets.size() == 3 - mc.pets.chuck == "Dog" - - when:"A collection of strings is queried by GString" - session.clear() - mc = MyCollections.findByNames("${'Bob'}") - then:"The correct result is returned" - mc != null - } -} - -@Entity -class MyCollections { - Long id - List names = [] - Map pets = [:] -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BasicCollectionsSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BasicCollectionsSpec.groovy deleted file mode 100644 index e79eb8bdf..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BasicCollectionsSpec.groovy +++ /dev/null @@ -1,106 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class BasicCollectionsSpec extends GormDatastoreSpec{ - @Override - List getDomainClasses() { - [Linguist, Increment] - } - - void "Test that a Locale can be used inside a collection"() { - when:"A locale collection is persisted" - def p = new Linguist(name:"Bob") - p.spokenLanguages << Locale.UK << Locale.CANADA_FRENCH << Locale.US - p.save(flush:true) - - then:"The collection is still ok" - p.spokenLanguages == [Locale.UK, Locale.CANADA_FRENCH, Locale.US] - - when:"The entity is refetched" - session.clear() - p = Linguist.get(p.id) - - then:"The embedded collection and locales can be read back correctly" - p.name == "Bob" - p.spokenLanguages == [Locale.UK, Locale.CANADA_FRENCH, Locale.US] - } - - void "Test that a map of Currency works."() { - when:"A currency map is persisted" - def p = new Linguist(name:"Bob") - p.currencies.put(Locale.UK.toString(), Currency.getInstance("GBP")) - p.currencies.put(Locale.US.toString(), Currency.getInstance("USD")) - p.save(flush:true) - - then:"The collection is still ok" - p.currencies == [ - (Locale.UK.toString()):Currency.getInstance("GBP"), - (Locale.US.toString()):Currency.getInstance("USD") - ] - - when: - session.clear() - p = Linguist.get(p.id) - - then:"The embedded collection and locales can be read back correctly" - p.name == "Bob" - p.currencies == [ - (Locale.UK.toString()):Currency.getInstance("GBP"), - (Locale.US.toString()):Currency.getInstance("USD") - ] - } - - void "Test beforeInsert() and beforeUpdate() methods for collections"() { - when:"An entity is persisted" - def p = new Increment() - p.save(flush:true) - session.clear() - p = Increment.get(p.id) - - then:"The collection is updated" - p.counter == 1 - p.history == [0] - - when:"The entity is updated" - p.counter = 10 - p.save(flush:true) - session.clear() - p = Increment.get(p.id) - - then:"The collection is updated too" - p.counter == 11 - p.history == [0, 10] - } -} - -@Entity -class Linguist { - String id - String name - List spokenLanguages = [] - Map currencies = [:] - - static constraints = { - } -} - -@Entity -class Increment { - String id - Integer counter = 0 - List history = [] - - def beforeInsert() { - inc() - } - - def beforeUpdate() { - inc() - } - - def inc() { - history << counter++ - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BeforeInsertUpdateSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BeforeInsertUpdateSpec.groovy deleted file mode 100644 index 317c04f20..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BeforeInsertUpdateSpec.groovy +++ /dev/null @@ -1,69 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import org.bson.types.ObjectId -import spock.lang.Issue - -/** - * @author Graeme Rocher - */ -class BeforeInsertUpdateSpec extends GormDatastoreSpec{ - - @Issue('GPMONGODB-251') - void "Test that before insert and update events are triggered without issue"() { - when:"A user is persisted" - def u = new BeforeInsertUser(login: "fred", password: "bar") - u.save(flush:true) - session.clear() - u = BeforeInsertUser.findByLogin("fred") - - then:"The before insert event was triggered and the password encoded" - u != null - u.password == 'foo' - - when:"A user is updated" - u.password = "bar" - u.save(flush: true) - session.clear() - u = BeforeInsertUser.findByLogin("fred") - - then:"The before update event was triggered" - u != null - u.password == 'foo' - - } - - @Override - List getDomainClasses() { - [BeforeInsertUser] - } -} - -@Entity -class BeforeInsertUser { - - ObjectId id - String login - String password - - transient isPasswordEncoded = false - - def beforeInsert() { - if (!isPasswordEncoded) { - encodePassword() - isPasswordEncoded = true - } - } - - def beforeUpdate() { - if (!isPasswordEncoded) { - encodePassword() - isPasswordEncoded = true - } - } - - protected void encodePassword() { - password = "foo" - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BrokenManyToManyAssociationSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BrokenManyToManyAssociationSpec.groovy deleted file mode 100644 index a655afb92..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/BrokenManyToManyAssociationSpec.groovy +++ /dev/null @@ -1,61 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import com.mongodb.BasicDBObject -import com.mongodb.DBCollection -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -/** - * @author Noam Y. Tenne - */ -class BrokenManyToManyAssociationSpec extends GormDatastoreSpec { - - def 'Perform a cascading delete on a broken many-to-many relationship'() { - given:'An owning entity with 2 owned entities' - ReferencingEntity referencing = new ReferencingEntity() - referencing = referencing.save(flush: true) - referencing.addToReferencedEntities(new ReferencedEntity().save()) - referencing.addToReferencedEntities(new ReferencedEntity().save()) - - referencing.save(flush: true) - session.clear() - - when:'Low-level deleting 1 owned entity to simulate a broken relationship' - ((DBCollection) ReferencedEntity.collection).remove(new BasicDBObject('_id', ReferencedEntity.find{}.id)) - session.clear() - referencing = ReferencingEntity.find{} - - then:'Expect to still find 2 owned entities, but 1 of them is null (because the reference is broken)' - referencing.referencedEntities.size() == 2 - referencing.referencedEntities.any { it == null } - - and: - when:'Deleting the owning entity, thus invoking a cascading delete' - referencing.delete(flush: true) - session.clear() - - then:'Expect all the entities to be removed with no error' - ReferencedEntity.count == 0 - ReferencingEntity.count == 0 - } - - @Override - List getDomainClasses() { - [ReferencingEntity, ReferencedEntity] - } -} - -@Entity -class ReferencingEntity { - String id - Set referencedEntities - static hasMany = [referencedEntities: ReferencedEntity] -} - -@Entity -class ReferencedEntity { - String id - static belongsTo = ReferencingEntity - Set referencingEntities - static hasMany = [referencingEntities: ReferencingEntity] -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CascadeDeleteOneToOneSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CascadeDeleteOneToOneSpec.groovy deleted file mode 100644 index b55a839cb..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CascadeDeleteOneToOneSpec.groovy +++ /dev/null @@ -1,106 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import org.bson.types.ObjectId - -/** - * @author Graeme Rocher - */ -class CascadeDeleteOneToOneSpec extends GormDatastoreSpec { - - void "Test owner deletes child in one-to-one cascade"() { - - when:"A owner with a one-to-one relation is persisted" - def u = new SystemUser(name:"user2") - u.settings = new UserSettings(user:u) - u.save(flush:true) - session.clear() - def found1 = SystemUser.findByName("user2") - def found1a = UserSettings.findByUser(found1) - - then:"The user is found" - found1 != null - found1a != null - - when:"An owner is deleted" - found1.delete(flush:true) - def found2 = SystemUser.findByName("user2") - def found1b = UserSettings.findByUser(found1) - - then:"The child association is deleted too" - assert found2 == null - assert found1b == null - } - - void "Test delete doesnt cascade if no belongsTo"() { - when:"A one-to-one with no belongsTo is persisted" - def c = new Company(name:"Apple", ceo:new Executive(name:"Tim Cook").save(), designer:new Employee(name:"Bob")) - c.save flush:true - session.clear() - c = Company.get(c.id) - - then:"The relationship can be retrieved" - c != null - c.ceo != null - c.designer != null - - when:"The the entity is deleted" - c.delete flush:true - session.clear() - - then:"The associated entity is not deleted" - Company.count() == 0 - Employee.count() == 0 - Executive.count() == 1 - } - - @Override - List getDomainClasses() { - [SystemUser, UserSettings, Company, Executive,Employee] - } -} - -@Entity -class SystemUser { - ObjectId id - - String name - UserSettings settings -} - -@Entity -class UserSettings { - ObjectId id - - boolean someSetting = true - - SystemUser user - static belongsTo = [user:SystemUser] - - static mapping = { - collection "user_settings" - } -} - -@Entity -class Company { - String id - String name - Executive ceo - Employee designer -} - -@Entity -class Executive { - String id - String name -} - -@Entity -class Employee { - String id - String name - static belongsTo = Company -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CascadeDeleteSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CascadeDeleteSpec.groovy deleted file mode 100644 index e26fd6e52..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CascadeDeleteSpec.groovy +++ /dev/null @@ -1,65 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import org.bson.types.ObjectId - -import spock.lang.Issue - -class CascadeDeleteSpec extends GormDatastoreSpec { - - @Issue(['GPMONGODB-187', 'GPMONGODB-285']) - void "Test that a delete cascade from owner to child"() { - expect:"No existing user settings" - CascadeUserSettings.findAll().isEmpty() - - when:"An owner with a child object is saved" - def u = new CascadeUser(name:"user2") - def s = new CascadeUserSettings() - u.settings = [s] as Set - - u.save(flush:true) - - and:"The owner is queried" - def found1 = CascadeUser.findByName("user2") - def found1a = CascadeUserSettings.findByUser(found1) - - then:"The data is correct" - found1 != null - found1.settings.size() == 1 - - when:"The owner is deleted" - found1.delete(flush:true) - def found2 = CascadeUser.findByName("user2") - def allUserSettings = CascadeUserSettings.findAll() - - then:"So is the child" - found2 == null - allUserSettings.isEmpty() - } - - @Override - List getDomainClasses() { - [CascadeUser, CascadeUserSettings] - } -} - -@Entity -class CascadeUser { - - ObjectId id - String name - - Set settings - static hasMany = [settings:CascadeUserSettings] -} - -@Entity -class CascadeUserSettings { - - ObjectId id - boolean someSetting = true - - static belongsTo = [user:CascadeUser] -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CircularOneToManySpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CircularOneToManySpec.groovy deleted file mode 100644 index ae5bc5569..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CircularOneToManySpec.groovy +++ /dev/null @@ -1,46 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import spock.lang.Issue - -/** - * @author Graeme Rocher - */ -class CircularOneToManySpec extends GormDatastoreSpec { - - @Issue('GPMONGODB-254') - void "Test store and retrieve circular one-to-many association"() { - given:"A circular one-to-many" - new Profile(name: "Fred") - .addToFriends(name: "Bob") - .addToFriends(name: "Frank") - .save(flush:true) - - session.clear() - - when:"The entity is loaded" - def fred = Profile.get(1L) - - then:"The association is valid" - fred.name == "Fred" - fred.friends.size() == 2 - fred.friends.any { it.name == "Bob" } - fred.friends.any { it.name == "Frank" } - - } - - @Override - List getDomainClasses() { - [Profile] - } -} - -@Entity -class Profile { - Long id - String name - List friends - - static hasMany = [friends:Profile] -} \ No newline at end of file diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/ClearCollectionSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/ClearCollectionSpec.groovy deleted file mode 100644 index 26ab3b952..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/ClearCollectionSpec.groovy +++ /dev/null @@ -1,81 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import org.bson.types.ObjectId -import grails.persistence.Entity - -/** - */ -class ClearCollectionSpec extends GormDatastoreSpec{ - - void "Test clear embedded mongo collection"() { - given:"An entity with an embedded collection" - Building b = new Building(buildingName: "WTC", rooms: [new Room(roomNo: 1),new Room(roomNo: 1)]).save(flush:true) - session.clear() - - when:"The entity is queried" - b = Building.get(b.id) - - then:"The entity was persisted correctly" - b.buildingName == "WTC" - b.rooms.size() == 2 - b.rooms[0].roomNo == "1" - - when:"The association is cleared" - b.rooms.clear() - b.save(flush: true) - session.clear() - b = Building.get(b.id) - - then:"It is empty" - b.rooms.size() == 0 - - } - - @Override - List getDomainClasses() { - [Building, Room, RoomCompany] - } -} - -@Entity -class Building { - ObjectId id - String buildingName - List rooms - - static mapWith = "mongo" - static mapping = { - collection "building" - version false - } - static constraints = { - rooms(blank:true,nullable:true) - } - static embedded = ['rooms'] -} - -@Entity -class Room { - ObjectId id - String roomNo - RoomCompany refCompany - - static mapWith = "mongo" - static constraints = { - } -} - -@Entity -class RoomCompany { - ObjectId id - String companyName - - static mapWith = "mongo" - static constraints = { - } - static mapping = { - collection "company" - version false - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CustomCollectionAndAttributeMappingSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CustomCollectionAndAttributeMappingSpec.groovy deleted file mode 100644 index f6b40e763..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CustomCollectionAndAttributeMappingSpec.groovy +++ /dev/null @@ -1,80 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -/** - * Tests for the case where a custom mapping is used. - */ -class CustomCollectionAndAttributeMappingSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [CCAAMPerson] - } - - void "Test that custom collection and attribute names are correctly used"() { - when:"An entity with custom collection and attribute naming is persisted" - def p = new CCAAMPerson(groupId:10, pets:[new CCAAMPet(name:"Joe")]).save(flush:true) - def dbo = CCAAMPerson.collection.findOne() - then:"The underlying mongo collection is correctly populated" - CCAAMPerson.collection.name == "persons" - dbo.gid == 10 - dbo.ps != null - dbo.ps.size() == 1 - dbo.ps[0].nom == "Joe" - - when:"An entity is queried" - session.clear() - p = CCAAMPerson.get(p.id) - - then:"It is returned in the correct state" - p.groupId == 10 - p.pets.size() == 1 - p.pets[0].name == "Joe" - - when:"An order by query is used" - session.clear() - new CCAAMPerson(groupId:5, pets:[new CCAAMPet(name:"Fred")]).save(flush:true) - new CCAAMPerson(groupId:15, pets:[new CCAAMPet(name:"Ed")]).save(flush:true) - def results = CCAAMPerson.list(sort:"groupId") - - then:"The results are in the correct order" - results.size() == 3 - results[0].groupId == 5 - results[1].groupId == 10 - results[2].groupId == 15 - - when:"A dynamic finder is used in a query" - session.clear() - results = CCAAMPerson.findAllByGroupId(10) - - then:"The results are correct" - results.size() == 1 - results[0].groupId == 10 - } -} - -@Entity -class CCAAMPerson { - String id - Integer groupId - List pets = [] - - static mapWith = "mongo" - - static embedded = ['pets'] - - static mapping = { - collection 'persons' - groupId attribute: 'gid' - pets attribute: 'ps' - } -} - -class CCAAMPet { - String name - static mapping = { - name attribute: "nom" - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CustomTypeMarshallingSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CustomTypeMarshallingSpec.groovy deleted file mode 100644 index d0a82df3d..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/CustomTypeMarshallingSpec.groovy +++ /dev/null @@ -1,64 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import org.bson.types.ObjectId - -class CustomTypeMarshallingSpec extends GormDatastoreSpec { - - void "Test basic crud with custom types"() { - given: "A custom type registered for the Birthday class" - final now = new Date() - def p = new Person(name:"Fred", birthday: new Birthday(now)) - p.save(flush:true) - session.clear() - - when: "We query the person" - p = Person.findByName("Fred") - - then: "The birthday is returned" - p != null - p.name == "Fred" - p.birthday != null - - when: "We query with a custom type" - p = Person.findByBirthday(new Birthday(now)) - - then: - p != null - - when: "A range query is executed" - - p = Person.findByBirthdayBetween(new Birthday(now-1), new Birthday(now+1)) - def p2 = Person.findByBirthdayBetween(new Birthday(now+1), new Birthday(now+2)) - - then: - p != null - p2 == null - } - - @Override - List getDomainClasses() { - [Person] - } -} - -@Entity -class Person { - ObjectId id - String name - Birthday birthday -} - -class Birthday implements Comparable { - Date date - - Birthday(Date date) { - this.date = date - } - - int compareTo(t) { - date.compareTo(t.date) - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DBObjectConversionSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DBObjectConversionSpec.groovy deleted file mode 100644 index aa889ce9f..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DBObjectConversionSpec.groovy +++ /dev/null @@ -1,126 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec - -class DBObjectConversionSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [Boat, Sailor, Captain] - } - - void "Test that it is possible to convert DBObjects to GORM entities"() { - given:"A domain model with embedded associations that have non-embedded associations" - createCrew() - - when:"A DBObject is read then converted to an entity" - Boat boat = Boat.collection.findOne() as Boat - - then:"The results are returned correctly" - boat != null - boat.name == "The Float" - boat.captain != null - boat.captain.name == 'Bob' - boat.crew.size() == 2 - boat.crew[0].name == 'Fred' - boat.crew[0].captain != null - boat.crew[0].captain.name == 'Bob' - boat.captain.shipmates.size() == 1 - Captain.count() == 1 - Sailor.count() == 1 - Boat.count() == 1 - } - - void "Test that it is possible to convert DBCursors to GORM entities"() { - given:"A domain model with embedded associations that have non-embedded associations" - createCrew() - - when:"A DBCursor is read then converted to an entity" - Boat boat = Boat.collection.find() as Boat - - then:"The results are returned correctly" - boat != null - boat.name == "The Float" - boat.captain != null - boat.captain.name == 'Bob' - boat.crew.size() == 2 - boat.crew[0].name == 'Fred' - boat.crew[0].captain != null - boat.crew[0].captain.name == 'Bob' - boat.captain.shipmates.size() == 1 - Captain.count() == 1 - Sailor.count() == 1 - Boat.count() == 1 - } - - void "Test that it is possible to convert DBCursors to a list of GORM entities"() { - given:"A domain model with embedded associations that have non-embedded associations" - createCrew() - - when:"A DBCursor is read then converted to an entity" - List boats = Boat.collection.find().toList(Boat) - - then:"The results are returned correctly" - boats != null - boats.size() == 1 - def boat = boats.get(0) - boat != null - boat.name == "The Float" - boat.captain != null - boat.captain.name == 'Bob' - boat.crew.size() == 2 - boat.crew[0].name == 'Fred' - boat.crew[0].captain != null - boat.crew[0].captain.name == 'Bob' - boat.captain.shipmates.size() == 1 - Captain.count() == 1 - Sailor.count() == 1 - Boat.count() == 1 - } - - void "Test that an entity can be round-tripped to dbo and back"() { - given:"A domain model with embedded associations that have non-embedded associations" - createCrew() - - when:"The model is converted to a dbo and back" - Boat boat = Boat.findAll().get(0).dbo as Boat - - then:"The copy matches the original" - boat != null - boat.name == "The Float" - boat.captain != null - boat.captain.name == 'Bob' - boat.crew.size() == 2 - boat.crew[0].name == 'Fred' - boat.crew[0].captain != null - boat.crew[0].captain.name == 'Bob' - boat.captain.shipmates.size() == 1 - - when:"The association is updated" - boat.crew.pop() - boat.save(flush: true) - boat = boat.dbo as Boat - - then:"The model is correct" - boat != null - boat.name == "The Float" - boat.captain != null - boat.captain.name == 'Bob' - boat.crew.size() == 1 - boat.crew[0].name == 'Fred' - boat.crew[0].captain != null - boat.crew[0].captain.name == 'Bob' - boat.captain.shipmates.size() == 1 - } - - private createCrew() { - final captain = new Captain(name: "Bob").save() - final firstMate = new Sailor(name: "Jim", captain: captain) - def boat = new Boat(name: "The Float", captain: captain, firstMate: firstMate) - boat.crew << new Sailor(name: "Fred", captain: captain) - boat.crew << new Sailor(name: "Joe", captain: captain) - captain.shipmates << new Sailor(name: "Jeff", captain: captain) - boat.save flush: true - session.clear() - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DbRefWithEmbeddedSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DbRefWithEmbeddedSpec.groovy deleted file mode 100644 index 110e9d383..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DbRefWithEmbeddedSpec.groovy +++ /dev/null @@ -1,59 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import com.mongodb.DBRef -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import org.bson.types.ObjectId -import spock.lang.Issue - -/** - * @author Graeme Rocher - */ -class DbRefWithEmbeddedSpec extends GormDatastoreSpec { - - @Issue('GPMONGODB-260') - void "Test that an embedded links to the correct collection when using dbrefs"() { - when:"" - def one = new One(name: 'My Foo') - one.save(flush: true) - - def two = new Two() - two.link2one = new Link2One(link: one) - two.save(flush: true) - session.clear() - final link2one = Two.collection.findOne().link2one?.link - then:"" - link2one instanceof DBRef - ((DBRef) link2one).fetch().name == "My Foo" - - } - - @Override - List getDomainClasses() { - [One,Two] - } -} -@Entity -class One { - ObjectId id - String name - static mapping = { - version false - } -} -@Entity -class Two { - ObjectId id - Link2One link2one - static embedded = ['link2one'] - static mapping = { - version false - } -} -class Link2One { - One link - static mapping = { - version false - link reference: true - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DefaultSortOrderSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DefaultSortOrderSpec.groovy deleted file mode 100644 index 67727cb37..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DefaultSortOrderSpec.groovy +++ /dev/null @@ -1,42 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Issue - -class DefaultSortOrderSpec extends GormDatastoreSpec { - - @Issue('GPMONGODB-181') - void 'Test that default sort order works correctly'() { - given:"A domain model with default sort order" - (2..10).each { - new SOBook(title:'The History of the English Speaking People volume ' + it, published:new Date(), isbn: it).save(flush:true) - } - new SOBook(title:'The History of the English Speaking People volume ' + 1, published:new Date(), isbn: 1).save(flush:true) - - when:"The model is queried" - def books = SOBook.list() - - then:"The sort order is correct" - books[0].isbn == 1 - books[1].isbn == 2 - } - - @Override - List getDomainClasses() { - [SOBook] - } -} - -@Entity -class SOBook { - Long id - String title - Date published - Integer isbn - - static mapping = { - sort isbn:'asc' - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DisableVersionSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DisableVersionSpec.groovy deleted file mode 100644 index 1b8ea6b2a..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DisableVersionSpec.groovy +++ /dev/null @@ -1,35 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec - -class DisableVersionSpec extends GormDatastoreSpec { - - void "Test that disabling the version does not persist the version field"() { - when:"An object with a disabled version is persisted" - def nv = new NoVersion(name: "Bob").save(flush:true) - session.clear() - nv = NoVersion.findByName("Bob") - - then:"The version field is not persisted" - nv.name == "Bob" - nv.version == null - nv.dbo.version == null - !nv.dbo.containsKey("version") - } - - @Override - List getDomainClasses() { - [NoVersion] - } -} - -class NoVersion { - - Long id - Long version - String name - - static mapping = { - version false - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DistinctPropertySpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DistinctPropertySpec.groovy deleted file mode 100644 index 83b33df7f..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/DistinctPropertySpec.groovy +++ /dev/null @@ -1,60 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import spock.lang.Issue -import grails.persistence.Entity -import org.bson.types.ObjectId - -/** - */ -class DistinctPropertySpec extends GormDatastoreSpec{ - - @Issue('GPMONGODB-220') - def "Test that a distinct project returns distinct results"() { - given:"Some domain classes with distinct and non-distinct properties" - createSampleData() - - when:"We query for non-distinct results using criteria" - def results = Student.createCriteria().list { - projections { - property('classcode') - } - } - - then:"The results are correct" - results.size() == 3 - results.contains("01") - results.contains("02") - - when:"We query for distinct results using criteria" - results = Student.createCriteria().list { - projections { - distinct('classcode') - } - } - - then:"The results are correct" - results.size() == 2 - results.contains("01") - results.contains("02") - } - - void createSampleData() { - [[classcode:"01",studentcode:"0101"], - [classcode:"01",studentcode:"0102"], - [classcode:"02",studentcode:"0201"]].each { - new Student(it).save(flush:true) - } - } - - @Override - List getDomainClasses() { - [Student] - } -} -@Entity -class Student { - ObjectId id - String classcode - String studentcode -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedAssociationSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedAssociationSpec.groovy deleted file mode 100644 index 0868fdb23..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedAssociationSpec.groovy +++ /dev/null @@ -1,306 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class EmbeddedAssociationSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - return [Individual, Individual2, Address, LongAddress] - } - - void "Test persistence of embedded entities"() { - given:"A domain with an embedded association" - def i = new Individual(name:"Bob", address: new Address(postCode:"30483")) - - i.save(flush:true) - session.clear() - - when:"When domain is queried" - i = Individual.findByName("Bob") - - then:"The embedded association is correctly loaded" - i != null - i.name == 'Bob' - i.address != null - i.address.postCode == '30483' - - when:"The embedded association is updated" - i.address.postCode = "28749" - i.save(flush:true) - session.clear() - i = Individual.get(i.id) - - then:"The embedded association is correctly updated" - i != null - i.name == 'Bob' - i.address != null - i.address.postCode == '28749' - - when:"An embedded association is queried" - session.clear() - i = Individual.createCriteria().get { - address { - eq 'postCode', '28749' - } - } - - then:"The correct results are returned" - i != null - i.name == 'Bob' - i.address != null - i.address.postCode == '28749' - - when:"The embedded association is set to null" - i.address = null - i.save(flush:true) - session.clear() - i = Individual.get(i.id) - - then:"The embedded association is updated correctly" - i.address == null - - } - - void "Test persistence of embedded entities with links to parent"() { - given:"A domain with an embedded association" - def i = new Individual(name:"Bob", address: new Address(postCode:"30483")) - i.address.individual = i - i.save(flush:true) - session.clear() - - when:"When domain is queried" - i = Individual.findByName("Bob") - - then:"The embedded association is correctly loaded" - i != null - i.name == 'Bob' - i.address != null - i.address.postCode == '30483' - i.address.individual == i - - when:"The embedded association is updated" - i.address = new Address(postCode: '28749') - i.save(flush:true) - session.clear() - i = Individual.get(i.id) - - then:"The embedded association is correctly updated" - i != null - i.name == 'Bob' - i.address != null - i.address.postCode == '28749' - i.address.individual == i - } - - void "Test persistence of embedded entity collections"() { - given:"An entity with an embedded entity collection" - def i = new Individual2(name:"Bob", address: new Address(postCode:"30483")) - i.otherAddresses = [new Address(postCode: "12345"), new Address(postCode: "23456")] - i.save(flush:true) - session.clear() - - when:"The entity is queried" - i = Individual2.findByName("Bob") - - then:"The object was correctly persisted" - i != null - i.name == 'Bob' - i.address != null - i.address.postCode == '30483' - i.otherAddresses != null - i.otherAddresses.size() == 2 - i.otherAddresses[0].postCode == '12345' - i.otherAddresses[1].postCode == '23456' - - when:"The embedded collection association is queried" - def i2 = new Individual2(name:"Fred", address: new Address(postCode:"345334")) - i2.otherAddresses = [new Address(postCode: "35432"), new Address(postCode: "34542")] - i2.save(flush:true) - - session.clear() - def results = Individual2.createCriteria().list { - otherAddresses { - eq 'postCode', '23456' - } - } - - then:"The correct results are returned" - results.size() == 1 - results[0].name == 'Bob' - - } - - void "Test persistence of embedded collections with links to parent"() { - given:"A domain with an embedded association" - def i = new Individual2(name:"Bob", address: new Address(postCode:"30483")) - - when:"A collection is added via addTo" - [new Address(postCode: "12345"), new Address(postCode: "23456")].each { i.addToOtherAddresses(it) } - - then:"Back-links are populated" - i.otherAddresses[0].individual2 == i - i.otherAddresses[1].individual2 == i - - when:"Entity is saved and session is cleared" - i.save(flush:true) - session.clear() - i = Individual2.findByName("Bob") - - then:"The object was correctly persisted" - i != null - i.name == 'Bob' - i.otherAddresses != null - i.otherAddresses.size() == 2 - i.otherAddresses[0].individual2 == i - i.otherAddresses[1].individual2 == i - - when:"The embedded association is updated" - i.otherAddresses = [new Address(postCode: '28749')] - i.save(flush:true) - session.clear() - i = Individual2.get(i.id) - - then:"The embedded association is correctly updated" - i != null - i.name == 'Bob' - i.otherAddresses != null - i.otherAddresses.size() == 1 - i.otherAddresses[0].individual2 == i - } - - void "Test persistence of embedded sub-class entities"() { - given:"A domain with an embedded association" - def i = new Individual(name:"Oliver", address: new LongAddress(postCode:"30483", firstLine: "1 High Street", - city: "Timbuktu")) - - i.save(flush:true) - session.clear() - - when:"When domain is queried" - i = Individual.findByName("Oliver") - - then:"The embedded association is correctly loaded" - i != null - i.name == 'Oliver' - i.address instanceof LongAddress - i.address.postCode == '30483' - i.address.firstLine == '1 High Street' - i.address.city == 'Timbuktu' - - when:"The embedded association is updated" - i.address.firstLine = "2 High Street" - i.save(flush:true) - session.clear() - i = Individual.get(i.id) - - then:"The embedded association is correctly updated" - i != null - i.name == 'Oliver' - i.address instanceof LongAddress - i.address.firstLine == '2 High Street' - - when:"An embedded association is queried" - session.clear() - i = Individual.createCriteria().get { - address { - eq 'city', 'Timbuktu' - } - } - - then:"The correct results are returned" - i != null - i.name == 'Oliver' - i.address instanceof LongAddress - i.address.city == 'Timbuktu' - } - - void "Test persistence of embedded sub-class entity collection"() { - given:"An entity with an embedded entity collection" - def i = new Individual2(name:"Ed", address: new Address(postCode:"30483")) - i.otherAddresses = [new LongAddress(postCode: "12345", city: 'Auckland', firstLine: '1 Long Road'), - new Address(postCode: "23456")] - i.save(flush:true) - session.clear() - - when:"The entity is queried" - i = Individual2.findByName("Ed") - - then:"The object was correctly persisted" - i != null - i.name == 'Ed' - i.address != null - i.address.postCode == '30483' - i.otherAddresses != null - i.otherAddresses.size() == 2 - i.otherAddresses[0] instanceof LongAddress - i.otherAddresses[0].postCode == '12345' - i.otherAddresses[0].city == 'Auckland' - !(i.otherAddresses[1] instanceof LongAddress) - i.otherAddresses[1].postCode == '23456' - - when:"The embedded collection association is queried" - def i2 = new Individual2(name:"Felix", address: new Address(postCode:"345334")) - i2.otherAddresses = [new LongAddress(postCode: "35432", city: "London", firstLine: "1 Oxford Road"), - new Address(postCode: "34542")] - i2.save(flush:true) - - session.clear() - def results = Individual2.createCriteria().list { - otherAddresses { - eq 'city', 'Auckland' - } - } - - then:"The correct results are returned" - results.size() == 1 - results[0].name == 'Ed' - } -} - -@Entity -class Individual { - Long id - String name - Address address - static embedded = ['address'] - - static mapping = { - name index:true - } -} - -@Entity -class Individual2 { - Long id - String name - Address address - List

    otherAddresses - static embedded = ['address', 'otherAddresses'] - - static mapping = { - name index:true - } -} - -@Entity -class Address { - Long id - String postCode - Individual individual - Individual2 individual2 - - static belongsTo = [Individual, Individual2] - - static constraints = { - individual nullable: true - individual2 nullable: true - } -} - -@Entity -class LongAddress extends Address { - String firstLine - String city -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedCollectionAndInheritanceSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedCollectionAndInheritanceSpec.groovy deleted file mode 100644 index b048905a6..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedCollectionAndInheritanceSpec.groovy +++ /dev/null @@ -1,99 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -/** - * Tests the use of embedded collections in inheritance hierarchies. - */ -class EmbeddedCollectionAndInheritanceSpec extends GormDatastoreSpec { - - def "Test read and write embedded collection inherited from parent"() { - when:"A embedded subclass entity is added to a collection" - def p = new ECAISPerson() - p.save() - p.pets << new ECAISDog(name:"Joe",anotherField:"foo") - p.save(flush:true) - session.clear() - - p = ECAISPerson.get(p.id) - - then:"The dog is persisted correctly" - p != null - p.pets.size() == 1 - p.pets[0] instanceof ECAISDog - p.pets[0].anotherField == 'foo' - - when:"An embedded subclass entity is updated in the collection" - p.pets << new ECAISDog(name:"Fred", anotherField: 'bar') - p.save(flush:true) - session.clear() - p = ECAISPerson.get(p.id) - - then:"The dogs are persisted correctly" - p != null - p.pets.size() == 2 - p.pets[0] instanceof ECAISDog - p.pets[0].name == "Joe" - p.pets[0].anotherField == 'foo' - p.pets[1] instanceof ECAISDog - p.pets[1].name == "Fred" - p.pets[1].anotherField == 'bar' - - when:"An update is made to an embedded collection entry but not the collection itself" - p.pets[0].name = "Changed" - p.pets[0].anotherField = "ChangedAnotherField" - p.save(flush:true) - session.clear() - p = ECAISPerson.get(p.id) - - then:"The update is correctly applied" - p != null - p.pets.size() == 2 - p.pets[0] instanceof ECAISDog - p.pets[0].name == "Changed" - p.pets[0].anotherField == "ChangedAnotherField" - p.pets[1] instanceof ECAISDog - p.pets[1].name == "Fred" - p.pets[1].anotherField == 'bar' - - when:"An embedded entity is removed from a collection" - p.pets.remove(0) - p.save(flush:true) - session.clear() - p = ECAISPerson.get(p.id) - - then:"The update is correctly applied" - p != null - p.pets.size() == 1 - p.pets[0] instanceof ECAISDog - p.pets[0].name == "Fred" - p.pets[0].anotherField == 'bar' - } - - @Override - List getDomainClasses() { - [ECAISPerson, ECAISPet, ECAISDog] - } -} - -@Entity -class ECAISPerson { - String id - Listpets = [] - static hasMany = [pets:ECAISPet] - static embedded = ['pets'] -} - -@Entity -class ECAISPet { - String id - String name -} - -@Entity -class ECAISDog extends ECAISPet { - String id - String name - String anotherField -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedCollectionWithOneToOneSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedCollectionWithOneToOneSpec.groovy deleted file mode 100644 index fec592f51..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedCollectionWithOneToOneSpec.groovy +++ /dev/null @@ -1,88 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec - -/** - * @author Graeme Rocher - */ -class EmbeddedCollectionWithOneToOneSpec extends GormDatastoreSpec { - - void "Test that embedded collections with one to one associations can be persisted correctly"() { - when:"" - def buildingInstance = new Building(buildingName:"WorldTradeCentre") - buildingInstance.save(flush:true,failOnError:true) - session.clear() - buildingInstance = Building.findByBuildingName("WorldTradeCentre") - then:"" - buildingInstance != null - buildingInstance.buildingName == "WorldTradeCentre" - - when:"" - buildingInstance.rooms = [] - buildingInstance.rooms.add(new Room(roomNo:"A001")) - buildingInstance.rooms.add(new Room(roomNo:"A002")) - buildingInstance.rooms.add(new Room(roomNo:"A003")) - buildingInstance.save(flush: true) - session.clear() - buildingInstance = Building.findByBuildingName("WorldTradeCentre") - then:"" - buildingInstance != null - buildingInstance.buildingName == "WorldTradeCentre" - buildingInstance.rooms.size() == 3 - - when:"" - def sony = new RoomCompany(companyName:"Sony") - sony.save() - buildingInstance.rooms.getAt(0).refCompany = sony - buildingInstance.save(flush: true) - session.clear() - buildingInstance = Building.findByBuildingName("WorldTradeCentre") - - then:"" - buildingInstance != null - buildingInstance.buildingName == "WorldTradeCentre" - buildingInstance.rooms.size() == 3 - buildingInstance.rooms[0].roomNo == "A001" - buildingInstance.rooms[0].refCompany != null - buildingInstance.rooms[0].refCompany.companyName == "Sony" - - when:"" - def sharp= new RoomCompany(companyName:"Sharp") - sharp.save() - buildingInstance.rooms.getAt(1).refCompany = sharp - buildingInstance.save(flush: true) - buildingInstance = Building.findByBuildingName("WorldTradeCentre") - - then:"" - buildingInstance != null - buildingInstance.buildingName == "WorldTradeCentre" - buildingInstance.rooms.size() == 3 - buildingInstance.rooms[0].roomNo == "A001" - buildingInstance.rooms[0].refCompany != null - buildingInstance.rooms[0].refCompany.companyName == "Sony" - buildingInstance.rooms[1].roomNo == "A002" - buildingInstance.rooms[1].refCompany != null - buildingInstance.rooms[1].refCompany.companyName == "Sharp" - - when:"" - buildingInstance.buildingName = "WorldTradeCentre 2nd" - buildingInstance.save(flush: true) - session.clear() - buildingInstance = Building.findByBuildingName("WorldTradeCentre 2nd") - - then:"" - buildingInstance != null - buildingInstance.buildingName == "WorldTradeCentre 2nd" - buildingInstance.rooms.size() == 3 - buildingInstance.rooms[0].roomNo == "A001" - buildingInstance.rooms[0].refCompany != null - buildingInstance.rooms[0].refCompany.companyName == "Sony" - buildingInstance.rooms[1].roomNo == "A002" - buildingInstance.rooms[1].refCompany != null - buildingInstance.rooms[1].refCompany.companyName == "Sharp" - } - @Override - List getDomainClasses() { - [Building, Room, RoomCompany] - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedHasManyWithBeforeUpdateSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedHasManyWithBeforeUpdateSpec.groovy deleted file mode 100644 index 9d27112a7..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedHasManyWithBeforeUpdateSpec.groovy +++ /dev/null @@ -1,62 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec - -import org.bson.types.ObjectId - -class EmbeddedHasManyWithBeforeUpdateSpec extends GormDatastoreSpec { - - void "Test embedded hasMany with beforeUpdate event"() { - given: - def user = User.findByName("Ratler") - if (!user) { - user = new User(name: "Ratler") - } - def address = new UserAddress(type:"home") - user.addresses = [address] - user.save(flush: true) - session.clear() - - when: - user = User.findByName("Ratler") - - then: - user != null - user.addresses.size() == 1 - user.addresses[0].type == 'home' - - when: - user.name = "Bob" - user.save(flush:true) - session.clear() - user = User.findByName("bob") - - then: - user != null - user.addresses.size() == 1 - user.addresses[0].type == 'home' - } - - @Override - List getDomainClasses() { - [User, UserAddress] - } -} - -class User { - ObjectId id - String name - List addresses - - static embedded = ['addresses'] - static hasMany = [addresses:UserAddress] - - def beforeUpdate() { - this.name = name.toLowerCase() - } -} - -class UserAddress { - ObjectId id - String type -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedListWithCustomTypeSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedListWithCustomTypeSpec.groovy deleted file mode 100644 index b0df6f162..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedListWithCustomTypeSpec.groovy +++ /dev/null @@ -1,45 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import org.bson.types.ObjectId -import grails.persistence.Entity -import spock.lang.Issue - -/** - */ -class EmbeddedListWithCustomTypeSpec extends GormDatastoreSpec{ - - @Issue('GPMONGODB-217') - void "Test that custom types in an embedded list persist correctly"() { - given:"An entity with a custom type property" - final birthdate = new Date() - def joan = new Person (name: 'joan', birthday: new Birthday(birthdate)) - - when:"The person is persisted inside an embedded collection" - def black = new Family(name: 'black', members: [joan]) - black.save(flush:true) - session.clear() - black = Family.findByName('black') - - then:"Custom type is persisted correctly" - black != null - black.members.size() == 1 - black.members[0].name == 'joan' - black.members[0].birthday != null - black.members[0].birthday.date == birthdate - } - - @Override - List getDomainClasses() { - [Person,Family] - } -} - -@Entity -class Family { - ObjectId id - String name - List members - static hasMany = [members: Person] -// static embedded = ['members'] -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedSimpleObjectSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedSimpleObjectSpec.groovy deleted file mode 100644 index a2cdee67b..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedSimpleObjectSpec.groovy +++ /dev/null @@ -1,37 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class EmbeddedSimpleObjectSpec extends GormDatastoreSpec { - - void "Test embedded non-domain object"() { - when:"An entity with a simple non-domain embedded object is persisted" - def s = new Space(displayName: "foo", db: new DatabaseConfig(name: "test")) - s.save(flush:true) - session.clear() - s = Space.get(s.id) - then:"The embedded association is persisted correctly" - s.db.name == 'test' - } - - @Override - List getDomainClasses() { - [Space] - } -} - -@Entity -class Space { - - String id - String displayName - - DatabaseConfig db - - static embedded = [ 'db' ] -} - -class DatabaseConfig { - String name -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedStringListInsideEmbeddedCollectionSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedStringListInsideEmbeddedCollectionSpec.groovy deleted file mode 100644 index d06597228..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedStringListInsideEmbeddedCollectionSpec.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class EmbeddedStringListInsideEmbeddedCollectionSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [ESLIECPerson] - } - - void "Test that an embedded primitive string can be used inside an embedded collection"() { - when:"A embedded collection is persisted which has an embedded string" - def p = new ESLIECPerson(name:"Bob") - p.cameras << new Camera(name:"Canon 50D", lenses:["Wide", "Long"]) - p.save(flush:true) - session.clear() - - p = ESLIECPerson.get(p.id) - - then:"The embedded collection and strings can be read back correctly" - p.name == "Bob" - p.cameras.size() == 1 - p.cameras[0].name == "Canon 50D" - p.cameras[0].lenses == ["Wide", "Long"] - - when:"An embedded collection is updated " - p.cameras[0].lenses << "Other" - p.save(flush:true) - p = ESLIECPerson.get(p.id) - - then:"The embedded collection is updated appropriately" - p.name == "Bob" - p.cameras.size() == 1 - p.cameras[0].name == "Canon 50D" - p.cameras[0].lenses == ["Wide", "Long", "Other"] - } -} - -@Entity -class ESLIECPerson { - - String id - String name - List cameras = [] - - static embedded = ['cameras'] -} - -class Camera { - - String name - List lenses = [] - - static embedded = ['lenses'] -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithCustomFieldMappingSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithCustomFieldMappingSpec.groovy deleted file mode 100644 index ef7e0f4dd..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithCustomFieldMappingSpec.groovy +++ /dev/null @@ -1,50 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class EmbeddedWithCustomFieldMappingSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [EWCFMPerson, EWCFMPet] - } - - void "Test that embedded collections map to the correct underlying attributes"() { - when:"An entity with custom attribute mappings is persisted" - def p = new EWCFMPerson(groupId:1) - p.pets << new EWCFMPet(name:"Fred") - p.save(flush:true) - session.clear() - - p = EWCFMPerson.get(p.id) - - then:"The data can be correctly read" - p != null - p.pets.size() == 1 - } -} - -@Entity -class EWCFMPerson { - String id - Integer groupId - List pets = [] - - static mapWith = "mongo" - - static embedded = ['pets'] - - static mapping = { - collection 'persons' - groupId field: 'gid' - pets field: 'ps' - } -} - -@Entity -class EWCFMPet { - static mapWith = "mongo" - String id - String name -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithIdSpecifiedSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithIdSpecifiedSpec.groovy deleted file mode 100644 index 500dbac7e..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithIdSpecifiedSpec.groovy +++ /dev/null @@ -1,56 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class EmbeddedWithIdSpecifiedSpec extends GormDatastoreSpec { - - void "Test that id is saved of embedded entity if specified"() { - when:"A domain model with an embedded id specified" - def sc = new SystemCustomer(name: "Bob", singleKpi:new MultiLevelKpi(id: "bar", name: "bar1", type: 'goods')) - sc.kpis << new MultiLevelKpi(id: "foo", name: "foo1", type: "stuff") - sc.save flush:true - session.clear() - sc = SystemCustomer.get(sc.id) - - then:"The id is saved too" - sc != null - sc.kpis.size() == 1 - sc.kpis[0].id == "foo" - sc.kpis[0].name == "foo1" - sc.kpis[0].type == "stuff" - sc.singleKpi != null - sc.singleKpi.id == 'bar' - sc.singleKpi.name == 'bar1' - } - - @Override - List getDomainClasses() { - [SystemCustomer, PreorderTreeNode, MultiLevelKpi] - } -} - -@Entity -class PreorderTreeNode { - String id - Integer left = 1 - Integer right = 2 -} - -@Entity -class SystemCustomer { - String id - List kpis = [] - static hasMany = [kpis:MultiLevelKpi] - static embedded = ['kpis', 'singleKpi'] - - String name - MultiLevelKpi singleKpi - String toString() { name } -} - -@Entity -class MultiLevelKpi extends PreorderTreeNode { - String name - String type -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithNonEmbeddedAssociationsSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithNonEmbeddedAssociationsSpec.groovy deleted file mode 100644 index 1ceed9b6a..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithNonEmbeddedAssociationsSpec.groovy +++ /dev/null @@ -1,83 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import com.mongodb.DBObject - -class EmbeddedWithNonEmbeddedAssociationsSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [Boat, Sailor, Captain] - } - - void "Test that embedded collections can have non-embedded associations"() { - given:"A domain model with embedded associations that have non-embedded associations" - final captain = new Captain(name: "Bob").save() - final firstMate = new Sailor(name:"Jim", captain:captain) - def boat = new Boat(name:"The Float", captain: captain, firstMate: firstMate) - boat.crew << new Sailor(name:"Fred", captain:captain) - boat.crew << new Sailor(name:"Joe", captain:captain) - captain.shipmates << new Sailor(name:"Jeff", captain: captain) - boat.save flush:true - session.clear() - - when:"The domain model is queried" - boat = Boat.get(boat.id) - Sailor jeff = Sailor.findByName("Jeff") - - then:"The right results are returned" - boat != null - boat.name == "The Float" - boat.captain != null - boat.captain.name == 'Bob' - boat.crew.size() == 2 - boat.crew[0].name == 'Fred' - boat.crew[0].captain != null - boat.crew[0].captain.name == 'Bob' - boat.captain.shipmates.size() == 1 - jeff.name == "Jeff" - Captain.count() == 1 - Sailor.count() == 1 - Boat.count() == 1 - - when:"The underlying Mongo document is queried" - def boatDbo = Boat.collection.findOne() - - then:"It is correctly defined" - boatDbo.name == "The Float" - Captain.collection.findOne(boatDbo.captain).name == "Bob" - boatDbo.firstMate instanceof DBObject - boatDbo.firstMate.name == "Jim" - boatDbo.crew.size() == 2 - boatDbo.crew[0].name == "Fred" - boatDbo.crew[1].name == "Joe" - boatDbo.crew[0].captain == boatDbo.captain - } -} - -@Entity -class Boat { - String id - String name - Captain captain - Sailor firstMate - List crew = [] - static embedded = ['firstMate', 'crew'] -} - -@Entity -class Sailor { - String id - String name - Captain captain -} - -@Entity -class Captain { - String id - String name - Set shipmates = [] - static hasMany = [shipmates:Sailor] -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithNonEmbeddedCollectionsSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithNonEmbeddedCollectionsSpec.groovy deleted file mode 100644 index d25c3ad16..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithNonEmbeddedCollectionsSpec.groovy +++ /dev/null @@ -1,94 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import com.mongodb.DBRef -import com.mongodb.DBObject -import org.bson.types.ObjectId - -/** - * - */ -class EmbeddedWithNonEmbeddedCollectionsSpec extends GormDatastoreSpec{ - @Override - List getDomainClasses() { - [Ship, Crew, Sailor, Captain] - } - - void "Test that embedded collections can have non-embedded collections"() { - given:"A domain model with embedded associations that have non-embedded collections" - final captain = new Captain(name: "Bob").save() - final firstMate = new Sailor(name:"Jim", captain:captain) - def ship = new Ship(name:"The Float") - ship.crew.firstMate = firstMate - ship.crew.sailors << new Sailor(name:"Fred", captain:captain) - ship.crew.sailors << new Sailor(name:"Joe", captain:captain) - ship.crew.reserves << new Sailor(name:"Tristan", captain:captain) - ship.crew.reserves << new Sailor(name:"Roger", captain:captain) - captain.shipmates << new Sailor(name:"Jeff", captain: captain) - captain.save flush: true - ship.save flush:true - session.clear() - - when:"The underlying Mongo document is queried" - def shipDbo = Ship.collection.findOne() - Sailor fred = Sailor.findByName("Fred") - Sailor joe = Sailor.findByName("Joe") - - then:"It is correctly defined" - shipDbo.name == "The Float" - shipDbo.crew != null - shipDbo.crew.firstMate == firstMate.id - shipDbo.crew.sailors.size() == 2 - shipDbo.crew.sailors == [fred.id, joe.id] - shipDbo.crew.reserves.size() == 2 - shipDbo.crew.reserves[0] instanceof DBRef - shipDbo.crew.reserves[0].id == Sailor.findByName('Tristan').id - shipDbo.crew.reserves[0].ref == 'sailor' - - when:"The domain model is queried" - session.clear() - ship = Ship.get(ship.id) - - then:"The right results are returned" - ship != null - ship.name == "The Float" - ship.crew != null - ship.crew.sailors.size() == 2 - ship.crew.sailors[0].name == 'Fred' - ship.crew.sailors[0].captain != null - ship.crew.sailors[0].captain.name == 'Bob' - ship.crew.reserves.size() == 2 - ship.crew.reserves[1].name == 'Roger' - ship.crew.firstMate != null - ship.crew.firstMate.name == 'Jim' - Sailor.count() == 6 - Ship.count() == 1 - } -} - -@Entity -class Ship { - String id - String name - Crew crew = new Crew() - static embedded = ['crew'] -} - -@Entity -class Crew { - String id - String name - Sailor firstMate - List sailors = [] - List reserves = [] - - static hasMany = [ - sailors:Sailor, - reserves:Sailor - ] - - static mapping = { - reserves reference: true - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithinEmbeddedAssociationSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithinEmbeddedAssociationSpec.groovy deleted file mode 100644 index 3049b9f39..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EmbeddedWithinEmbeddedAssociationSpec.groovy +++ /dev/null @@ -1,105 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class EmbeddedWithinEmbeddedAssociationSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [Customer,Vehicle,Maker,Part,Component] - } - - void "Test that nested embedded associations can be persisted"() { - given:"a domain model with lots of nesting" - def customer = new Customer(name: 'Kruttik Aggarwal').save(failOnError: true, flush: true) - def maker = new Maker(name: 'Good Year').save(failOnError: true, flush: true) - def vehicle1 = new Vehicle(type: 'car', owners: [customer], parts: [new Part(type: 'wheel', maker: maker)]).save(failOnError: true, flush: true) - def vehicle2 = new Vehicle(type: 'truck', owners: [customer], parts: [new Part(type: 'headlight', maker: maker)]).save(failOnError: true, flush: true) - customer.vehicles = [vehicle1, vehicle2] - customer.save(failOnError: true, flush: true) - def vehicle3 = new Vehicle(type: 'bus', owners: [customer], parts: [new Part(type: 'plate', maker: maker, components: [new Component(type: 'scribble')])]).save(failOnError: true, flush: true) - - session.clear() - - when:"The domain model is queries" - customer = Customer.findByName('Kruttik Aggarwal') - - then:"We get the right results back" - customer != null - customer.vehicles.size() == 2 - - when:"we get the individual cars" - def car = customer.vehicles.find { it.type == 'car'} - def truck = customer.vehicles.find { it.type == 'truck'} - - then:"make sure those are present and valid" - car != null - truck != null - car.parts.size() == 1 - car.parts.iterator().next().type == 'wheel' - car.parts.iterator().next().maker != null - truck.parts.size() == 1 - truck.parts.iterator().next().type == 'headlight' - truck.parts.iterator().next().maker != null - - when:"we check the bus" - def bus = Vehicle.findByType("bus") - - then:"the bus is valid too" - bus != null - bus.parts.size() == 1 - - when:"We get the part of the bus" - Part busPart = bus.parts.iterator().next() - - then:"Check that it is valid" - busPart.type == "plate" - busPart.maker.name == "Good Year" - busPart.components.size() == 1 - } -} - -@Entity -class Customer { - - Long id - String name - - Set vehicles - static hasMany = [vehicles: Vehicle] -} - -@Entity -class Vehicle { - Long id - String type - List parts = new ArrayList() - - Set owners - static hasMany = [owners: Customer] - static belongsTo = Customer - static embedded = ['parts'] -} - -@Entity -class Part { - Long id - String type - Maker maker - List components = new ArrayList() - static embedded = ['components'] - static belongsTo = Maker -} - -@Entity -class Maker { - Long id - String name -} - -@Entity -class Component { - Long id - String type -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EnumCollectionSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EnumCollectionSpec.groovy deleted file mode 100644 index 3b4b76a50..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/EnumCollectionSpec.groovy +++ /dev/null @@ -1,124 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class EnumCollectionSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - return [Teacher, Teacher2, DerivedTeacher] - } - - void "Test persistence of enum"() { - given: - def i = new Teacher(name:"Melvin", subject: Subject.MATH) - - when: - i.save(flush:true) - - then:"Saving it doesn't break it" - i.subject == Subject.MATH - - when: - session.clear() - i = Teacher.findByName("Melvin") - - then: - i != null - i.name == 'Melvin' - i.subject == Subject.MATH - } - - void "Test persistence of enum collections"() { - given: - def i = new Teacher2(name:"Melvin", subject: Subject.MATH) - i.otherSubjects = [Subject.HISTORY, Subject.HOME_EC] - - when:"The entity is saved and flushed" - i.save(flush:true) - - then:"The collection hasn't been broken by saving it" - i.otherSubjects == [Subject.HISTORY, Subject.HOME_EC] - - when:"The entity is queried for afresh" - session.clear() - i = Teacher2.findByName("Melvin") - - then: - i != null - i.name == 'Melvin' - i.subject == Subject.MATH - i.otherSubjects != null - i.otherSubjects.size() == 2 - i.otherSubjects[0] == Subject.HISTORY - i.otherSubjects[1] == Subject.HOME_EC - } - - void "Test persistence of parent enum collections"() { - given: - def i = new DerivedTeacher(name:"Melvin", subject: Subject.MATH, extra: 'hello') - i.otherSubjects = [Subject.HISTORY, Subject.HOME_EC] - - when:"The entity is saved and flushed" - i.save(flush:true) - - then:"The collection hasn't been broken by saving it" - i.otherSubjects == [Subject.HISTORY, Subject.HOME_EC] - - when:"The entity is queried for afresh" - session.clear() - i = DerivedTeacher.findByName("Melvin") - - then: - i != null - i.name == 'Melvin' - i.subject == Subject.MATH - i.otherSubjects != null - i.otherSubjects.size() == 2 - i.otherSubjects[0] == Subject.HISTORY - i.otherSubjects[1] == Subject.HOME_EC - i.extra == 'hello' - } -} - -@Entity -class Teacher { - Long id - String name - Subject subject - - static mapping = { - name index:true - } -} - -@Entity -class Teacher2 { - Long id - String name - Subject subject - List otherSubjects - - static mapping = { - name index:true - } -} - -@Entity -class DerivedTeacher extends Teacher2 { - String extra - - static mapping = { - name index:true - } -} - -enum Subject { - HISTORY, MATH, ENGLISH, HOME_EC - - @Override - String toString() { - "Surprise!" - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/FindOrCreateWhereSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/FindOrCreateWhereSpec.groovy deleted file mode 100644 index af3ae58e1..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/FindOrCreateWhereSpec.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person -import grails.gorm.tests.Pet - -class FindOrCreateWhereSpec extends GormDatastoreSpec { - - void "Test findOrCreateWhere with association"() { - given:"A domain class with a bidirectional one-to-many" - def person = new Person(firstName: "Fred", lastName: "Flinstone") - person.save(flush:true) - session.clear() - person = Person.load(person.id) - - when:"findByOrCreateWhere is called" - def pet = Pet.findOrCreateWhere(name:"Dino", owner:person) - - then:"The instance was created" - pet != null - } - - @Override - List getDomainClasses() { - [Person, Pet] - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GMongoSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GMongoSpec.groovy deleted file mode 100644 index 9639f0f1e..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GMongoSpec.groovy +++ /dev/null @@ -1,60 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.Person - -import org.grails.datastore.gorm.mongo.bean.factory.GMongoFactoryBean -import org.springframework.context.support.GenericApplicationContext -import org.grails.datastore.mapping.mongo.MongoDatastore -import org.grails.datastore.mapping.mongo.config.MongoMappingContext - -import spock.lang.Specification - -import com.mongodb.DB - -class GMongoSpec extends Specification { - void setup() { - ExpandoMetaClass.enableGlobally() - } - void cleanup() { - ExpandoMetaClass.disableGlobally() - } - - def "Test configure and use gmongo"() { - given: - def gfb = new GMongoFactoryBean() - gfb.afterPropertiesSet() - - when: - def gmongo = gfb.getObject() - DB db = gmongo.getDB("test") - db.dropDatabase() - - then: - gmongo != null - - when: - def ctx = new GenericApplicationContext() - ctx.refresh() - def datastore = new MongoDatastore(new MongoMappingContext("test"), gmongo.mongo, ctx) - def session = datastore.connect() - def entity = datastore.mappingContext.addPersistentEntity(Person) - new MongoGormEnhancer(datastore).enhance entity - - then: - Person.count() == 0 - - when: - def p = new Person(firstName:"Fred", lastName:"Flintstone").save(flush:true) - - then: - Person.count() == 1 - Person.withSession { - Person.collection.count() == 1 - Person.collection.findOne(firstName:"Fred").lastName == "Flintstone" - - db[Person.collectionName].count() == 1 - db[Person.collectionName].findOne(firstName:"Fred").lastName == "Flintstone" - - } - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GeospacialQuerySpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GeospacialQuerySpec.groovy deleted file mode 100644 index f96e91dc0..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GeospacialQuerySpec.groovy +++ /dev/null @@ -1,168 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class GeospacialQuerySpec extends GormDatastoreSpec { - - void "Test geolocation with BigDecimal values"() { - given:"Some entities stored with BigDecimal locations" - new Hotel(name:"Hilton", location:[50.34d, 50.12d]).save() - new Hotel(name:"Raddison", location:[150.45d, 130.67d]).save(flush:true) - session.clear() - - when:"We query by location" - def h = Hotel.findByLocation([50.34d, 50.12d]) - - then:"The location is found" - h != null - - } - void "Test that we can query within a circle"() { - given: - new Hotel(name:"Hilton", location:[50, 50]).save() - new Hotel(name:"Raddison", location:[150, 130]).save(flush:true) - session.clear() - - when: - def h = Hotel.findByLocation([50, 50]) - - then: - h != null - - when: - h = Hotel.findByLocationWithinCircle([[40, 30],40]) - - then: - h != null - h.name == "Hilton" - when: - h = Hotel.findByLocationWithinCircle([[10, 10],30]) - - then: - h == null - } - - void "Test that we can query within a box"() { - given: - new Hotel(name:"Hilton", location:[50, 50]).save() - new Hotel(name:"Raddison", location:[150, 130]).save(flush:true) - session.clear() - - when: - def h = Hotel.findByLocation([50, 50]) - - then: - h != null - - when: - h = Hotel.findByLocationWithinBox([[40, 30],[60, 70]]) - - then: - h != null - h.name == "Hilton" - when: - h = Hotel.findByLocationWithinBox([[20, 10],[40, 30]]) - - then: - h == null - } - - void "Test that we can query within a polygon with criteria"() { - given: - new Hotel(name:"Hilton", location:[50, 50]).save() - new Hotel(name:"Raddison", location:[150, 130]).save(flush:true) - session.clear() - - when: - def h = Hotel.findByLocation([50, 50]) - - then: - h != null - - when: - h = Hotel.createCriteria().get { - withinPolygon("location", [[40, 30], [40, 70], [60, 70], [60, 30]]) - } - - then: - h != null - h.name == "Hilton" - - when: - h = Hotel.createCriteria().get { - withinPolygon("location", [[20, 10], [20, 30], [40, 30], [40, 10]]) - } - - then: - h == null - } - - void "Test that we can query for nearby location"() { - given: - new Hotel(name:"Hilton", location:[50, 50]).save() - new Hotel(name:"Raddison", location:[150, 130]).save(flush:true) - session.clear() - - when: - def h = Hotel.findByLocation([50, 50]) - - then: - h != null - - when: - h = Hotel.findByLocationNear([50, 60]) - - then: - h != null - h.name == "Hilton" - when: - h = Hotel.findByLocationNear([170, 160]) - - then: - h != null - h.name == "Raddison" - } - - void "Test that we can query for nearby location with criteria"() { - given: - new Hotel(name:"Hilton", location:[50, 50]).save() - new Hotel(name:"Raddison", location:[150, 130]).save(flush:true) - session.clear() - - when: - def h = Hotel.findByLocation([50, 50]) - - then: - h != null - - when: - h = Hotel.createCriteria().get { near( "location", [50, 60] ) } - - then: - h != null - h.name == "Hilton" - when: - h = Hotel.createCriteria().get { near( "location", [170, 160] ) } - - then: - h != null - h.name == "Raddison" - } - - @Override - List getDomainClasses() { - [Hotel] - } -} - -@Entity -class Hotel { - Long id - String name - List location - - static mapping = { - location geoIndex:true - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GetAllSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GetAllSpec.groovy deleted file mode 100644 index 5079c6b23..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GetAllSpec.groovy +++ /dev/null @@ -1,61 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person -import grails.gorm.tests.Pet -import grails.gorm.tests.PetType - -/** - * @author Graeme Rocher - */ -class GetAllSpec extends GormDatastoreSpec { - - void "Test the getAll method works with no arguments"() { - given:"some sample data" - createPets() - - when:"The getAll method is used to retrieve all pets" - def results = Pet.getAll() - - then:"The correct number of results is returned" - results.size() == 3 - results.every { it instanceof Pet } - } - - void "Test the getAll method works with arguments"() { - given:"some sample data" - createPets() - - when:"The getAll method is used to retrieve all pets" - def results = Pet.getAll(1,3) - - then:"The correct number of results is returned" - results.size() == 2 - results.any { it.id == 1 } - results.any { it.id == 3 } - } - - void "Test the getAll method works with a list argument"() { - given:"some sample data" - createPets() - - when:"The getAll method is used to retrieve all pets" - def results = Pet.getAll([1,3]) - - then:"The correct number of results is returned" - results.size() == 2 - results.any { it.id == 1 } - results.any { it.id == 3 } - } - - void createPets() { - def owner = new Person(firstName: "Fred", lastName: "Flintstone").save() - assert owner != null - def saurapod = new PetType(name: "Saurapod").save() - def tyrannosaur = new PetType(name: "Tyrannosaur").save() - def plesiosaur = new PetType(name: "Plesiosaur").save() - assert new Pet(name: "Dino", owner: owner, type: saurapod, age: 5).save() - assert new Pet(name: "T-rex", owner: owner, type: tyrannosaur, age: 4).save() - assert new Pet(name: "Flipper", owner: owner, type: plesiosaur, age: 10).save(flush:true) - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GetAllWithStringIdSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GetAllWithStringIdSpec.groovy deleted file mode 100644 index a59d692bd..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GetAllWithStringIdSpec.groovy +++ /dev/null @@ -1,53 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import spock.lang.Issue - -/** - * @author Graeme Rocher - */ -class GetAllWithStringIdSpec extends GormDatastoreSpec { - - - @Issue('GPMONGODB-278') - void "Test that getAll returns the correct items"() { - - when:"domains with String ids are saved" - def id1 = new GetItem( title: "Item 1" ).save(flush:true,failOnError:true).id - def id2 = new GetItem( title: "Item 2" ).save(flush:true,failOnError:true).id - def id3 = new GetItem( title: "Item 3" ).save(flush:true,failOnError:true).id - def id4 = new GetItem( title: "Item 4" ).save(flush:true,failOnError:true).id - def id5 = new GetItem( title: "Item 5" ).save(flush:true,failOnError:true).id - def id6 = new GetItem( title: "Item 6" ).save(flush:true,failOnError:true).id - def id7 = new GetItem( title: "Item 7" ).save(flush:true,failOnError:true).id - def id8 = new GetItem( title: "Item 8" ).save(flush:true,failOnError:true).id - - then:"The ids are strings and can be queried" - id5.class == String.class - id6.class == String.class - id7.class == String.class - GetItem.get(id5).id - GetItem.get(id6).id - GetItem.get(id7).id - GetItem.findAllById(id5).id - GetItem.findAllByIdInList([id5,id6,id7]).size() == 3 - GetItem.getAll(id5).size() == 1 - GetItem.getAll(id5,id6,id7).size() == 3 - GetItem.getAll([id5,id6,id7]).size() == 3 - - } - - @Override - List getDomainClasses() { - [GetItem] - } -} -@Entity -class GetItem { - String id - String title - - static constraints = { - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GreaterThanAndLessThanCriteriaSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GreaterThanAndLessThanCriteriaSpec.groovy deleted file mode 100644 index ea6370cfe..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/GreaterThanAndLessThanCriteriaSpec.groovy +++ /dev/null @@ -1,37 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Issue - -class GreaterThanAndLessThanCriteriaSpec extends GormDatastoreSpec { - - @Issue('GPMONGODB-180') - void "Test that gt and lt criterion work together"() { - given:"some books with publication dates in the last 2 days" - new GTBook(title:'The Cross and the Switchblade', published:new Date() - 7).save(flush:true) - new GTBook(title:'The Firm', published:new Date() + 1).save(flush:true) - - when:"lt and gt are used in the same query" - def books = GTBook.createCriteria().list { - gt('published', new Date()) - lt('published', new Date() + 5) - } - - then:"The correct results are returned" - 1 == books.size() - } - - @Override - List getDomainClasses() { - [GTBook] - } -} - -@Entity -class GTBook { - Long id - String title - Date published -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/HasOneSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/HasOneSpec.groovy deleted file mode 100644 index 9f90d6a3d..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/HasOneSpec.groovy +++ /dev/null @@ -1,73 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -/** - * Tests hasOne functionality with MongoDB. - */ -class HasOneSpec extends GormDatastoreSpec { - - void "Test that a hasOne association is persisted correctly"() { - when:"A hasOne association is created and persisted" - final nose = new Nose(isLong: true) - def f = new Face(name:"Bob", nose: nose) - nose.face = f - f.save flush:true - - session.clear() - f = Face.get(f.id) - def fdbo = Face.collection.findOne() - def ndbo = Nose.collection.findOne() - - then:"The data is persisted correctly" - f.nose != null - f.nose.face != null - f.name == "Bob" - f.nose.isLong - fdbo.name == "Bob" - fdbo.nose == null - ndbo.isLong == true - ndbo.face != null - - when:"A hasOne is updated" - f.name = "Fred" - f.nose.isLong = false - f.save(flush:true) - session.clear() - f = Face.get(f.id) - then:"The data is persisted correctly" - f.nose != null - f.nose.face != null - f.name == "Fred" - !f.nose.isLong - - when:"The owner is deleted" - f.delete flush:true - - then:"The child is gone too" - Face.count() == 0 - Nose.count() == 0 - } - - @Override - List getDomainClasses() { - [Face, Nose] - } -} - -@Entity -class Face { - String id - String name - Nose nose - static hasOne = [nose:Nose] -} - -@Entity -class Nose { - String id - boolean isLong - Face face - static belongsTo = [face:Face] -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/HintQueryArgumentSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/HintQueryArgumentSpec.groovy deleted file mode 100644 index 93f7e1492..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/HintQueryArgumentSpec.groovy +++ /dev/null @@ -1,36 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import com.mongodb.MongoException -import grails.gorm.CriteriaBuilder -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person - - -class HintQueryArgumentSpec extends GormDatastoreSpec { - - void "Test that hints work on criteria queries"() { - when:"A criteria query is created with a hint" - CriteriaBuilder c = Person.createCriteria() - c.list { - eq 'firstName', 'Bob' - arguments hint:["firstName":1] - } - - then:"The query contains the hint" - c.query.@queryArguments == [hint:['firstName':1]] - - when:"A dynamic finder uses a hint" - def results = Person.findAllByFirstName("Bob", [hint:"firstName"]) - for(e in results) {} // just to trigger the query - - then:"The hint is used" - MongoException exception = thrown() - exception.message == 'bad hint' - - when:"A dynamic finder uses a hint" - results = Person.findAllByFirstName("Bob", [hint:["firstName":1]]) - - then:"The hint is used" - results.size() == 0 - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/InListQuerySpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/InListQuerySpec.groovy deleted file mode 100644 index 9d0244266..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/InListQuerySpec.groovy +++ /dev/null @@ -1,96 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person -import grails.gorm.tests.Pet -import grails.gorm.tests.PetType - -import spock.lang.Issue - -class InListQuerySpec extends GormDatastoreSpec { - - @Issue("GPMONGODB-160") - void "Test that ne works for a single-ended association"() { - given:"Some test data" - createPets() - session.clear() - - when:"Querying an association in a given list" - def saurapod = PetType.findByName('Saurapod') - - def results = Pet.withCriteria { - ne 'type', saurapod - order "name" - } - - then:"The correct results are returned" - results.size() == 2 - results[0].name == "Flipper" - results[1].name == "T-rex" - } - - @Issue('GPMONGODB-161') - void "Test that in queries work for single-ended associations"() { - given:"Some test data" - createPets() - session.clear() - - when:"Querying an association in a given list" - def list = PetType.withCriteria { - or { - eq 'name', 'Tyrannosaur' - eq 'name', 'Saurapod' - } - } - - assert list.size() == 2 - def results = Pet.withCriteria { - inList 'type', list - order "name" - } - - then:"The correct results are returned" - results.size() == 2 - results[0].name == "Dino" - results[1].name == "T-rex" - } - - void "Test that in list queries work for simple types"() { - given:"Some test data" - createPets() - session.clear() - - when:"Querying a property in a given list of strings" - def results = PetType.withCriteria { - inList 'name', ['Tyrannosaur', 'Saurapod'] - order "name" - } - - then:"The correct results are returned" - results.size() == 2 - results[0].name == "Saurapod" - results[1].name == "Tyrannosaur" - - when:"Querying an association in a given list of integers" - results = Pet.withCriteria { - inList 'age', [10, 5] - order "name" - } - - then:"The correct results are returned" - results.size() == 2 - results[0].name == "Dino" - results[1].name == "Flipper" - } - - void createPets() { - def owner = new Person(firstName: "Fred", lastName: "Flintstone").save() - assert owner != null - def saurapod = new PetType(name: "Saurapod").save() - def tyrannosaur = new PetType(name: "Tyrannosaur").save() - def plesiosaur = new PetType(name: "Plesiosaur").save() - assert new Pet(name: "Dino", owner: owner, type: saurapod, age: 5).save() - assert new Pet(name: "T-rex", owner: owner, type: tyrannosaur, age: 4).save() - assert new Pet(name: "Flipper", owner: owner, type: plesiosaur, age: 10).save(flush:true) - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/InheritanceQueryingSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/InheritanceQueryingSpec.groovy deleted file mode 100644 index 226661d45..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/InheritanceQueryingSpec.groovy +++ /dev/null @@ -1,96 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class InheritanceQueryingSpec extends GormDatastoreSpec { - - def cleanup() { - A.get("id")?.delete(flush:true) - B.get("id")?.delete(flush:true) - } - - def setup() { - B b = new B() - b.id = "id" - b.prop = "value" - b.save(failOnError:true, flush:true) - } - - def "Test collection and count sizes"() { - expect: "Both collections have 1" - B.collection.count()==0 - A.collection.count()==1 - - and: "Both counts have 1" - B.count()==1 - A.count()==1 - } - - def "Test listing"() { - when: "B has them in the list" - def bList = B.list() - - then: - bList.size()==1 - bList[0].id=="id" - - when: - def aList = A.list() - - then: - aList.size()==1 - aList[0].id=="id" - } - - def "Test getting"() { - when: - B b = B.get("id") - - then: - b?.id=="id" - b.prop=="value" - - when: - def a = A.get("id") - - then: - a?.id=="id" - a instanceof B - a.hasProperty("prop") - } - - def "Access prop through mongo"() { - when: - def jsonString = (A.collection.findOne(_id:"id")).toString() - - then: - jsonString.contains("id") - jsonString.contains("prop") - - } - - @Override - List getDomainClasses() { - [A,B] - } -} - -@Entity -class A { - static mapWith = "mongo" - - static mapping = { - id generator:'assigned', name:'id', type:'string' - } - String id -} - -@Entity -class B extends A { - static mapWith = "mongo" - - static constraints = { - } - String prop -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/InheritanceWithSingleEndedAssociationSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/InheritanceWithSingleEndedAssociationSpec.groovy deleted file mode 100644 index da5164caa..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/InheritanceWithSingleEndedAssociationSpec.groovy +++ /dev/null @@ -1,74 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import org.bson.types.ObjectId -import org.grails.datastore.mapping.proxy.EntityProxy -import spock.lang.Issue - -/** - * @author Graeme Rocher - */ -class InheritanceWithSingleEndedAssociationSpec extends GormDatastoreSpec { - - @Issue('GPMONGODB-304') - void "Test that inheritance works correctly with single ended associations"() { - given:"An association that uses a parent class type" - - def a = new NodeA(a: 'A') - def b = new NodeB(b: 'B', childNode: a) - a.save() - b.save(flush:true) - session.clear() - - when:"The association is queried with the get method" - def nodeB = NodeB.get(b.id) - - - then:"The correct type is returned for the association" - nodeB.childNode instanceof EntityProxy - nodeB.childNode.target instanceof NodeA - - when:"The association is queried with a finder" - nodeB = NodeB.findById(b.id) - then:"The correct type is returned for the association" - nodeB.childNode.target instanceof NodeA - -// nodeB = NodeB.findByB('B') -// assertTrue(nodeB.childNode instanceof NodeA) // doesn't work, childNode is a Node - - - } - - @Override - List getDomainClasses() { - [Node, NodeA, NodeB] - } -} - -@Entity -class Node { - - ObjectId id - - String name - - static constraints = { - } - - static mapping = { - version false -// collection "node" - } -} - -@Entity -class NodeA extends Node { - String a -} - -@Entity -class NodeB extends Node { - String b - Node childNode -} \ No newline at end of file diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/IsNullSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/IsNullSpec.groovy deleted file mode 100644 index 1765d9f99..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/IsNullSpec.groovy +++ /dev/null @@ -1,78 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Issue - -class IsNullSpec extends GormDatastoreSpec { - - @Issue('GPMONGODB-164') - void "Test isNull works in a criteria query"() { - given:"Some test data" - new Elephant(name: "Dumbo").save() - new Elephant(name: "Big Daddy", trunk:new Trunk(length: 10).save()).save(flush:true) - session.clear() - - when:"A entity is queried with isNull" - def results = Elephant.withCriteria { - isNull 'trunk' - } - - then:"The correct results are returned" - results.size() == 1 - results[0].name == "Dumbo" - - when:"A entity is queried with isNotNull" - results = Elephant.withCriteria { - isNotNull 'trunk' - } - - then:"The correct results are returned" - results.size() == 1 - results[0].name == "Big Daddy" - } - - @Issue('GPMONGODB-164') - void "Test isNull works in a dynamic finder"() { - given:"Some test data" - new Elephant(name: "Dumbo").save() - new Elephant(name: "Big Daddy", trunk:new Trunk(length: 10).save()).save(flush:true) - session.clear() - - when:"A entity is queried with isNull" - def results = Elephant.findAllByTrunkIsNull() - - then:"The correct results are returned" - results.size() == 1 - results[0].name == "Dumbo" - - when:"A entity is queried with isNotNull" - results = Elephant.findAllByTrunkIsNotNull() - - then:"The correct results are returned" - results.size() == 1 - results[0].name == "Big Daddy" - } - - @Override - List getDomainClasses() { - [Elephant, Trunk] - } -} - -@Entity -class Elephant { - Long id - String name - Trunk trunk - static mapping = { - trunk nullable:true - } -} - -@Entity -class Trunk { - Long id - int length -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/LikeQuerySpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/LikeQuerySpec.groovy deleted file mode 100644 index 9e0113cde..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/LikeQuerySpec.groovy +++ /dev/null @@ -1,42 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import spock.lang.Issue -import grails.gorm.tests.Pet -import grails.gorm.tests.Person -import grails.gorm.tests.PetType - -class LikeQuerySpec extends GormDatastoreSpec { - - void "Test for like query"() { - given: - new Pet(name: "foo").save(flush:true, failOnError:true) - new Pet(name: "bar").save(flush:true, failOnError:true) - new Pet(name: "baz").save(flush:true, failOnError:true) - new Pet(name: "foobar").save(flush:true, failOnError:true) - new Pet(name: "*").save(flush:true, failOnError:true) - new Pet(name: "**").save(flush:true, failOnError:true) - new Pet(name: "***").save(flush:true, failOnError:true) - session.clear() - - when: - def results = Pet.findAllByNameLike(search) - - then: - results*.name == expected - - where: - search | expected - 'f' | [] - 'foo' | ['foo'] - 'f%' | ['foo', 'foobar'] - 'f%o' | ['foo'] - '%foo' | ['foo'] - 'foo%' | ['foo', 'foobar'] - '%foo%' | ['foo', 'foobar'] - 'f.*' | [] - '*' | ['*'] - '**' | ['**'] - '.*' | [] - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/ListOneToManyOrderingSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/ListOneToManyOrderingSpec.groovy deleted file mode 100644 index 44605b4a3..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/ListOneToManyOrderingSpec.groovy +++ /dev/null @@ -1,75 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Issue - -class ListOneToManyOrderingSpec extends GormDatastoreSpec { - - @Issue('GPMONGODB-162') - void "Test that one-to-many associations of type list retain ordering"() { - given:"A domain model that features a list association" - def j = new Judge(name: "Bob") - j.jury = [ - new Juror(name: "Fred"), - new Juror(name: "Joe"), - new Juror(name: "Bill") - ] - j.save flush:true - session.clear() - when:"The domain model is queried" - j = Judge.findByName("Bob") - then:"The list ordering is retained" - j != null - j.name == "Bob" - j.jury.size() == 3 - j.jury[0].name == "Fred" - j.jury[1].name == "Joe" - j.jury[2].name == "Bill" - } - - @Issue('GPMONGODB-162') - void "Test that one-to-many associations of type list retain ordering from existing entities"() { - given:"A domain model that features a list association" - def j = new Judge(name: "Bob") - def joe = new Juror(name: "Joe").save() - def bill = new Juror(name: "Bill").save() - def fred = new Juror(name: "Fred").save(flush: true) - j.jury = [ - fred, - joe, - bill - ] - j.save flush:true - session.clear() - when:"The domain model is queried" - j = Judge.findByName("Bob") - then:"The list ordering is retained" - j != null - j.name == "Bob" - j.jury.size() == 3 - j.jury[0].name == "Fred" - j.jury[1].name == "Joe" - j.jury[2].name == "Bill" - } - - @Override - List getDomainClasses() { - [Judge, Juror] - } -} - -@Entity -class Judge { - Long id - String name - List jury = [] - static hasMany = [jury:Juror] -} - -@Entity -class Juror { - Long id - String name -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoDynamicPropertyOnEmbeddedSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoDynamicPropertyOnEmbeddedSpec.groovy deleted file mode 100644 index 486ed669d..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoDynamicPropertyOnEmbeddedSpec.groovy +++ /dev/null @@ -1,74 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import org.bson.types.ObjectId -import spock.lang.Issue - -/** - * @author Graeme Rocher - */ -class MongoDynamicPropertyOnEmbeddedSpec extends GormDatastoreSpec{ - - @Issue('GPMONGODB-290') - void "Test that accessing dynamic attributes on embedded objects use the embedded collection"() { - when:"An embedded collection is created" - Container.collection.insert(name:'big box of items', - contents:(0..9).collect { [name:"Item $it"]}) - def collectionNames = Container.collection.DB.getCollectionNames().sort() - - then:"The embedded collection is valid" - Container.count() == 1 - Container.first().contents.size() == 10 - Container.first().contents.first().name ==~ /Item \d/ - collectionNames.any { it =~ /^container\b/ } - !collectionNames.any { it =~ /^item\b/ } - session.clear() - - when:"An embedded dynamic property is accessed" - Container.first().contents.first().nonexistentProperty == null - then:"A collection is not created for the embedded property" - Container.collection.DB.getCollectionNames().sort() == collectionNames - !collectionNames.any { it =~ /^item\b/ } - } - - @Override - List getDomainClasses() { - [Container] - } -} - -@Entity -class Container { - static mapWith='mongo' - static embedded = ['contents'] - static mapping = { - version false - cache false - } - static constraints = { - contents nullable:true - } - - - ObjectId id - String name - - Set contents = new HashSet() -} -@Entity -class Item { - static mapWith='mongo' - static mapping = { - version false - } - static constraints = { - - } - static belongsTo = Container - - ObjectId id - String name - - -} \ No newline at end of file diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoEntityConfigSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoEntityConfigSpec.groovy deleted file mode 100644 index 2f262a0ea..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoEntityConfigSpec.groovy +++ /dev/null @@ -1,72 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec - -import org.grails.datastore.mapping.document.config.DocumentPersistentEntity -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.mongo.MongoSession -import org.grails.datastore.mapping.mongo.config.MongoAttribute -import org.grails.datastore.mapping.mongo.config.MongoCollection - -import com.mongodb.DB -import com.mongodb.WriteConcern -import org.springframework.data.mongodb.core.MongoTemplate - -class MongoEntityConfigSpec extends GormDatastoreSpec{ - -// @Ignore - def "Test custom collection config"() { - given: - session.mappingContext.addPersistentEntity MyMongoEntity - DB db = session.nativeInterface - - db.dropDatabase() - // db.resetIndexCache() // this method is missing from more recent driver versions - - when: - PersistentEntity entity = session.mappingContext.getPersistentEntity(MyMongoEntity.name) - - then: - entity instanceof DocumentPersistentEntity - - when: - MongoCollection coll = entity.mapping.mappedForm - MongoAttribute attr = entity.getPropertyByName("name").getMapping().getMappedForm() - MongoAttribute location = entity.getPropertyByName("location").getMapping().getMappedForm() - then: - coll != null - coll.collection == 'mycollection' - coll.database == "test2" - coll.writeConcern == WriteConcern.FSYNC_SAFE - attr != null - attr.index == true - attr.targetName == 'myattribute' - attr.indexAttributes == [unique:true] - location != null - location.index == true - location.indexAttributes == [type:"2d"] - - when: - MongoSession ms = session - MongoTemplate mt = ms.getMongoTemplate(entity) - then: - ms.getCollectionName(entity) == "mycollection" - } -} - -class MyMongoEntity { - String id - - String name - String location - - static mapping = { - collection "mycollection" - database "test2" - shard "name" - writeConcern WriteConcern.FSYNC_SAFE - name index:true, attr:"myattribute", indexAttributes: [unique:true] - - location geoIndex:true - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoGormEnhancerSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoGormEnhancerSpec.groovy deleted file mode 100644 index 96d74e72d..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoGormEnhancerSpec.groovy +++ /dev/null @@ -1,31 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec - -import com.mongodb.DBCollection - -class MongoGormEnhancerSpec extends GormDatastoreSpec{ - - def "Test getCollectionName static method" () { - given: - session.mappingContext.addPersistentEntity MyMongoEntity - - when: - def collectionName = MyMongoEntity.collectionName - - then: - collectionName == "mycollection" - - } - - def "Test getCollection static method" () { - given: - session.mappingContext.addPersistentEntity MyMongoEntity - - when: - DBCollection collection = MyMongoEntity.collection - - then: - collection.name == 'mycollection' - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoResultsListIndexSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoResultsListIndexSpec.groovy deleted file mode 100644 index 32465c8ff..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoResultsListIndexSpec.groovy +++ /dev/null @@ -1,44 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person - -/** - * @author Graeme Rocher - */ -class MongoResultsListIndexSpec extends GormDatastoreSpec{ - - void "Test that indexing into results works with MongoDB"() { - given:"Some people" - createPeople() - - when:"We index into the results" - def people = Person.list() - def bart = people[2] - def homer = people[0] - def barney = people[4] - - then:"The results are correct" - bart.firstName == "Bart" - homer.firstName == "Homer" - barney.firstName == "Barney" - people[10] == null - people.size() == 6 - - when:"An index out of range is used" - people.get(10) - - then:"An exception is thrown" - thrown ArrayIndexOutOfBoundsException - } - - - protected void createPeople() { - new Person(firstName: "Homer", lastName: "Simpson").save() - new Person(firstName: "Marge", lastName: "Simpson").save() - new Person(firstName: "Bart", lastName: "Simpson").save() - new Person(firstName: "Lisa", lastName: "Simpson").save() - new Person(firstName: "Barney", lastName: "Rubble").save() - new Person(firstName: "Fred", lastName: "Flinstone").save() - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoSuite.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoSuite.groovy deleted file mode 100644 index a80449865..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoSuite.groovy +++ /dev/null @@ -1,22 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.CrudOperationsSpec -import grails.gorm.tests.ProxyLoadingSpec -import org.junit.runner.RunWith -import org.junit.runners.Suite -import org.junit.runners.Suite.SuiteClasses -import grails.gorm.tests.PagedResultSpec -import grails.gorm.tests.EnumSpec -import grails.gorm.tests.OrderBySpec -import grails.gorm.tests.OneToManySpec - -/** - * @author graemerocher - */ -@RunWith(Suite) -@SuiteClasses([ - ProxyLoadingSpec - -]) -class MongoSuite { -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoTypesSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoTypesSpec.groovy deleted file mode 100644 index 3033531ff..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/MongoTypesSpec.groovy +++ /dev/null @@ -1,45 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import org.bson.types.Binary -import org.bson.types.ObjectId - -import com.mongodb.BasicDBObject -import com.mongodb.DBObject - -class MongoTypesSpec extends GormDatastoreSpec { - - void "Test that an entity can save and load native mongo types"() { - when:"A domain class with mongodb types is saved and read" - def mt = new MongoTypes() - mt.bson = new BasicDBObject(foo:new BasicDBObject([embedded:"bar"])) - mt.binary = new Binary("foo".bytes) - def otherId = new ObjectId() - mt.otherId = otherId - mt.save flush:true - session.clear() - mt = MongoTypes.get(mt.id) - then:"Then it is in the correct state" - mt != null - mt.bson != null - mt.bson.foo instanceof DBObject - mt.bson.foo.embedded == 'bar' - mt.binary.data == 'foo'.bytes - mt.otherId == otherId - } - - @Override - List getDomainClasses() { - [MongoTypes] - } -} - -@Entity -class MongoTypes { - ObjectId id - DBObject bson - Binary binary - ObjectId otherId -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/NegateInListSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/NegateInListSpec.groovy deleted file mode 100644 index 6883ab27e..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/NegateInListSpec.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person - -class NegateInListSpec extends GormDatastoreSpec { - - void "Test negate in list query"() { - given:"two people" - def p1 = new Person(firstName:"Homer", lastName: "Simpson").save() - new Person(firstName:"Bart", lastName: "Simpson").save(flush:true) - - when:"We query for people who don't have the given id" - def results = Person.withCriteria { - not { - inList('id', [p1.id]) - } - } - - then:"The results are correct" - results.size() == 1 - results[0].firstName == "Bart" - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/NullifyPropertySpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/NullifyPropertySpec.groovy deleted file mode 100644 index 677a15e85..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/NullifyPropertySpec.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person -import grails.gorm.tests.Pet - -/** - * Tests the nullification of properties - */ -class NullifyPropertySpec extends GormDatastoreSpec { - - void "Test nullify basic property"() { - given:"A an entity with a basic property" - - def pet = new Pet(name:"Spike") - pet.save flush:true - session.clear() - pet = Pet.get(pet.id) - - when:"A property is nulled" - pet.name = null - pet.save flush:true - session.clear() - pet = Pet.get(pet.id) - - then:"It is null when retrieved" - pet != null - pet.name == null - } - - void "Test nullify to-one association"() { - given:"A an entity with a to-one association" - - def bob = new Person(firstName:"Bob", lastName:"Builder") - bob.save() - def pet = new Pet(name:"Spike", owner:bob) - pet.save flush:true - session.clear() - pet = Pet.get(pet.id) - assert pet.owner != null - - when:"A property is nulled" - pet.owner = null - pet.save flush:true - session.clear() - pet = Pet.get(pet.id) - - then:"It is null when retrieved" - pet != null - pet.owner == null - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/NullsAreNotStoredSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/NullsAreNotStoredSpec.groovy deleted file mode 100644 index 2a724572b..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/NullsAreNotStoredSpec.groovy +++ /dev/null @@ -1,55 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import com.mongodb.Mongo -import com.mongodb.DB -import com.mongodb.DBObject -import org.bson.types.ObjectId -import grails.persistence.Entity - -/** - * - */ -class NullsAreNotStoredSpec extends GormDatastoreSpec { - @Override - List getDomainClasses() { - [NANSPerson] - } - void "Test that null values are not stored on domain creation"() { - given:"A domain model with fields that are null" - NANSPerson person = new NANSPerson() - person.save(flush:true) - session.clear() - - when:"The instance is read from the database" - DBObject personObj = NANSPerson.collection.findOne(person.id) - - then:"The null-valued fields are not stored" - personObj != null - !personObj.containsField("name") - } - - void "Test that null values are not stored on domain update"() { - given:"A domain model with fields that are null" - NANSPerson person = new NANSPerson(name: "John Smith") - person.save(flush:true) - session.clear() - - when:"The instance is updated and read from the database" - person = NANSPerson.get(person.id) - person.name = null - person.save(flush: true) - session.clear() - DBObject personObj = NANSPerson.collection.findOne(person.id) - - then:"The null-valued fields are not stored" - personObj != null - !personObj.containsField("name") - } -} - -@Entity -class NANSPerson { - ObjectId id - String name -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/ObjectIdPersistenceSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/ObjectIdPersistenceSpec.groovy deleted file mode 100644 index b432f2c44..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/ObjectIdPersistenceSpec.groovy +++ /dev/null @@ -1,28 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec - -import org.bson.types.ObjectId - -class ObjectIdPersistenceSpec extends GormDatastoreSpec { - - def "Test that we can persist an object that has a BSON ObjectId"() { - given: - session.mappingContext.addPersistentEntity MongoObjectIdEntity - - when: - def t = new MongoObjectIdEntity(name:"Bob").save(flush:true) - session.clear() - t = MongoObjectIdEntity.get(t.id) - - then: - t != null - t.id != null - } -} - -class MongoObjectIdEntity { - ObjectId id - - String name -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/OneToManyWithInheritanceSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/OneToManyWithInheritanceSpec.groovy deleted file mode 100644 index 1b58212fe..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/OneToManyWithInheritanceSpec.groovy +++ /dev/null @@ -1,51 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class OneToManyWithInheritanceSpec extends GormDatastoreSpec { - - void "Test that a one-to-many with inheritances behaves correctly"() { - given:"A one-to-many association inherited from a parent" - Animal animal = new Animal().save() - Donkey donkey = new Donkey(name: "Eeyore").save() - new Carrot(leaves: 1, animal: animal).save() - new Carrot(leaves: 2, animal: animal).save() - new Carrot(leaves: 3, animal: donkey).save() - new Carrot(leaves: 4, animal: donkey).save(flush:true) - session.clear() - - when:"The association is loaded" - animal = Animal.get(animal.id) - donkey = Donkey.get(donkey.id) - - then:"The association is correctly loaded" - animal.carrots.size() == 2 - donkey.carrots.size() == 2 - } - - @Override - List getDomainClasses() { - [Animal,Donkey, Carrot] - } -} - -@Entity -class Donkey extends Animal { - String name -} - -@Entity -class Animal { - String id - Set carrots = [] - static hasMany = [carrots:Carrot] -} - -@Entity -class Carrot { - Long id - Integer leaves - Animal animal - static belongsTo = [animal:Animal] -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/OneToOneIntegritySpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/OneToOneIntegritySpec.groovy deleted file mode 100644 index b4a62880c..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/OneToOneIntegritySpec.groovy +++ /dev/null @@ -1,72 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.Face -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Nose -import grails.gorm.tests.Person -import grails.gorm.tests.Pet - -class OneToOneIntegritySpec 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.owner != null - pet.owner.firstName == "Fred" - - when:"The low level API is accessed" - def petDbo = Pet.collection.findOne(name:"Dino") - def ownerRef =petDbo.owner - - then:"check the state is valid" - petDbo != null - ownerRef == person.id - } - - 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) - - then:"The domain model is valid" - - face != null - 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" - - when:"The low level API is accessed" - def noseDbo = Nose.collection.findOne(hasFreckles:true) - def faceRef = noseDbo.face - then:"check the state is valid" - noseDbo != null - noseDbo.hasFreckles == true - faceRef == face.id - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/OneToOneNoReferenceSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/OneToOneNoReferenceSpec.groovy deleted file mode 100644 index 1047650b9..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/OneToOneNoReferenceSpec.groovy +++ /dev/null @@ -1,58 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import org.bson.types.ObjectId - -class OneToOneNoReferenceSpec extends GormDatastoreSpec{ - - void "Test that associations can be saved with no dbrefs"() { - when:"A domain class is saved that has references disabled" - def other = new OtherNoRef().save() - def noref = new NoRef(other: other) - noref.save flush:true - - then:"The association is saved without a dbref" - println NoRef.collection.findOne() - NoRef.collection.findOne().other == other.id - } - - void "Test that querying an association works"() { - when:"A domain class is saved that has references disabled" - def other = new OtherNoRef().save() - def noref = new NoRef(other: other) - noref.save flush:true - session.clear() - - other = OtherNoRef.get(other.id) - noref = NoRef.findByOther(other) - - then:"The association can be queried" - other != null - noref != null - } - - @Override - List getDomainClasses() { - [OtherNoRef,NoRef] - } -} - -@Entity -class NoRef { - - ObjectId id - - OtherNoRef other - - static mapping = { - other reference:false - } -} - -@Entity -class OtherNoRef { - - ObjectId id -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/OptimisticLockingWithExceptionSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/OptimisticLockingWithExceptionSpec.groovy deleted file mode 100644 index 3c46fca31..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/OptimisticLockingWithExceptionSpec.groovy +++ /dev/null @@ -1,51 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import org.grails.datastore.mapping.core.OptimisticLockingException -import spock.lang.Issue - -import javax.persistence.FlushModeType - -/** - * @author Graeme Rocher - */ -class OptimisticLockingWithExceptionSpec extends GormDatastoreSpec{ - - @Issue('GPMONGODB-256') - void "Test that when an optimistic locking exception is thrown the flush mode is set to commit"() { - when:"An optimistic locking session is thrown" - Counter c = new Counter(counter: 0).save(flush:true) - session.clear() - c = Counter.get(c.id) - Thread.start { - Counter.withNewSession { - Counter c1 = Counter.get(c.id) - c1.counter++ - c1.save(flush:true) - } - }.join() - c.counter = 2 - c.save(flush: true) - - then:"An optimistic locking exception was thrown" - thrown(OptimisticLockingException) - session.flushMode == FlushModeType.COMMIT - - - } - - @Override - List getDomainClasses() { - [Counter] - } -} - -@Entity -class Counter { - Long id - Long version - Date lastUpdated - Date dateCreated - int counter -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/QueriesWithIdenticallyNamedPartsSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/QueriesWithIdenticallyNamedPartsSpec.groovy deleted file mode 100644 index eb96c7746..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/QueriesWithIdenticallyNamedPartsSpec.groovy +++ /dev/null @@ -1,130 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import org.bson.types.ObjectId -import spock.lang.Issue - -/** - * Test cases for GPMONGODB-296 (and GPMONGODB-302). - */ -@Issue('GPMONGODB-296') -class QueriesWithIdenticallyNamedPartsSpec extends GormDatastoreSpec { - @Override - List getDomainClasses() { - return [Foo] - } - - void "Ors and ands work together"() { - given: - def foos = [ - new Foo(1, 1, 1, 1).save(), - new Foo(1, 2, 1, 2).save(), - new Foo(2, 1, 2, 1).save(), - new Foo(2, 2, 2, 2).save(), - ] - session.flush() - - when: "ors combined in implicit conjuction" - def results = Foo.createCriteria().list { - or { - eq 'a', 1 - eq 'b', 1 - } - or { - eq 'c', 2 - eq 'd', 2 - } - } - - then: - results.size() == 2 - results.contains(foos[1]) - results.contains(foos[2]) - - when: "ors combined in explicit conjunction" - results = Foo.createCriteria().list { - and { - or { - eq 'a', 1 - eq 'b', 1 - } - or { - eq 'c', 2 - eq 'd', 2 - } - } - } - - then: - results.size() == 2 - results.contains(foos[1]) - results.contains(foos[2]) - } - - void "Multiple queries on same property work"() { - given: - def foos = [ - new Foo(1, 2, 3, 4).save(), - new Foo(2, 2, 3, 4).save(), - new Foo(3, 2, 4, 3).save(), - new Foo(4, 2, 4, 3).save(), - ] - session.flush() - def results - - when: "Multiple inList queries are combined" - results = Foo.createCriteria().list { - inList 'a', [1, 2, 3] - inList 'a', [2, 4] - } - - then: - results.size() == 1 - results.contains(foos[1]) - - when: "Eq and in queries are combined" - results = Foo.createCriteria().list { - eq 'a', 2 - inList 'a', [2, 4] - } - - then: - results.size() == 1 - results.contains(foos[1]) - - when: "Multiple property queries are combined" - results = Foo.createCriteria().list { - geProperty 'a', 'd' - ltProperty 'a', 'c' - } - - then: - results.size() == 1 - results.contains(foos[2]) - } -} - -@Entity -class Foo { - ObjectId id - - Foo(Integer a = null, Integer b = null, Integer c = null, Integer d = null) { - this.a = a - this.b = b - this.c = c - this.d = d - } - - Integer a - Integer b - Integer c - Integer d - - static constraints = { - a() - b nullable: true - c nullable: true - d nullable: true - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/ReadManyObjectsSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/ReadManyObjectsSpec.groovy deleted file mode 100644 index 710f46366..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/ReadManyObjectsSpec.groovy +++ /dev/null @@ -1,74 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import org.bson.types.ObjectId - -/** - * @author Graeme Rocher - */ -class ReadManyObjectsSpec extends GormDatastoreSpec { - - void "Test that reading thousands of objects doesn't run out of memory"() { - given:"A lot of test data" - createData() - - when:"The data is read" - long took = 30000 - final now = System.currentTimeMillis() - for(p in ProfileDoc.list()) { - println p.n1 - } - final then = System.currentTimeMillis() - took = then-now - println "Took ${then-now}ms" - - then:"Check that it doesn't take too long" - took < 30000 - - } - - void "Test that reading thousands of objects doesn't run out of memory native query"() { - given:"A lot of test data" - createData() - - when:"The data is read" - final now = System.currentTimeMillis() - final cursor = ProfileDoc.collection.find() - for(p in cursor) { - println p.n1 - } - final then = System.currentTimeMillis() - long took = then-now - println "Took ${then-now}ms" - - then:"If it gets to this point we " - took < 30000 - - } - - void createData() { - ProfileDoc.collection.drop() - 100000.times { - ProfileDoc.collection.insert(n1:"Plane $it".toString(),n2:it,n3:it, date: new Date()) - } - } - - @Override - List getDomainClasses() { - [ProfileDoc] - } -} - -@Entity -class ProfileDoc { - ObjectId id - String n1 - Integer n2 - Long n3 - Date date - - static mapping = { - stateless true - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/SchemalessSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/SchemalessSpec.groovy deleted file mode 100644 index c4ff74dbd..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/SchemalessSpec.groovy +++ /dev/null @@ -1,81 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Plant - -class SchemalessSpec extends GormDatastoreSpec{ - - def "Test attach additional data"() { - given: - def p = new Plant(name:"Pineapple") - p.dbo.color = "Yellow" - p.save(flush:true) - session.clear() - - when: - p = Plant.get(p.id) - - then: - p.name == 'Pineapple' - p.dbo.color == 'Yellow' - p['color'] == 'Yellow' - - when: - p['hasLeaves'] = true - p.save(flush:true) - session.clear() - p = Plant.get(p.id) - - then: - p.name == 'Pineapple' - p.dbo.color == 'Yellow' - p['color'] == 'Yellow' - p['hasLeaves'] == true - - when:"All objects are listed" - session.clear() - def results = Plant.list() - - then:"The right data is returned and the schemaless properties accessible" - results.size() == 1 - results[0].name == 'Pineapple' - results[0]['color'] == 'Yellow' - - when:"A groovy finderAll method is executed" - def newResults = results.findAll { it['color'] == 'Yellow' } - - then:"The embedded data is stil there" - newResults.size() == 1 - newResults[0].name == 'Pineapple' - newResults[0]['color'] == 'Yellow' - - when:"A dynamic finder is used on a schemaless property" - session.clear() - def plant = Plant.findByColor("Yellow") - - then:"The dynamic finder works" - plant.name == "Pineapple" - - when:"A criteria query is used on a schemaless property" - session.clear() - plant = Plant.createCriteria().get { - eq 'color', 'Yellow' - } - - then:"The criteria query works" - plant.name == "Pineapple" - - when:"A dynamic property is accessed via a getter" - def color = plant.color - - then:"The getter works" - color == 'Yellow' - - when:"A dynamic property is set via a setter" - plant.color = "Red" - - then:"The setter works" - plant.color == 'Red' - - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/SessionCachingSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/SessionCachingSpec.groovy deleted file mode 100644 index 67b2a98b4..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/SessionCachingSpec.groovy +++ /dev/null @@ -1,73 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person - -/** - * Tests related to caching of entities. - */ -class SessionCachingSpec extends GormDatastoreSpec { - void "test cache used for get"() { - given: - def a = new Person(firstName:"Bob", lastName:"Builder").save() - session.flush() - - when: - def aa = Person.get(a.id) - - then: - a.attached - aa != null - aa.is(a) - } - - void "test cache used for getAll"() { - given: - def a = new Person(firstName:"Bob", lastName:"Builder").save() - def b = new Person(firstName:"Another", lastName:"Builder").save() - session.flush() - session.clear() - - when: - a = Person.get(a.id) - def list = Person.getAll(b.id, a.id) - - then: - a != null - list.size() == 2 - list.every { it != null } - list.every { it.attached } - list[0].id == b.id - list[1].is(a) - } - - void "test unique queried elements are from cache"() { - given: - def p = new Person(firstName:"Bob", lastName:"Builder").save() - session.flush() - - when: - def pp = Person.findByFirstName("Bob") - - then: - p.attached - pp != null - pp.attached - p.is(pp) - } - - void "test multi-queried elements are in cache"() { - given: - def p = new Person(firstName:"Bob", lastName:"Builder").save() - session.flush() - - when: - def test = Person.findAllByFirstName("Bob") - - then: - test.size() == 1 - session.contains(test[0]) - test[0].attached - p.is(test[0]) - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/SwitchDatabaseAtRuntimeSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/SwitchDatabaseAtRuntimeSpec.groovy deleted file mode 100644 index a11f60fd6..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/SwitchDatabaseAtRuntimeSpec.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person -import org.grails.datastore.mapping.mongo.MongoDatastore -import org.grails.datastore.mapping.mongo.MongoSession - -/** - * @author Graeme Rocher - */ -class SwitchDatabaseAtRuntimeSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [Person] - } - - void setup() { - final mongo = ((MongoDatastore) session.getDatastore()).getMongo() - mongo.getDB('thesimpsons').dropDatabase() - } - - - void "Test switch database at runtime"() { - given:"Some test data" - createPeople() - - when:"A count is issued" - int total = Person.count() - - then:"The result is correct" - total == 6 - - when:"We switch to another database" - def previous = Person.useDatabase("thesimpsons") - - then:"The count is now 0" - Person.count() == 0 - Person.DB.name == 'thesimpsons' - - when:"We save a new person" - new Person(firstName: "Maggie", lastName: "Simpson").save(flush:true) - - then:"The count is now 1" - Person.count() == 1 - Person.DB.name == 'thesimpsons' - - - when:"we switch back all is good" - Person.useDatabase(previous) - - then:"the people count is 6 again" - Person.count() == 6 - Person.DB.name == 'test' - } - - - protected void createPeople() { - new Person(firstName: "Homer", lastName: "Simpson").save() - new Person(firstName: "Marge", lastName: "Simpson").save() - new Person(firstName: "Bart", lastName: "Simpson").save() - new Person(firstName: "Lisa", lastName: "Simpson").save() - new Person(firstName: "Barney", lastName: "Rubble").save() - new Person(firstName: "Fred", lastName: "Flinstone").save() - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/TransientPropertySpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/TransientPropertySpec.groovy deleted file mode 100644 index 7b92d7b53..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/TransientPropertySpec.groovy +++ /dev/null @@ -1,35 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec - -class TransientPropertySpec extends GormDatastoreSpec { - - void "Test that transient properties are not saved to mongodb"() { - when:"A doman with a transient property is saved" - def c = new Cow(name: "Daisy", other:"foo").save(flush:true) - def service = c.rodeoService - session.clear() - c = Cow.findByName("Daisy") - - then:"The transient instance is not persisted" - c != null - c.name == "Daisy" - c.other == null - c.rodeoService != null - c.rodeoService != service - } - - @Override - List getDomainClasses() { - [Cow] - } -} - -class RodeoService {} - -class Cow { - Long id - String name - transient String other - transient rodeoService = new RodeoService() -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/UnitTestObjectIdFieldSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/UnitTestObjectIdFieldSpec.groovy deleted file mode 100644 index 44dbe02b6..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/UnitTestObjectIdFieldSpec.groovy +++ /dev/null @@ -1,51 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.datastore.test.DatastoreUnitTestMixin -import grails.persistence.Entity -import org.bson.types.ObjectId -import spock.lang.Issue -import spock.lang.Specification - -/** - * @author Graeme Rocher - */ -@Mixin(DatastoreUnitTestMixin) -class UnitTestObjectIdFieldSpec extends Specification { - - void setup() { - ExpandoMetaClass.enableGlobally() - connect() - } - - void cleanup() { - ExpandoMetaClass.disableGlobally() - disconnect() - } - - @Issue('GPMONGODB-172') - void "Test storing and retrieving an entity with an ObjectId field in unit tests"() { - when:"A entity is mocked and a query by id executed" - mockDomain(Test) - - final oid = ObjectId.get() - new Test(someOtherId: oid).save(flush:true) - session.clear() - def t = Test.findBySomeOtherId(oid) - - then:"No error is thrown and the correct entity is returned" - t != null - t.someOtherId == oid - - } -} - -@Entity -class Test { - - ObjectId id - Long version - ObjectId someOtherId - - static constraints = { - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/WriteConcernSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/WriteConcernSpec.groovy deleted file mode 100644 index 154a4fce1..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/WriteConcernSpec.groovy +++ /dev/null @@ -1,35 +0,0 @@ -package org.grails.datastore.gorm.mongo - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import com.mongodb.WriteConcern - -/** - * Tests usage of WriteConcern - */ -class WriteConcernSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [SafeWrite] - } - - void "Test that the correct WriteConcern is used to save entities"() { - when:"An object is saved" - def sw = new SafeWrite(name:"Bob") - sw.save(flush:true) - - then:"The correct write concern is used" - sw != null - } -} - -@Entity -class SafeWrite { - String id - String name - static mapping = { - writeConcern WriteConcern.FSYNC_SAFE - } -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/bugs/GPMongoDB295Spec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/bugs/GPMongoDB295Spec.groovy deleted file mode 100644 index 9c3568ef9..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/bugs/GPMongoDB295Spec.groovy +++ /dev/null @@ -1,100 +0,0 @@ -package org.grails.datastore.gorm.mongo.bugs - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import spock.lang.Issue -import spock.lang.Specification - -/** - * @author Graeme Rocher - */ -class GPMongoDB295Spec extends GormDatastoreSpec { - - - @Issue('GPMONGODB-295') - void "Test that 'com.mongodb.DBRef cannot be cast to java.io.Serializable' exception is not thrown"() { - given:"Some test data" - UserGroup group = new UserGroup(name: 'group', company: 'JFrog').save(flush: true, failOnError: true) - User user = new User(lastName: 'lastName', name: 'user', group: group).save(flush: true, failOnError: true) - UserObject obj = new UserObject(objName: 'obj').save(flush: true, failOnError: true) - group.addToUsers(user) - user.addToObjects(obj) - user.save(flush: true, failOnError: true) - group.save(failOnError: true, flush: true) - - expect:"The exception is not thrown" - getAllSavedDataWithANewSession() - } - - private getAllSavedDataWithANewSession() { - UserGroup.withNewSession { - UserGroup userGroup = UserGroup.findByName('group') - assert userGroup - assert userGroup.users.size() - User user = User.findByName('user') - user.objects.size() - assert user.objects.size() == 1 - return user - } - } - - @Override - List getDomainClasses() { - [InheritUser, ObjParent, UserGroup, User, UserObject] - } -} - -@Entity -class InheritUser { - String id - String name - static constraints = { - name unique: true, nullable: false - } - -} -@Entity -class ObjParent { - String id - String dateCreated - String lastUpdated - -} - -@Entity -class UserGroup extends InheritUser { - Set users - static hasMany = [users: User] - static mappedBy = [users: 'group'] - - static constraints = { - company nullable: false - } - - String id - String company -} -@Entity -class User extends InheritUser { - Set objects - static hasMany = [objects: UserObject] - UserGroup group - static belongsTo = [group: UserGroup] - static constraints = { - group nullable: false - lastName nullable: false - } - String id - String lastName -} - -@Entity -class UserObject extends ObjParent { - static constraints = { - objName nullable: false, unique: true - } - String objName - String id - String dateCreated - String lastUpdated -} diff --git a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoSpringConfigurerSpec.groovy b/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoSpringConfigurerSpec.groovy deleted file mode 100644 index 56ca2b31c..000000000 --- a/grails-datastore-gorm-mongo/src/test/groovy/org/grails/datastore/gorm/mongo/plugin/support/MongoSpringConfigurerSpec.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package org.grails.datastore.gorm.mongo.plugin.support - -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 - -/** - */ -class MongoSpringConfigurerSpec extends Specification{ - - void "Test configure Mongo via Spring"() { - when:"The spring configurer is used" - def configurer = new MongoSpringConfigurer() - def config = configurer.getConfiguration() - def bb = new BeanBuilder() - final binding = new Binding() - def application = new DefaultGrailsApplication([Person] as Class[], Thread.currentThread().contextClassLoader) - - application.config.grails.mongo.databaseName = "test" - final closureConfig = { - '*'(reference: true) - } - application.config.grails.mongo.default.mapping = closureConfig - application.initialise() - application.registerArtefactHandler(new DomainClassArtefactHandler()) - binding.setVariable("application", application) - binding.setVariable("manager", new DefaultGrailsPluginManager([] as Class[], application)) - bb.setBinding(binding) - bb.beans { - grailsApplication(DefaultGrailsApplication, [Person] as Class[], Thread.currentThread().contextClassLoader) { bean -> - bean.initMethod = "initialise" - } - pluginManager(DefaultGrailsPluginManager, [] as Class[], ref("grailsApplication")) - } - bb.beans config - def ctx = bb.createApplicationContext() - MongoMappingContext mappingContext = ctx.getBean("mongoMappingContext",MongoMappingContext) - def entity = mappingContext?.getPersistentEntity(Person.name) - - then:"The application context is created" - ctx != null - ctx.containsBean("persistenceInterceptor") - mappingContext.defaultMapping == closureConfig - entity != null - entity.getPropertyByName('pets').getMapping().mappedForm.reference == true - - } -} diff --git a/grails-datastore-gorm-neo4j/build.gradle b/grails-datastore-gorm-neo4j/build.gradle deleted file mode 100644 index b4f1fe2f0..000000000 --- a/grails-datastore-gorm-neo4j/build.gradle +++ /dev/null @@ -1,61 +0,0 @@ -version = "1.0.1.SNAPSHOT" -//version = "1.0.1" - -ext.neo4jVersion = "1.8.2" -ext.gdmVersion = "1.1.7.RELEASE" - -repositories { - //mavenLocal() - //mavenCentral() - - // some artifacts used are not available on mavenCentral - maven { url "http://m2.neo4j.org/content/repositories/releases/" } -// maven { url "http://m2.neo4j.org/content/repositories/snapshots/" } -// maven { url "http://repo.grails.org/grails/core" } -} - -dependencies { - compile "org.neo4j:neo4j-community:$neo4jVersion" - - // during development (aka snapshot version), use project dependencies - // during release, use 'regular' dependencies - if (version =~ /SNAPSHOT/) { - compile project(":grails-datastore-gorm"), - project(":grails-datastore-web"), - project(":grails-datastore-gorm-plugin-support") - testCompile project(":grails-datastore-gorm-test"), - project(":grails-datastore-gorm-tck") - } else { - compile "org.grails:grails-datastore-gorm:$gdmVersion", - "org.grails:grails-datastore-web:$gdmVersion", - "org.grails:grails-datastore-gorm-plugin-support:$gdmVersion" - testCompile "org.grails:grails-datastore-gorm-test:$gdmVersion", - "org.grails:grails-datastore-gorm-tck:$gdmVersion" - } - - testCompile 'org.codehaus.gpars:gpars:0.12', - [group: "org.neo4j", name: "neo4j-kernel", version: neo4jVersion, classifier: 'tests'], - [group: "org.neo4j.app", name: "neo4j-server", version: neo4jVersion, classifier: 'tests'], - [group: "org.neo4j.app", name: "neo4j-server", version: neo4jVersion], - [group: "org.neo4j", name: "neo4j-rest-graphdb", version: '1.8'], - [group: "org.neo4j", name: "neo4j-rest-graphdb", version: '1.8', classifier: 'tests'], - "org.neo4j:neo4j-graphviz:$neo4jVersion" - testRuntime "javax.servlet:servlet-api:2.5", - "org.grails:grails-web:$grailsVersion", - 'com.sun.jersey:jersey-server:1.9', - 'com.sun.jersey:jersey-core:1.9', - 'com.sun.jersey:jersey-client:1.9' - testRuntime("org.grails:grails-plugin-domain-class:$grailsVersion") { - exclude group: 'org.grails', module:'grails-plugin-testing' - exclude group: 'org.grails', module:'grails-datastore-core' - exclude group: 'org.grails', module:'grails-datastore-gorm' - exclude group: 'org.grails', module:'grails-datastore-simple' - } -} - -/* -test { - jvmArgs '-Xmx1024m', '-Xdebug', '-Xnoagent', '-Dgrails.full.stacktrace=true', '-Djava.compiler=NONE', - '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005' -} -*/ diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/DummyEntityPersister.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/DummyEntityPersister.groovy deleted file mode 100644 index dc478465f..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/DummyEntityPersister.groovy +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (C) 2010 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.neo4j - -import org.grails.datastore.mapping.engine.EntityPersister -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.query.Query -import org.grails.datastore.mapping.model.MappingContext - -/** - * dummy implementation of {@link org.grails.datastore.mapping.engine.EntityPersister} - * The Neo4j gorm implementation does all persistence stuff in {@link Neo4jSession}, so there's no - * need for a {@link org.grails.datastore.mapping.engine.EntityPersister}, except on issue: - * {@link org.grails.datastore.gorm.proxy.GroovyProxyFactory} references - * {@link org.grails.datastore.mapping.engine.EntityPersister#setObjectIdentifier} so {@link Neo4jSession#proxy} needs - * to pass a valid EntityPersister - that's the purpose of this class. - * - * @author Stefan Armbruster - */ -class DummyEntityPersister extends EntityPersister { - - public DummyEntityPersister(MappingContext mappingContext, PersistentEntity entity) { - super(mappingContext, entity, null, null) - } - - @Override - protected List retrieveAllEntities(PersistentEntity pe, Serializable[] keys) { - throw new UnsupportedOperationException() - } - - @Override - protected List retrieveAllEntities(PersistentEntity pe, Iterable keys) { - throw new UnsupportedOperationException() - } - - @Override - protected List persistEntities(PersistentEntity pe, Iterable objs) { - throw new UnsupportedOperationException() - } - - @Override - protected Object retrieveEntity(PersistentEntity pe, Serializable key) { - throw new UnsupportedOperationException() - } - - @Override - protected Serializable persistEntity(PersistentEntity pe, Object obj) { - throw new UnsupportedOperationException() - } - - @Override - protected void deleteEntity(PersistentEntity pe, Object obj) { - throw new UnsupportedOperationException() - } - - @Override - protected void deleteEntities(PersistentEntity pe, Iterable objects) { - throw new UnsupportedOperationException() - } - - @Override - Query createQuery() { - throw new UnsupportedOperationException() - } - - @Override - Serializable refresh(Object o) { - throw new UnsupportedOperationException() - } - -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/GrailsRelationshipTypes.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/GrailsRelationshipTypes.groovy deleted file mode 100644 index 6a4da080a..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/GrailsRelationshipTypes.groovy +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (C) 2010 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.neo4j - -import org.neo4j.graphdb.RelationshipType - -/** - * @author Stefan Armbruster - */ -enum GrailsRelationshipTypes implements RelationshipType { - SUBREFERENCE, - INSTANCE, - SUBSUBREFERENCE -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/GraphGormMappingFactory.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/GraphGormMappingFactory.groovy deleted file mode 100644 index b3e2e37cb..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/GraphGormMappingFactory.groovy +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (C) 2010 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.neo4j - -import org.grails.datastore.mapping.config.AbstractGormMappingFactory -import org.grails.datastore.mapping.config.Property -import org.grails.datastore.mapping.keyvalue.mapping.config.Family -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValue -import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher -import java.beans.PropertyDescriptor -import org.grails.datastore.mapping.annotation.Index -import org.springframework.core.annotation.AnnotationUtils -import java.lang.reflect.Field -import org.springframework.util.ReflectionUtils - -/** - * @author Stefan Armbruster - */ -class GraphGormMappingFactory extends AbstractGormMappingFactory { - - @Override - protected Class getPropertyMappedFormType() { - Property - } - - @Override - protected Class getEntityMappedFormType() { - Family - } - -/* - // copied from AnnotationKeyValueMappingFactory - @Override - public Property createMappedForm(PersistentProperty mpp) { - - final Class javaClass = mpp.getOwner().getJavaClass(); - final ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(javaClass); - - final PropertyDescriptor pd = cpf.getPropertyDescriptor(mpp.getName()); - final Property property = super.createMappedForm(mpp); - Index index = AnnotationUtils.getAnnotation(pd.getReadMethod(), Index.class); - - if (index == null) { - final Field field = ReflectionUtils.findField(javaClass, mpp.getName()); - if (field != null) { - ReflectionUtils.makeAccessible(field); - index = field.getAnnotation(Index.class); - } - } - if (index != null) { - property.setIndex(true); - } - - return property; - } -*/ - -} - - 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 deleted file mode 100644 index d7ecf6992..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/GraphPersistentEntity.groovy +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2010 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.neo4j - -import org.grails.datastore.mapping.config.Entity -import org.grails.datastore.mapping.model.AbstractClassMapping -import org.grails.datastore.mapping.model.AbstractPersistentEntity -import org.grails.datastore.mapping.model.ClassMapping -import org.grails.datastore.mapping.model.MappingContext - -/** - * @author Stefan Armbruster - */ -@SuppressWarnings("unchecked") -class GraphPersistentEntity extends AbstractPersistentEntity { - - Entity mappedForm - - GraphPersistentEntity(Class javaClass, MappingContext context) { - super(javaClass, context) - this.mappedForm = context.getMappingFactory().createMappedForm(this); - } - - @Override - ClassMapping getMapping() { - return new AbstractClassMapping(this, context) { - @Override - public Entity getMappedForm() { - return GraphPersistentEntity.this.mappedForm; - } - }; - } -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jDatastore.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jDatastore.groovy deleted file mode 100644 index 29608c995..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jDatastore.groovy +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (C) 2010 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.neo4j - -import org.grails.datastore.mapping.core.AbstractDatastore -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.mapping.model.types.Simple -import org.neo4j.cypher.javacompat.ExecutionEngine -import org.neo4j.graphdb.* -import org.neo4j.graphdb.index.AutoIndexer -import org.neo4j.graphdb.index.IndexManager -import org.neo4j.kernel.EmbeddedGraphDatabase -import org.springframework.beans.factory.InitializingBean -import org.springframework.context.ConfigurableApplicationContext -import org.springframework.util.Assert -/** - * Datastore implementation for Neo4j backend - * @author Stefan Armbruster - * TODO: refactor constructors to be groovier - */ -class Neo4jDatastore extends AbstractDatastore implements InitializingBean { - - public static final NUMBER_OF_SUBSUBREFERENCE_NODES = 2 ** 7 - - GraphDatabaseService graphDatabaseService - @Lazy ExecutionEngine executionEngine = new ExecutionEngine(graphDatabaseService) - Map subReferenceNodes - Map> subSubReferenceNodes - String storeDir - @Lazy IndexManager indexManager = graphDatabaseService.index() - Map> domainSubclasses = [:].withDefault { [] } - - /** - * only to be called during testing - * @return - */ - Neo4jDatastore() { - this(new Neo4jMappingContext(), null, null) - } - - Neo4jDatastore(Neo4jMappingContext mappingContext, ConfigurableApplicationContext ctx, GraphDatabaseService graphDatabaseService) { - super(mappingContext, Collections.emptyMap(), ctx) - this.graphDatabaseService = graphDatabaseService - -/* mappingContext.getConverterRegistry().addConverter(new Converter() { - ObjectId convert(String source) { - return new ObjectId(source) - } - }) - - mappingContext.getConverterRegistry().addConverter(new Converter() { - String convert(ObjectId source) { - return source.toString() - } - })*/ - - } - - Neo4jDatastore(Neo4jMappingContext mappingContext, GraphDatabaseService graphDatabaseService) { - this(mappingContext, null, graphDatabaseService) - } - - @Override - protected Session createSession(Map connectionDetails) { - new Neo4jSession( - datastore: this, - mappingContext: mappingContext, - applicationEventPublisher: applicationEventPublisher - ) - } - - void afterPropertiesSet() { - if (!graphDatabaseService) { - Assert.notNull storeDir - graphDatabaseService = new EmbeddedGraphDatabase(storeDir) - } - initializeConverters(mappingContext) - findOrCreateSubReferenceNodes() - setupIndexing() - } - - protected void setupIndexing() { - AutoIndexer nodeAutoIndex = indexManager.nodeAutoIndexer - nodeAutoIndex.enabled = true - nodeAutoIndex.startAutoIndexingProperty(Neo4jSession.TYPE_PROPERTY_NAME) - for (PersistentEntity pe in mappingContext.persistentEntities) { - - for (PersistentEntity parent in collectSuperclassChain(pe)) { - domainSubclasses[parent] << pe - } - - for (PersistentProperty pp in pe.persistentProperties) { - if ((pp instanceof Simple) && (pp.mapping.mappedForm.index)) { - nodeAutoIndex.startAutoIndexingProperty(pp.name) - } - } - } - } - - protected List collectSuperclassChain(PersistentEntity pe, def list=[]) { - if (pe) { - list << pe - return collectSuperclassChain(pe.parentEntity, list) - } - list - } - - protected void findOrCreateSubReferenceNodes() { - Transaction tx = graphDatabaseService.beginTx() - try { - subReferenceNodes = [:] - Node referenceNode = graphDatabaseService.referenceNode - - for (Relationship rel in referenceNode.getRelationships(GrailsRelationshipTypes.SUBREFERENCE, Direction.OUTGOING).iterator()) { - Node endNode = rel.endNode - String clazzName = endNode.getProperty(Neo4jSession.SUBREFERENCE_PROPERTY_NAME) - subReferenceNodes[clazzName] = endNode - } - - for (PersistentEntity pe in mappingContext.persistentEntities) { - if (!subReferenceNodes.containsKey(pe.name)) { - subReferenceNodes[pe.name] = createSubReferenceNode(pe.name) - } - } - tx.success() - } finally { - tx.finish() - } - } - - protected Node createSubReferenceNode(name) { - Node subReferenceNode = graphDatabaseService.createNode() - subReferenceNode.setProperty(Neo4jSession.SUBREFERENCE_PROPERTY_NAME, name) - graphDatabaseService.referenceNode.createRelationshipTo(subReferenceNode, GrailsRelationshipTypes.SUBREFERENCE) - return subReferenceNode - } - -} \ No newline at end of file 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 deleted file mode 100644 index c0f1f6bc4..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jGormEnhancer.groovy +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright (C) 2010 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.neo4j - -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.neo4j.graphdb.Direction -import org.neo4j.graphdb.Node -import org.neo4j.graphdb.ReturnableEvaluator -import org.neo4j.graphdb.StopEvaluator -import org.neo4j.graphdb.Traverser -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.core.SessionCallback -import org.springframework.transaction.PlatformTransactionManager -import org.springframework.util.ClassUtils - -/** - * @author Stefan Armbruster - */ -class Neo4jGormEnhancer extends GormEnhancer { - - Neo4jGormEnhancer(Datastore datastore, PlatformTransactionManager transactionManager = null) { - super(datastore, transactionManager) - } - - protected GormStaticApi getStaticApi(Class cls) { - return new Neo4jGormStaticApi(cls, datastore, finders) - } - - protected GormInstanceApi getInstanceApi(Class cls) { - final api = new Neo4jGormInstanceApi(cls, datastore) - api.failOnError = failOnError - return api - } -} - -class Neo4jGormInstanceApi extends GormInstanceApi { - - Neo4jGormInstanceApi(Class persistentClass, Datastore datastore) { - super(persistentClass, datastore) - } - - def traverse(instance, Traverser.Order order, StopEvaluator stopEvaluator, ReturnableEvaluator returnableEvaluator, Object... args ) { - - execute new SessionCallback() { - def doInSession(Session session) { - - Node referenceNode = ((Neo4jDatastore)datastore).graphDatabaseService.getNodeById(instance.id) - - // run neo4j traverser - Traverser traverser = args ? referenceNode.traverse(order, stopEvaluator, returnableEvaluator, args) : - referenceNode.traverse(order, stopEvaluator, returnableEvaluator, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH) - - // iterate result, unmarshall nodes to domain class instances if possible - traverser.collect { Node node -> - String className = node.getProperty("__type__", null) - if (className) { - session.retrieve(ClassUtils.forName(className), node.id) - } else { - node - } - } - } - } - } - - Node getSubreferenceNode(instance) { - ((Neo4jDatastore)datastore).subReferenceNodes[instance.getClass().name] - } - - Node getNode(instance) { - ((Neo4jDatastore)datastore).graphDatabaseService.getNodeById(instance.id) - } - - def traverse(instance, StopEvaluator stopEvaluator, ReturnableEvaluator returnableEvaluator, Object... args) { - traverse(instance, Traverser.Order.BREADTH_FIRST, stopEvaluator, returnableEvaluator, args) - } - - def traverse(instance, Closure stopEvaluator, Closure returnableEvaluator, Object... args) { - traverse(instance, Traverser.Order.BREADTH_FIRST, stopEvaluator, returnableEvaluator, args) - } - - def traverse(instance, Traverser.Order order, Closure stopEvaluator, Closure returnableEvaluator, Object... args) { - traverse(instance, order, stopEvaluator as StopEvaluator, returnableEvaluator as ReturnableEvaluator, args) - } - - /** - * Allows accessing to dynamic properties with the dot operator - * - * @param instance The instance - * @param name The property name - * @return The property value - */ - def propertyMissing(D instance, String name) { - getAt(instance, name) - } - - /** - * Allows setting a dynamic property via the dot operator - * @param instance The instance - * @param name The property name - * @param val The value - */ - def propertyMissing(D instance, String name, val) { - putAt(instance, name, val) - } - - /** - * Allows subscript access to schemaless attributes. - * - * @param instance The instance - * @param name The name of the field - */ - void putAt(D instance, String name, value) { - if (instance.hasProperty(name)) { - instance.setProperty(name, value) - } - else { - execute new SessionCallback() { - @Override - Object doInSession(Session session) { - if (!session.contains(instance)) { - throw new IllegalStateException("cannot store a non declared property on a transient instance") - } - session.persist(instance) - Node node = instance.node - if (value instanceof Collection) { - - Class c = String[] - if (!value.empty) { - def first = value.iterator().next() - def baseClass = first.getClass() - switch (first) { - case BigDecimal: // BigDeciaml is not allowed in neo4j -> storing doubles instead - baseClass = Double.class - break - } - c = ClassUtils.forName("[L${baseClass.name};") - } - value = value.asType(c) - } - if (value==null) { - node.removeProperty(name) - } else { - node.setProperty(name, value) - } - } - } - } - } - - /** - * Allows subscript access to schemaless attributes. - * - * @param instance The instance - * @param name The name of the field - * @return the value - */ - def getAt(D instance, String name) { - if (instance.hasProperty(name)) { - return instance.getProperty(name) - } - else { - execute new SessionCallback() { - @Override - Object doInSession(Session session) { - session.persist(instance) - Node node = instance.node - node.getProperty(name, null) - } - } - } - } - - /** - * perform a cypher query - * @param queryString - * @param params - * @return - */ - def cypher(instance, String queryString, Map params = [:]) { - params['this'] = instance.id - datastore.executionEngine.execute(queryString, params) - } - -} - -class Neo4jGormStaticApi extends GormStaticApi { - - Neo4jGormStaticApi(Class persistentClass, Datastore datastore, List finders) { - super(persistentClass, datastore, finders) - } - - def traverseStatic(Traverser.Order order, StopEvaluator stopEvaluator, ReturnableEvaluator returnableEvaluator, Object... args ) { - - execute new SessionCallback() { - def doInSession(Session session) { - - Node subReferenceNode = ((Neo4jDatastore)datastore).subReferenceNodes[persistentEntity.name] - - // run neo4j traverser - Traverser traverser = args ? subReferenceNode.traverse(order, stopEvaluator, returnableEvaluator, args) : - subReferenceNode.traverse(order, stopEvaluator, returnableEvaluator, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, - GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH, - GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.BOTH, - ) - - // iterate result, unmarshall nodes to domain class instances if possible - traverser.collect { Node node -> - String className = node.getProperty("__type__", null) - if (className) { - session.retrieve(ClassUtils.forName(className), node.id) - } else { - node - } - } - } - } - } - - def traverseStatic(StopEvaluator stopEvaluator, ReturnableEvaluator returnableEvaluator, Object... args) { - traverseStatic(Traverser.Order.BREADTH_FIRST, stopEvaluator, returnableEvaluator, args) - } - - def traverseStatic(Closure stopEvaluator, Closure returnableEvaluator, Object... args) { - traverseStatic(Traverser.Order.BREADTH_FIRST, stopEvaluator, returnableEvaluator, args) - } - - def traverseStatic(Traverser.Order order, Closure stopEvaluator, Closure returnableEvaluator, Object... args) { - traverseStatic(order, stopEvaluator as StopEvaluator, returnableEvaluator as ReturnableEvaluator, args) - } - - def createInstanceForNode(nodeOrId) { - execute new SessionCallback() { - def doInSession(Session session) { - session.createInstanceForNode(nodeOrId) - } - } - } - - def cypherStatic(String queryString, Map params = [:]) { - params['this'] = datastore.subReferenceNodes[persistentEntity.name] - datastore.executionEngine.execute(queryString, params) - } - -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jMappingContext.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jMappingContext.groovy deleted file mode 100644 index 2ba71bff7..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jMappingContext.groovy +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (C) 2010 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.neo4j - -import org.grails.datastore.gorm.neo4j.converters.* -import org.grails.datastore.mapping.document.config.Attribute -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 -/** - * @author Stefan Armbruster - */ -class Neo4jMappingContext extends AbstractMappingContext { - - MappingFactory mappingFactory - MappingConfigurationStrategy syntaxStrategy - - Neo4jMappingContext() { - mappingFactory = new GraphGormMappingFactory() - syntaxStrategy = new GormMappingConfigurationStrategy(mappingFactory) - } - - @Override - protected PersistentEntity createPersistentEntity(Class javaClass) { - GraphPersistentEntity persistentEntity = new GraphPersistentEntity(javaClass, this) - mappingFactory.createMappedForm(persistentEntity) // populates mappingFactory.entityToPropertyMap as a side effect - persistentEntity - } - - MappingConfigurationStrategy getMappingSyntaxStrategy() { - syntaxStrategy - } - - MappingFactory getMappingFactory() { - mappingFactory - } -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jOpenSessionInViewInterceptor.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jOpenSessionInViewInterceptor.groovy deleted file mode 100644 index ee92a0762..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jOpenSessionInViewInterceptor.groovy +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (C) 2010 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.neo4j - -import org.neo4j.graphdb.Transaction -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.grails.datastore.mapping.web.support.OpenSessionInViewInterceptor -import org.springframework.web.context.request.WebRequest - -/** - * provide a transaction context for each request - */ -class Neo4jOpenSessionInViewInterceptor extends OpenSessionInViewInterceptor { - - protected final Logger log = LoggerFactory.getLogger(getClass()) - - ThreadLocal> transactionThreadLocal = new ThreadLocal>() { - @Override - protected Stack initialValue() { - new Stack() - } - }; - - @Override - void preHandle(WebRequest request) { - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "preHandle ${request.getDescription(true)}" - } - super.preHandle(request) - - transactionThreadLocal.get().push(datastore.graphDatabaseService.beginTx()) - } - - @Override - void afterCompletion(WebRequest request, Exception ex) { - super.afterCompletion(request, ex) - Transaction transaction = transactionThreadLocal.get().pop() - assert transaction - ex ? transaction.failure() : transaction.success() - transaction.finish() - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "afterCompletion ${request.getDescription(true)}" - } - } -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jQuery.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jQuery.groovy deleted file mode 100644 index dd4c750c4..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jQuery.groovy +++ /dev/null @@ -1,441 +0,0 @@ -/* Copyright (C) 2010 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.neo4j - -import static org.grails.datastore.mapping.query.Query.* -import static org.apache.lucene.search.BooleanClause.Occur.* -import static org.grails.datastore.mapping.query.Query.Order.Direction.* - -import org.neo4j.graphdb.Node -import org.neo4j.graphdb.Relationship - -import org.grails.datastore.mapping.model.PersistentEntity -import org.springframework.util.Assert -import java.util.regex.Pattern - -import org.grails.datastore.mapping.query.AssociationQuery; -import org.grails.datastore.mapping.query.Query -import org.grails.datastore.mapping.query.Restrictions -import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.mapping.query.projections.ManualProjections -import org.grails.datastore.mapping.model.types.Association -import org.neo4j.graphdb.index.IndexManager -import org.apache.lucene.search.BooleanQuery -import org.apache.lucene.search.BooleanClause -import org.apache.lucene.search.TermQuery -import org.apache.lucene.index.Term -import org.slf4j.LoggerFactory -import org.slf4j.Logger -import org.apache.lucene.search.MatchAllDocsQuery -import org.grails.datastore.mapping.model.types.Simple -import org.neo4j.cypher.javacompat.ExecutionEngine - -/** - * perform criteria queries on a Neo4j backend - * - * @author Stefan Armbruster - */ -class Neo4jQuery extends Query { - - protected final Logger log = LoggerFactory.getLogger(getClass()) - - Neo4jQuery(Neo4jSession session, PersistentEntity entity) { - super(session, entity) - } - - @Override - protected List executeQuery(PersistentEntity entity, Junction criteria) { - - Assert.notNull( entity, "Entity must not be null" ) - - if (indexQueryPossible(entity, criteria)) { - try { - executeQueryViaIndex(entity, criteria) - } catch (UnsupportedOperationException e) { - executeQueryViaRelationships(entity, criteria) - } catch (UnsupportedOperationException e) { - executeQueryViaRelationships(entity, criteria) - } - } else { - executeQueryViaRelationships(entity, criteria) - } - } - - protected List executeQueryViaIndex(PersistentEntity persistentEntity, Junction junction) { - IndexManager indexManager = session.datastore.indexManager - def query = new BooleanQuery() - - def typeQuery = new BooleanQuery() - for (PersistentEntity pe in session.datastore.domainSubclasses[persistentEntity]) { - typeQuery.add(new TermQuery(new Term(Neo4jSession.TYPE_PROPERTY_NAME, pe.name)), SHOULD) - } - query.add(typeQuery, MUST) -// query.add(new TermQuery(new Term(Neo4jSession.TYPE_PROPERTY_NAME, persistentEntity.name)), MUST) - query.add(buildIndexQuery(persistentEntity, junction), MUST) -// def query = buildIndexQuery(persistentEntity, junction) - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug("lucene query: $query") - } - - orderBy(paginate( - indexManager.nodeAutoIndexer.autoIndex.query(query.toString()).iterator().collect { - session.retrieve(persistentEntity.javaClass, it.id) - })) - } - - ExecutionEngine getExecutionEngine() { - session.datastore.executionEngine - } - - static MAP_JUNCTION_TO_BOOLEAN_CLAUSE = [ - Conjunction: MUST, - Disjunction: SHOULD, - Negation: MUST_NOT - ] - - protected org.apache.lucene.search.Query buildIndexQuery(PersistentEntity persistentEntity, Negation negation) { - org.apache.lucene.search.Query query = new BooleanQuery() - query.add(new MatchAllDocsQuery(), MUST) - query.add(buildIndexQuery(persistentEntity, new Disjunction(negation.criteria)), MUST_NOT) - query - } - - protected org.apache.lucene.search.Query buildIndexQuery(PersistentEntity persistentEntity, Junction junction) { - org.apache.lucene.search.Query query = new BooleanQuery() - BooleanClause.Occur queryType = MAP_JUNCTION_TO_BOOLEAN_CLAUSE[junction.class.simpleName] - //assert queryType - - for (Criterion criterion in junction.criteria) { - query.add(buildIndexQuery(persistentEntity, criterion), queryType) - } - query - } - - protected org.apache.lucene.search.Query buildIndexQuery(PersistentEntity persistentEntity, PropertyNameCriterion criterion) { - switch (criterion) { - case Equals: - def value = criterion.value - if (value instanceof String) { - value = "\"$value\"" - } else { - value = value?.toString() - } - return new TermQuery(new Term(criterion.name, value?.toString())) - break - // TODO: amend other cases - default: - throw new UnsupportedOperationException("criterion $criterion for index queries".toString()) - } - } - - boolean indexQueryPossible(PersistentEntity persistentEntity, Junction junction) { - - if ((!projections.empty) || (junction.criteria.empty)) { - return false - } - - Collection indexedPropertyNames = entity.persistentProperties.findAll { - (it instanceof Simple) && (it.propertyMapping.mappedForm.index) - }.collect {it.name} - return !hasNonIndexedPropertyCriterion(indexedPropertyNames, junction) - } - - boolean hasNonIndexedPropertyCriterion(Collection indexPropertyNames, Junction junction) { - junction.criteria.any { hasNonIndexedPropertyCriterion(indexPropertyNames, it)} - } - - boolean hasNonIndexedPropertyCriterion(Collection indexPropertyNames, PropertyNameCriterion propertyNameCriterion) { - !(propertyNameCriterion.property in indexPropertyNames) - } - - protected List executeQueryViaRelationships(PersistentEntity entity, Junction criteria) { - def result = [] - List subReferenceNodes = getSubreferencesOfSelfAndDerived(entity) - List validClassNames = subReferenceNodes.collect { it.getProperty(Neo4jSession.SUBREFERENCE_PROPERTY_NAME)} - - // shortcut for count() - if (criteria.empty && (projections.projectionList?.size()==1) && projections.projectionList[0] instanceof CountProjection) { - def cypherStatement = """ - START n=node({subReferenceNodes}) - MATCH n-[:SUBSUBREFERENCE*0..1]->s-[:INSTANCE]->instance - RETURN COUNT(*) as count - """ - if (log.debugEnabled) { - log.debug "using shortcut for count, cypher is: $cypherStatement" - } - def cypherResult = executionEngine.execute(cypherStatement, [subReferenceNodes: subReferenceNodes ]) - def cypherResultRow = cypherResult.iterator().next() - def count = cypherResultRow.get('count') - return [count] - } else { - - def cypherStatement = """ - START n=node({subReferenceNodes}) - MATCH n-[:SUBSUBREFERENCE*0..1]->s-[:INSTANCE]->instance - RETURN instance - """ - if (log.debugEnabled) { - log.debug "executing cypher statement: $cypherStatement" - } - def cypherResult = executionEngine.execute(cypherStatement, [subReferenceNodes: subReferenceNodes]) - - for (def row in cypherResult) { - Node node = row.instance - Assert.isTrue node.getProperty(Neo4jSession.TYPE_PROPERTY_NAME, null) in validClassNames - if (invokeMethod("matchesCriterion${criteria.getClass().simpleName}", [node, criteria])) { - result << session.retrieve(entity.javaClass, node.id) - } - } - if (projections.projectionList) { // TODO: optimize: add paginate and order to cypher statement - projection(result) - } else { - orderBy(paginate(result)) - } - } - } - - // FIXME: does the same query multiple times - boolean matchesCriterionAssociationQuery(Node node, AssociationQuery query) { - def (relationshipType, direction) = Neo4jUtils.relationTypeAndDirection(query.association) - def value = node.getSingleRelationship(relationshipType, direction)?.getOtherNode(node) - def q = new Neo4jQuery(query.session, query.entity) - q.add(query.criteria) - def list = q.list() - list.any { it.id == value.id } - } - - boolean hasNonIndexedPropertyCriterion(Collection indexPropertyNames, AssociationQuery query) { - true - } - - - List getSubreferencesOfSelfAndDerived(entity) { - Map subReferenceNodes = session.datastore.subReferenceNodes - // TODO: handle inheritence recursively - List result = session.mappingContext.persistentEntities.findAll { it.parentEntity == entity }.collect { - subReferenceNodes[it.name] - } - if (subReferenceNodes.containsKey(entity.name)) { - result << subReferenceNodes[entity.name] - } - result - } - - def projection(collection) { - projections.projectionList.collect { projection -> - switch (projection) { - case CountProjection: - return collection.size() - break - case MinProjection: - return collection.collect { it."$projection.propertyName" }.min() - break - case MaxProjection: - return collection.collect { it."$projection.propertyName" }.max() - break - case CountDistinctProjection: - return new ManualProjections(entity).countDistinct(collection, projection.propertyName) - break - case PropertyProjection: - return paginate( collection.collect { it."$projection.propertyName" } ) - break - case IdProjection: - return paginate( collection.collect { it."${entity.identity.name}" } ) - break - default: - throw new IllegalArgumentException("projections do not support ${projection.getClass().name}") - } - }.flatten() - } - - def paginate(collection) { - if ((max == -1 && offset == 0) || collection.empty) return collection - - int lastIndex = (max == -1) ? collection.size() : Math.min(collection.size(), offset + max) - collection[offset..lastIndex - 1] - } - - def orderBy(collection) { - if (orderBy.empty) return collection -// assert orderBy.size() == 1, "for now only sorting a single property is allowd" - collection.sort { a,b -> - for (Order order in orderBy) { - int cmp = a."$order.property" <=> b."$order.property" - if (cmp) { - return order.direction == ASC ? cmp : -cmp - } - } - } - } - - boolean matchesCriterionDisjunction(Node node, Junction criterion) { - criterion.criteria.any { invokeMethod("matchesCriterion${it.getClass().simpleName}", [node,it])} - } - - boolean matchesCriterionConjunction(Node node, Junction criterion) { - criterion.criteria.every { invokeMethod("matchesCriterion${it.getClass().simpleName}", [node,it]) } - } - - boolean matchesCriterionNegation(Node node, Junction criterion) { - return !matchesCriterionDisjunction(node, criterion) - } - - boolean matchesCriterionEquals(Node node, Criterion criterion) { - def association = entity.associations.find { it.name == criterion.name} - if (association) { - def (relationshipType, direction) = Neo4jUtils.relationTypeAndDirection(association) - node.getSingleRelationship(relationshipType, direction)?.getOtherNode(node)?.id == criterion.value - } else { - getNodeProperty(node, criterion.name) == criterion.value - } - } - - boolean matchesCriterionNotEquals(Node node, Criterion criterion) { - getNodeProperty(node, criterion.name) != criterion.value - } - - boolean matchesCriterionIn(Node node, In criterion) { - getNodeProperty(node, criterion.name) in criterion.values - } - - boolean matchesCriterionLike(Node node, Like criterion) { - def value = criterion.value.replaceAll('%','.*') - getNodeProperty(node, criterion.name) ==~ /$value/ - } - - boolean matchesCriterionILike(Node node, ILike criterion) { - def value = criterion.value.replaceAll('%','.*') - def pattern = Pattern.compile(value, Pattern.CASE_INSENSITIVE) - pattern.matcher(getNodeProperty(node, criterion.name)).matches() - } - - boolean matchesCriterionBetween(Node node, Between criterion) { - def value = getNodePropertyAsType(node, criterion.property, criterion.from.getClass()) - return ((value >= criterion.from) && (value <= criterion.to)) - } - - boolean matchesCriterionGreaterThan(Node node, GreaterThan criterion) { - getNodePropertyAsType(node, criterion.name, criterion.value?.getClass()) > criterion.value - } - - boolean matchesCriterionGreaterThanEquals(Node node, GreaterThanEquals criterion) { - getNodePropertyAsType(node, criterion.name, criterion.value?.getClass()) >= criterion.value - } - - boolean matchesCriterionLessThan(Node node, LessThan criterion) { - getNodePropertyAsType(node, criterion.name, criterion.value?.getClass()) < criterion.value - } - - boolean matchesCriterionLessThanEquals(Node node, LessThanEquals criterion) { - getNodePropertyAsType(node, criterion.name, criterion.value?.getClass()) <= criterion.value - } - - boolean matchesCriterionIdEquals(Node node, IdEquals criterion) { - node.id == criterion.value - } - - boolean matchesCriterionIdEqualsWithName(Node node, IdEqualsWithName criterion) { - PersistentProperty persistentProperty = entity.getPropertyByName(criterion.name) - def (relationshipType, direction) = Neo4jUtils.relationTypeAndDirection(persistentProperty) - Relationship rel = node.getSingleRelationship(relationshipType, direction) - def result = rel?.getOtherNode(node).id == criterion.value - result - } - - boolean matchesCriterionNotEqualsProperty(Node node, NotEqualsProperty criterion) { - getNodeProperty(node, criterion.property) != getNodeProperty(node, criterion.otherProperty) - } - - boolean matchesCriterionEqualsProperty(Node node, EqualsProperty criterion) { - getNodeProperty(node, criterion.property) == getNodeProperty(node, criterion.otherProperty) - } - - boolean matchesCriterionGreaterThanEqualsProperty(Node node, GreaterThanEqualsProperty criterion) { - getNodeProperty(node, criterion.property) >= getNodeProperty(node, criterion.otherProperty) - } - - boolean matchesCriterionGreaterThanProperty(Node node, GreaterThanProperty criterion) { - getNodeProperty(node, criterion.property) > getNodeProperty(node, criterion.otherProperty) - } - - boolean matchesCriterionLessThanEqualsProperty(Node node, LessThanEqualsProperty criterion) { - getNodeProperty(node, criterion.property) <= getNodeProperty(node, criterion.otherProperty) - } - - boolean matchesCriterionLessThanProperty(Node node, LessThanProperty criterion) { - getNodeProperty(node, criterion.property) < getNodeProperty(node, criterion.otherProperty) - } - - boolean matchesCriterionSizeLessThanEquals(Node node, SizeLessThanEquals criterion) { - countRelationshipsForProperty(node, criterion.property) <= criterion.value - } - - boolean matchesCriterionSizeLessThan(Node node, SizeLessThan criterion) { - countRelationshipsForProperty(node, criterion.property) < criterion.value - } - - boolean matchesCriterionSizeGreaterThanEquals(Node node, SizeGreaterThanEquals criterion) { - countRelationshipsForProperty(node, criterion.property) >= criterion.value - } - - boolean matchesCriterionSizeGreaterThan(Node node, SizeGreaterThan criterion) { - countRelationshipsForProperty(node, criterion.property) > criterion.value - } - - boolean matchesCriterionSizeEquals(Node node, SizeEquals criterion) { - countRelationshipsForProperty(node, criterion.property) == criterion.value - } - - boolean matchesCriterionSizeNotEquals(Node node, SizeNotEquals criterion) { - countRelationshipsForProperty(node, criterion.property) != criterion.value - } - - protected int countRelationshipsForProperty(Node node, String propertyName) { - Association association = entity.getPropertyByName(propertyName) - def (relationshipType, direction) = Neo4jUtils.relationTypeAndDirection(association) - node.getRelationships(relationshipType, direction).iterator().size() - } - - protected getNodePropertyAsType(Node node, String propertyName, Class targetClass) { - def val = getNodeProperty(node, propertyName) - session.mappingContext.conversionService.convert(val, targetClass) - } - - protected getNodeProperty(Node node, String propertyName) { - if (propertyName == 'id') { - node.id - } else { - node.getProperty(propertyName, null) - } - } - - @Override - Query eq(String property, Object value) { - Object resolved = resolveIdIfEntity(value) - if (resolved == value) { - criteria.add(Restrictions.eq(property, value)) - } - else { - criteria.add(new IdEqualsWithName(property, resolved)) - } - this - } -} - -public class IdEqualsWithName extends PropertyCriterion { - def IdEqualsWithName(property, value) { - super(property,value) - } -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jSession.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jSession.groovy deleted file mode 100644 index be9000ab1..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jSession.groovy +++ /dev/null @@ -1,774 +0,0 @@ -/* Copyright (C) 2010 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.neo4j - -import org.neo4j.graphdb.GraphDatabaseService -import org.neo4j.graphdb.Node -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.context.ApplicationEventPublisher - -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.engine.Persister -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.transactions.Transaction - -import org.grails.datastore.mapping.core.AbstractAttributeStoringSession -import javax.persistence.FlushModeType -import org.grails.datastore.mapping.query.Query -import java.util.concurrent.ConcurrentHashMap -import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.mapping.model.types.Simple -import org.codehaus.groovy.runtime.NullObject -import org.grails.datastore.mapping.model.types.OneToOne -import org.neo4j.graphdb.NotFoundException -import org.neo4j.graphdb.Direction -import org.neo4j.graphdb.Relationship -import org.springframework.util.ClassUtils -import java.util.concurrent.ConcurrentLinkedQueue -import org.grails.datastore.mapping.engine.event.PreInsertEvent -import org.grails.datastore.mapping.engine.EntityAccess -import org.grails.datastore.mapping.engine.event.PreUpdateEvent -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent -import org.grails.datastore.mapping.engine.event.PreDeleteEvent -import org.grails.datastore.mapping.engine.event.PostInsertEvent -import org.grails.datastore.mapping.engine.event.PostUpdateEvent -import org.grails.datastore.mapping.engine.event.PostDeleteEvent -import org.grails.datastore.mapping.engine.event.PreLoadEvent -import org.grails.datastore.mapping.engine.event.PostLoadEvent -import org.grails.datastore.mapping.model.types.OneToMany -import org.grails.datastore.mapping.model.types.ToOne -import org.springframework.util.Assert -import org.grails.datastore.mapping.model.types.ManyToOne -import org.grails.datastore.mapping.model.types.Association -import org.grails.datastore.mapping.collection.AbstractPersistentCollection -import org.grails.datastore.mapping.model.types.ManyToMany -import org.neo4j.graphdb.RelationshipType -import org.grails.datastore.mapping.model.types.Basic -import java.beans.PropertyChangeListener -import java.beans.PropertyChangeEvent -import org.grails.datastore.mapping.query.api.QueryableCriteria -import org.springframework.beans.BeanWrapperImpl -import org.springframework.core.convert.ConverterNotFoundException - -/** - * @author Stefan Armbruster - */ -class Neo4jSession extends AbstractAttributeStoringSession implements PropertyChangeListener { - - public static final TYPE_PROPERTY_NAME = "__type__" - public static final String SUBREFERENCE_PROPERTY_NAME = "__subreference__" - public static final String VERSION_PROPERTY = 'version' - protected final Logger log = LoggerFactory.getLogger(getClass()) - - static final ALLOWED_CLASSES_NEO4J_PROPERTIES = [ - null, - NullObject, - String, - Integer, - Long, - Byte, - Float, - Short, - Double, - Boolean, - String[], - Integer[], - Long[], - Float[], - Boolean.TYPE, - Integer.TYPE, - Long.TYPE, - Byte.TYPE, - Float.TYPE, - Short.TYPE, - Double.TYPE, - byte[].class - ] - - Transaction transaction // defacto a Neo4jTransaction - Datastore datastore // defacto a Neo4jDatastore - MappingContext mappingContext // defacto a Neo4jMappingCOntext - ApplicationEventPublisher applicationEventPublisher - FlushModeType flushMode = FlushModeType.AUTO; - - protected Map objectToKey = new ConcurrentHashMap(); - protected inserts = Collections.synchronizedSet(new HashSet()) - protected Map persisters = new ConcurrentHashMap(); - protected dirtyObjects = Collections.synchronizedSet(new HashSet()) - protected nonMonitorableObjects = Collections.synchronizedSet(new HashSet()) - - @Override - Transaction beginTransaction() { - if ((!transaction) || (!transaction.active)) { - transaction = new Neo4jTransaction(nativeInterface) - } - transaction - } - - /*@Override - void disconnect() { - transaction?.commit() - super.disconnect() - }*/ - - @Override - Serializable persist(Object o) { - Assert.notNull o - if (!o.id) { - PersistentEntity pe = mappingContext.getPersistentEntity(o.class.name) - def name = pe.javaClass.name - - Node node = nativeInterface.createNode() - node.setProperty(TYPE_PROPERTY_NAME, name) - node.setProperty(VERSION_PROPERTY, 0); - - Node subSubReferenceNode = findOrCreateSubSubReferenceNode(datastore.subReferenceNodes[name]) - Assert.notNull subSubReferenceNode - - subSubReferenceNode.createRelationshipTo(node, GrailsRelationshipTypes.INSTANCE) - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "created node $node.id with class $name" - } - o.id = node.id - inserts << o - - EntityAccess entityAccess = new EntityAccess(pe, o) - for (Association association in pe.associations) { - def value = entityAccess.getProperty(association.name) - switch (association) { - case ToOne: - if (value!=null) { - if (!value.id) { - persist(value) - } - if ((association instanceof ManyToOne) && association.bidirectional) { - EntityAccess reverseEntityAccess = new EntityAccess(association.associatedEntity, value) - addObjectToReverseSide(reverseEntityAccess, association, o) - } - } - break - case ManyToMany: - case OneToMany: - if (value!=null) { - value.findAll { !it.id }.each { - persist(it) - if (association.bidirectional) { - EntityAccess reverseEntityAccess = new EntityAccess(association.associatedEntity, it) - addObjectToReverseSide(reverseEntityAccess, association, o) - } - } - } - break - default: - throw new UnsupportedOperationException() - } - } - } - objectToKey[o.id] = o - monitorSettersForObject(o) - o.id - } - - @Override - Serializable insert(Object o) { - return persist(o) - } -/** - * return a subSubReference node for the current operation. - * Current strategy is to use current thread's is module 128 - * @param subSubReferenceMap - * @return - */ - Node findOrCreateSubSubReferenceNode(Node subReferenceNode) { - int hashValue = Thread.currentThread().id % Neo4jDatastore.NUMBER_OF_SUBSUBREFERENCE_NODES - def subSubReferenceNode = subReferenceNode.getRelationships(GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.OUTGOING).find { - it.getProperty("hash", null) == hashValue - }?.endNode - if (!subSubReferenceNode) { - subSubReferenceNode = datastore.graphDatabaseService.createNode() - Relationship rel = subReferenceNode.createRelationshipTo(subSubReferenceNode, GrailsRelationshipTypes.SUBSUBREFERENCE) - rel.setProperty("hash", hashValue) - } - return subSubReferenceNode - //subSubReferenceMap.get(subSubReferneceKey) - } - - @Override - void refresh(Object o) { - throw new UnsupportedOperationException() - } - - @Override - void attach(Object o) { - Assert.notNull o.id - objectToKey[o.id] = o - monitorSettersForObject(o) - } - - private boolean isProxy(object) { - object.metaClass.getMetaMethod("isProxy", null) != null - } - - @Override - void flush() { - // do not iterate directly since we might add some entities to objects collection during iteration - def startingSet = new HashSet(nonMonitorableObjects.size() + dirtyObjects.size() + inserts.size()) - startingSet.addAll(nonMonitorableObjects) - startingSet.addAll(dirtyObjects) - startingSet.addAll(inserts) - - def objects = new ConcurrentLinkedQueue(startingSet) - - if (log.infoEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.info "pre flush counting: nonMonitorable: ${nonMonitorableObjects.size()}, dirty: ${dirtyObjects.size()}, inserts: ${inserts.size()}, total: ${objects.size()}" - } - - def alreadyPersisted = [] as Set // required to prevent doubled (and cyclic) saves - - def persistedCounter = 0 - - while (!objects.empty) { - def obj = objects.poll() - def id = obj.id - if ((obj in alreadyPersisted) || isProxy(obj)) { - continue - } - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "flush obj ${obj.getClass().name} $id" - } - alreadyPersisted << obj - PersistentEntity pe = mappingContext.getPersistentEntity(obj.getClass().name) - - def entityAccess = new EntityAccess(pe, obj) - AbstractPersistenceEvent event = inserts.contains(obj) ? - new PreInsertEvent(datastore, pe, entityAccess) : new PreUpdateEvent(datastore, pe, entityAccess) - applicationEventPublisher.publishEvent(event) - if (event.cancelled) { - continue - } - - boolean hasChanged = false - - Node thisNode = nativeInterface.getNodeById(obj.id) - for (PersistentProperty prop in pe.persistentProperties) { - def value = entityAccess.getProperty(prop.name) - switch (prop) { - case Simple: - if ((value!=null) && (!ALLOWED_CLASSES_NEO4J_PROPERTIES.contains(prop.type))) { - try { - value = mappingContext.conversionService.convert(value, Long.TYPE) - } catch (ConverterNotFoundException e) { - value = mappingContext.conversionService.convert(value, String) - } - - } - if (thisNode.getProperty(prop.name, null) != value) { - value == null ? thisNode.removeProperty(prop.name) : thisNode.setProperty(prop.name, value) - hasChanged = true - } - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "storing simple for $prop = $value ${thisNode.getProperty(prop.name, null)?.getClass()}" - } - break - - case ToOne: - def toAdd = writeToOneProperty(prop, thisNode, value, obj) - if (toAdd) { - objects << toAdd - } - break - - case ManyToMany: - case OneToMany: - objects.addAll(writeToManyProperty(value, prop, thisNode, obj)) - break - - case Basic: - if (prop.type instanceof Collection) { - objects.addAll(writeToManyProperty(value, prop, thisNode, obj)) - } - else { - def toAdd = writeToOneProperty(prop, thisNode, value, obj) - if (toAdd) { - objects << toAdd - } - } - break - - default: - throw new UnsupportedOperationException("don't know how to store $prop ${prop.getClass().superclass}") - - } - } - - if (hasChanged && (!inserts.contains(obj))) { - def version = thisNode.getProperty(VERSION_PROPERTY) + 1 - thisNode.setProperty(VERSION_PROPERTY, version) - if(obj && obj.hasProperty(VERSION_PROPERTY)) { - entityAccess.setProperty(VERSION_PROPERTY, version) - } - } - - //def entityAccess = new EntityAccess(pe, obj) - event = inserts.contains(obj) ? - new PostInsertEvent(datastore, pe, entityAccess) : new PostUpdateEvent(datastore, pe, entityAccess) - applicationEventPublisher.publishEvent(event) // TODO: hotspot - persistedCounter++ - } - inserts.clear() - dirtyObjects.clear() - if (log.infoEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.info "post flush counting: persisted: $persistedCounter" - } - } - - private def writeToManyProperty(value, Association association, Node thisNode, obj) { - def returnValue = [] - boolean doPersist = true - if (value == null) { - doPersist = false - } else { - // prevent persisting an not initialized APS - if (value instanceof AbstractPersistentCollection) { - doPersist = value.initialized - } - } - - if (doPersist) { - def nodesIds = value?.collect { - - if (!it.id) { // if referenced obj is not yet persisted, add it and append it to flush chain - persist(it) - returnValue << it - } - - if (association.bidirectional) { - EntityAccess reverseEntityAccess = new EntityAccess(association.associatedEntity, it) - addObjectToReverseSide(reverseEntityAccess, association, obj) - } - it.node.id - } ?: [] - - def (relationshipType, direction) = Neo4jUtils.relationTypeAndDirection(association) - - def existingNodesIds = [] - - for (Relationship rel in thisNode.getRelationships(relationshipType, direction).iterator()) { - def target = rel.getOtherNode(thisNode).id - if (target in nodesIds) { - existingNodesIds << target - } else { - rel.delete() - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "delete relationship ${rel.startNode.id} -> ${rel.endNode.id} ($rel.type.name()}" - } - } - } - - (nodesIds - existingNodesIds).each { - Node startNode = thisNode - Node endNode = nativeInterface.getNodeById(it) - if (direction == Direction.INCOMING) { - (startNode, endNode) = [endNode, startNode] - } - startNode.createRelationshipTo(endNode, relationshipType) - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "created relationship ${startNode.id} -> ${endNode.id} ($relationshipType}" - } - } - } - returnValue - } - - private def writeToOneProperty(Association association, Node thisNode, value, obj) { - def returnValue = null - if ((value != null) && (!value.id)) { - persist(value) - returnValue = value - } - - def (relationshipType, direction) = Neo4jUtils.relationTypeAndDirection(association) - Relationship rel = findRelationshipWithMatchingType(thisNode, relationshipType, direction, association.type) - - def endNodeId = rel?.getOtherNode(thisNode)?.id - if (endNodeId && ((value == null) || (value.id != endNodeId))) { - rel.delete() - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "delete relationship ${rel.startNode.id} -> ${rel.endNode.id} ($rel.type.name()}" - } - } - - if ((value != null) && (value.id != endNodeId)) { - Node startNode = thisNode - Node endNode = value?.node - if (direction == Direction.INCOMING) { - (startNode, endNode) = [endNode, startNode] - } - startNode.createRelationshipTo(endNode, relationshipType) - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "created relationship ${startNode.id} -> ${endNode.id} ($relationshipType}" - } - - if (association.bidirectional) { - def referencePropertyAccess = new EntityAccess(association.associatedEntity, value) - switch (association) { - case OneToOne: - //referencePropertyAccess.setProperty(association.referencedPropertyName, obj) - //value."${prop.referencedPropertyName}" = obj - break - case ManyToOne: - addObjectToReverseSide(referencePropertyAccess, association, obj) - break - default: - throw new UnsupportedOperationException("setting inverse side of bidi, ${association.getClass().superclass}") - } - } - } - returnValue - } - - @Override - void clear() { - objectToKey.values().each { unmonitorSettersForObject(it)} - objectToKey.clear() - dirtyObjects.clear() - inserts.clear() - } - - @Override - void clear(Object o) { - unmonitorSettersForObject(o) - objectToKey.remove(o.id) - inserts.remove(o) - dirtyObjects.remove(o) - } - - @Override - boolean contains(Object o) { - objectToKey.containsValue(o) - } - - @Override - void lock(Object o) { - // hack recommended from neo4j guys: remove an non-existing property from a node to lock it - Node node = o.node - node.removeProperty('__notexisting__') - } - - @Override - void unlock(Object o) { - // Unlocking happens upon transaction termination - } - - @Override - List persist(Iterable objects) { - objects.collect { persist(it) } - } - - /** - * @param node - * @return {@link PersistentEntity} matching the node's {@link org.grails.datastore.gorm.neo4j.Neo4jSession#TYPE_PROPERTY_NAME} or null - */ - private PersistentEntity getTypeForNode(Node node) { - String nodeType = node.getProperty(TYPE_PROPERTY_NAME, null) - nodeType == null ? null : mappingContext.getPersistentEntity(nodeType) - } - - private Relationship findRelationshipWithMatchingType(Node node, RelationshipType relationshipType, Direction direction, Class type) { - node.getRelationships(relationshipType, direction).iterator().find { - def otherNode = it.getOtherNode(node) - PersistentEntity pe = getTypeForNode(otherNode) - type.isAssignableFrom(pe.javaClass) - } - } - - @Override - def T retrieve(Class type, Serializable key) { - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "retrieving $type for id $key" - } - def id = mappingContext.getConversionService().convert(key, Long) - if (id == null) { - return null - } - def result = objectToKey[id] - if ((result == null) || isProxy(result)) { - try { - Node node = nativeInterface.getNodeById(id) - PersistentEntity pe = getTypeForNode(node) - if ((pe == null) || (type && !type.isAssignableFrom(pe.javaClass))) { - return null - } - result = pe.javaClass.newInstance() - result.id = id - - def entityAccess = new EntityAccess(pe, result) - applicationEventPublisher.publishEvent(new PreLoadEvent(datastore, pe, entityAccess)) - - for (PersistentProperty prop in pe.persistentProperties) { - switch (prop) { - case Simple: - def value = node.getProperty(prop.name, null) - value = mappingContext.conversionService.convert(value, prop.type) - entityAccess.setProperty(prop.name, value) - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "reading simple for $prop $value" - } - break - - case ToOne: - readToOneProperty(prop, node, entityAccess) - break - - case OneToMany: - case ManyToMany: - readToManyProperty(prop, node, entityAccess) - break - - case Basic: - if (prop.type instanceof Collection) { - readToManyProperty(prop, node, entityAccess) - } - else { - readToOneProperty(prop, node, entityAccess) - } - - default: - throw new UnsupportedOperationException("don't know how to read $prop ${prop.getClass().superclass}") - } - } - applicationEventPublisher.publishEvent(new PostLoadEvent(datastore, pe, entityAccess)) - objectToKey[id] = result - monitorSettersForObject(result) - } catch (NotFoundException e) { - log.warn "no node for $id found: $e.message" - return null - } - } - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "returning for $key ${System.identityHashCode(result)}" - } - result - } - - // global map that remembers if a given domain class supports propertyChangeListeners - static memoizePropertyChangeListener = Collections.synchronizedMap([:].withDefault() { - it.newInstance().respondsTo("addPropertyChangeListener") as Boolean - }) - - private void monitorSettersForObject(object) { - if (memoizePropertyChangeListener[object.class] == true) { - object.addPropertyChangeListener(this) - } else { - nonMonitorableObjects << object - } - } - - private void unmonitorSettersForObject(object) { - if (memoizePropertyChangeListener[object.class] == true) { - object.removePropertyChangeListener(this) - } else { - nonMonitorableObjects.remove(object) - } - } - - private def readToManyProperty(Association association, Node node, EntityAccess entityAccess) { - def (relationshipType, direction) = Neo4jUtils.relationTypeAndDirection(association) - def keys = node.getRelationships(relationshipType, direction).iterator().collect { it.getOtherNode(node).id } - - def collection = List.class.isAssignableFrom(association.type) ? - new ObservableListWrapper(entityAccess.entity, association.name, keys, association.associatedEntity.javaClass, this) : - new ObservableSetWrapper(entityAccess.entity, association.name, keys, association.associatedEntity.javaClass, this) - entityAccess.setPropertyNoConversion(association.name, collection) - } - - private def readToOneProperty(Association association, Node node, EntityAccess entityAccess) { - def (relationshipType, direction) = Neo4jUtils.relationTypeAndDirection(association) - def rel = findRelationshipWithMatchingType(node, relationshipType, direction, association.type) - if (rel) { - Node end = rel.getOtherNode(node) - def value = objectToKey[end.id] - if (value == null) { - value = proxy(ClassUtils.forName(end.getProperty(TYPE_PROPERTY_NAME, null)), end.id) - } - entityAccess.setProperty(association.name, value) - } - } - - @Override - def T proxy(Class type, Serializable key) { - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "creating proxy for $type, id $key" - } - mappingContext.proxyFactory.createProxy(this, type, key) - } - - @Override - def T lock(Class type, Serializable key) { - throw new UnsupportedOperationException() - } - - @Override - void delete(Iterable objects) { - for (instance in objects) { - delete(instance) - } - } - - @Override - void delete(Object obj) { - PersistentEntity pe = mappingContext.getPersistentEntity(obj.getClass().name) - - def entityAccess = new EntityAccess(pe, obj) - def event = new PreDeleteEvent(datastore, pe, entityAccess) - applicationEventPublisher.publishEvent(event) - if (event.cancelled) { - return - } - - Node node = obj.node - for (Relationship rel in node.getRelationships().iterator()) { - rel.delete() - } - node.delete() - inserts.remove(obj) - objectToKey.remove(obj.id) - dirtyObjects.remove(obj) - unmonitorSettersForObject(obj) - - event = new PostDeleteEvent(datastore, pe, entityAccess) - applicationEventPublisher.publishEvent(event) - - } - - @Override - List retrieveAll(Class type, Iterable keys) { - keys.collect { retrieve(type, it)} - } - - @Override - List retrieveAll(Class type, Serializable... keys) { - retrieveAll(type, keys) - } - - @Override - Query createQuery(Class type) { - new Neo4jQuery(this, mappingContext.getPersistentEntity(type.name)) - } - - @Override - GraphDatabaseService getNativeInterface() { - datastore.graphDatabaseService - } - - @Override - Persister getPersister(Object o) { - // copied from AbstractSession - if (o == null) return null; - Class cls = o instanceof Class ? o : (o instanceof PersistentEntity ? o.javaClass : o.getClass()) - Persister p = persisters.get(cls); - if (p == null) { - p = createPersister(cls, getMappingContext()); - if (p) { - persisters[cls] = p - } - } - p - } - - protected Persister createPersister(Class cls, MappingContext mappingContext) { - final PersistentEntity entity = mappingContext.getPersistentEntity(cls.name) - entity ? new DummyEntityPersister(mappingContext, entity) : null - } - - @Override - boolean isDirty(Object instance) { - throw new UnsupportedOperationException() - } - - @Override - Serializable getObjectIdentifier(Object instance) { - final entity = instance ? mappingContext.getPersistentEntity(instance.getClass().name) : null - if(entity) { - return (Serializable) new EntityAccess(entity, instance).getIdentifier(); - } - return null - } - - private def addObjectToReverseSide(EntityAccess reverseEntityAccess, Association association, objectToSet) { - def propertyValue = reverseEntityAccess.getProperty(association.referencedPropertyName) - switch (association.inverseSide) { - case OneToMany: - case ManyToMany: - if (!propertyValue) { - propertyValue = Set.class.isAssignableFrom(association.inverseSide.type) ? [] as Set : [] - reverseEntityAccess.setPropertyNoConversion(association.referencedPropertyName, propertyValue) - } - if (!(objectToSet in propertyValue)) { - propertyValue << objectToSet - } - break - case ToOne: - reverseEntityAccess.setProperty(association.referencedPropertyName, objectToSet) - break - default: - throw new UnsupportedOperationException() - } - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "addObjectToReverseSide: property value $propertyValue" - } - } - - - def createInstanceForNode(nodeOrId) { - def id = nodeOrId instanceof Node ? nodeOrId.id : nodeOrId as long - retrieve(null, id) - } - - @Override - int deleteAll(QueryableCriteria criteria) { - // TODO: suboptimal.. improve batch deletes - int total = 0 - for (o in criteria.list()) { - delete(o) - total++ - } - return total - } - - @Override - int updateAll(QueryableCriteria criteria, Map properties) { - // TODO: suboptimal.. improve batch updates - final results = criteria.list() - int total = 0 - for (o in results) { - total++ - def bean = new BeanWrapperImpl(o) - bean.setPropertyValues(properties) - persist(o) - } - return total - } - - @Override - void propertyChange(PropertyChangeEvent propertyChangeEvent) { - if (propertyChangeEvent.propertyName!=VERSION_PROPERTY) { - dirtyObjects << propertyChangeEvent.source - } - } - -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jTransaction.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jTransaction.groovy deleted file mode 100644 index 8a8cf1320..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jTransaction.groovy +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (C) 2010 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.neo4j - -import org.neo4j.graphdb.GraphDatabaseService -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.grails.datastore.mapping.transactions.Transaction - -/** - * wrapping a Neo4j {@link org.neo4j.graphdb.Transaction} into a Spring data mapping {@link Transaction} - * @author Stefan Armbruster - */ -class Neo4jTransaction implements Transaction { - - protected final Logger log = LoggerFactory.getLogger(getClass()) - - GraphDatabaseService graphDatabaseService - org.neo4j.graphdb.Transaction nativeTransaction - boolean active = true - - Neo4jTransaction(GraphDatabaseService graphDatabaseService) { - this.graphDatabaseService = graphDatabaseService - nativeTransaction = graphDatabaseService.beginTx() - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "new: $nativeTransaction" - } - } - - void commit() { - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "commit $nativeTransaction" - } - nativeTransaction.success() - nativeTransaction.finish() - active = false - } - - void rollback() { - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "rollback $nativeTransaction" - } - nativeTransaction.failure() - nativeTransaction.finish() - active = false - } - - Object getNativeTransaction() { - nativeTransaction - } - - boolean isActive() { - active - } - - void setTimeout(int timeout) { - throw new UnsupportedOperationException() - } -} 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 deleted file mode 100644 index bd744071f..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jUtils.groovy +++ /dev/null @@ -1,69 +0,0 @@ -package org.grails.datastore.gorm.neo4j - -import org.neo4j.graphdb.Direction -import org.neo4j.graphdb.Node -import org.grails.datastore.mapping.model.types.ManyToMany -import org.neo4j.graphdb.DynamicRelationshipType -import org.grails.datastore.mapping.model.types.Association -import org.slf4j.LoggerFactory -import org.grails.datastore.mapping.model.types.ManyToOne -import org.springframework.util.ClassUtils - -/** - * Collection of static util methods regarding Neo4j - */ -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 - */ - static void dumpNode(Node node, logger = null) { - logger = logger ?: LoggerFactory.getLogger(Neo4jDatastore.class) - logger.warn "Node $node.id: $node" - node.propertyKeys.each { - logger.warn "Node $node.id property $it -> ${node.getProperty(it,null)}" - } - node.relationships.each { - logger.warn "Node $node.id relationship $it.startNode -> $it.endNode : ${it.type.name()}" - } - } - - /** - * check if a given node is valid for a given class - * @param node - * @param persistentProperty - * @return - */ - static boolean doesNodeMatchType(Node node, Class clazz) { - try { - def nodeClass = ClassUtils.forName(node.getProperty(Neo4jSession.TYPE_PROPERTY_NAME, null)) - clazz.isAssignableFrom(nodeClass) - } catch (ClassNotFoundException e) { - false - } - } -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/ObservableListWrapper.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/ObservableListWrapper.groovy deleted file mode 100644 index 98ce1ff84..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/ObservableListWrapper.groovy +++ /dev/null @@ -1,106 +0,0 @@ -package org.grails.datastore.gorm.neo4j - -import java.beans.PropertyChangeEvent -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.collection.PersistentList - -import java.beans.PropertyChangeListener - -/** - * Created by IntelliJ IDEA. - * User: stefan - * Date: 18.09.11 - * Time: 14:44 - * To change this template use File | Settings | File Templates. - */ -class ObservableListWrapper implements List, Externalizable { - - @Delegate List wrapped - def entity - PropertyChangeListener propertyChangeListener - String propertyName - - ObservableListWrapper(def entity, String propertyName, Collection keys, Class clazz, Session session) { - this.entity = entity - this.propertyChangeListener = session - this.propertyName = propertyName - wrapped = new PersistentList(keys, clazz, session) - } - - ObservableListWrapper() { - } - - private fireChangeEvent() { - propertyChangeListener.propertyChange(new PropertyChangeEvent(entity, null, null, null)) - } - - boolean add(obj) { - fireChangeEvent() - wrapped.add(obj) - } - - boolean remove(def obj) { - fireChangeEvent() - wrapped.remove(obj) - } - - boolean addAll(Collection coll) { - fireChangeEvent() - wrapped.addAll(coll) - } - - boolean retainAll(Collection coll) { - fireChangeEvent() - wrapped.retainAll(coll) - } - - boolean removeAll(Collection coll) { - fireChangeEvent() - wrapped.removeAll(coll) - } - - void clear() { - fireChangeEvent() - wrapped.clear() - } - - public Object set(int index, Object element) { - fireChangeEvent() - wrapped.set(index, element) - } - - public void add(int index, Object element) { - fireChangeEvent() - wrapped.add(index, element) - } - - public Object remove(int index) { - fireChangeEvent() - wrapped.remove(index) - } - - public boolean addAll(int index, Collection c) { - fireChangeEvent() - wrapped.addAll(index, c) - } - - void writeExternal(java.io.ObjectOutput objectOutput) throws java.io.IOException { - objectOutput.writeObject(entity.class) - objectOutput.writeLong(entity.id) - objectOutput.writeObject(propertyName) - } - - void readExternal(java.io.ObjectInput objectInput) throws java.io.IOException, java.lang.ClassNotFoundException { - def entityClazz = objectInput.readObject() - def entityId = objectInput.readLong() - entity = entityClazz.get(entityId) - propertyName = objectInput.readObject(); - wrapped = entity."${propertyName}".wrapped - entityClazz.withSession { session -> - propertyChangeListener = session - } - - } - - -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/ObservableSetWrapper.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/ObservableSetWrapper.groovy deleted file mode 100644 index 421a8c2a0..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/ObservableSetWrapper.groovy +++ /dev/null @@ -1,83 +0,0 @@ -package org.grails.datastore.gorm.neo4j - -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.collection.PersistentSet -import java.beans.PropertyChangeEvent -import java.beans.PropertyChangeListener - -/** - * Created by IntelliJ IDEA. - * User: stefan - * Date: 18.09.11 - * Time: 14:44 - * To change this template use File | Settings | File Templates. - */ -class ObservableSetWrapper implements Set, Externalizable { - - @Delegate PersistentSet wrapped - def entity - PropertyChangeListener propertyChangeListener - String propertyName - - ObservableSetWrapper(def entity, String propertyName, Collection keys, Class clazz, Session session) { - this.entity = entity - this.propertyChangeListener = session - this.propertyName = propertyName - wrapped = new PersistentSet(keys, clazz, session) - } - - ObservableSetWrapper() { - } - - private void fireChangeEvent() { - propertyChangeListener.propertyChange(new PropertyChangeEvent(entity, null, null, null)) - } - - boolean add(obj) { - fireChangeEvent() - wrapped.add(obj) - } - boolean remove(def obj) { - fireChangeEvent() - wrapped.remove(obj) - } - - boolean addAll(Collection coll) { - fireChangeEvent() - wrapped.addAll(coll) - } - - boolean retainAll(Collection coll) { - fireChangeEvent() - wrapped.retainAll(coll) - } - - boolean removeAll(Collection coll) { - fireChangeEvent() - wrapped.removeAll(coll) - } - - void clear() { - fireChangeEvent() - wrapped.clear() - } - - void writeExternal(java.io.ObjectOutput objectOutput) throws java.io.IOException { - objectOutput.writeObject(entity.class) - objectOutput.writeLong(entity.id) - objectOutput.writeObject(propertyName) - } - - void readExternal(java.io.ObjectInput objectInput) throws java.io.IOException, java.lang.ClassNotFoundException { - def entityClazz = objectInput.readObject() - def entityId = objectInput.readLong() - entity = entityClazz.get(entityId) - propertyName = objectInput.readObject() - wrapped = entity."${propertyName}".wrapped - entityClazz.withSession { session -> - propertyChangeListener = session - } - - } - -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/bean/factory/Neo4jDatastoreFactoryBean.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/bean/factory/Neo4jDatastoreFactoryBean.groovy deleted file mode 100644 index 03e2b1a0f..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/bean/factory/Neo4jDatastoreFactoryBean.groovy +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (C) 2010 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.neo4j.bean.factory - -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.gorm.neo4j.Neo4jDatastore -import org.neo4j.graphdb.GraphDatabaseService -import org.springframework.beans.factory.FactoryBean -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware -import org.grails.datastore.mapping.model.MappingContext - -/** - * Factory bean for constructing a {@link Neo4jDatastore} instance. - * - * @author Stefan Armbruster - */ -class Neo4jDatastoreFactoryBean implements FactoryBean, ApplicationContextAware { - - GraphDatabaseService graphDatabaseService - MappingContext mappingContext - Map config = [:] - ApplicationContext applicationContext - - Neo4jDatastore getObject() { - - Neo4jDatastore datastore = new Neo4jDatastore(mappingContext, applicationContext, graphDatabaseService) - - applicationContext.addApplicationListener new DomainEventListener(datastore) - applicationContext.addApplicationListener new AutoTimestampEventListener(datastore) - - datastore.afterPropertiesSet() - datastore - } - - Class getObjectType() { Neo4jDatastore } - - boolean isSingleton() { true } -} 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 deleted file mode 100644 index 8ba708196..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/bean/factory/Neo4jMappingContextFactoryBean.groovy +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (C) 2010 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.neo4j.bean.factory - -import org.grails.datastore.gorm.bean.factory.AbstractMappingContextFactoryBean -import org.grails.datastore.gorm.neo4j.Neo4jMappingContext -import org.grails.datastore.mapping.model.MappingContext - -/** - * Factory bean for construction the Neo4j DocumentMappingContext. - * - * @author Stefan Armbruster - */ -class Neo4jMappingContextFactoryBean extends AbstractMappingContextFactoryBean { - - protected MappingContext createMappingContext() { - new Neo4jMappingContext() - } -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/constraints/UniqueConstraint.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/constraints/UniqueConstraint.groovy deleted file mode 100644 index 998958547..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/constraints/UniqueConstraint.groovy +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (C) 2010 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.neo4j.constraints - -import org.codehaus.groovy.grails.validation.AbstractConstraint -import org.grails.datastore.gorm.neo4j.GrailsRelationshipTypes -import org.neo4j.graphdb.Direction -import org.neo4j.graphdb.Node -import org.neo4j.graphdb.Relationship -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.validation.Errors - -/** - * The UniqueConstraint depends on the current GORM implementation, that's why we need to implement it here. - * @author Stefan Armbruster - * @since 0.2 - */ -@Deprecated -class UniqueConstraint extends AbstractConstraint { - - protected final Logger log = LoggerFactory.getLogger(getClass()) - protected static final String DEFAULT_NOT_UNIQUE_MESSAGE_CODE = "default.not.unique.message" - - public static final String UNIQUE_CONSTRAINT = "unique" - - protected void processValidate(target, propertyValue, Errors errors) { - - if (!constraintParameter) { - return - } - - Node subreferenceNode = target.subreferenceNode - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "subreferenceNode $subreferenceNode" - } - // TODO: consider using index for this - - Relationship hasMatchingNode = subreferenceNode.getRelationships(GrailsRelationshipTypes.INSTANCE, Direction.OUTGOING).iterator().find { - (it.endNode.id != target.id) && (it.endNode.getProperty(constraintPropertyName, null) == propertyValue) - - } - if (log.debugEnabled) { // TODO: add @Slf4j annotation when groovy 1.8 is used - log.debug "hasMatchingNode $hasMatchingNode" - } - - if (hasMatchingNode) { - rejectValue(target, errors, UNIQUE_CONSTRAINT, - [constraintPropertyName, constraintOwningClass, propertyValue ], - getDefaultMessage(DEFAULT_NOT_UNIQUE_MESSAGE_CODE)) - } - } - - boolean supports(Class type) { - type != null - } - - String getName() { - UNIQUE_CONSTRAINT - } -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jMethodsConfigurer.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jMethodsConfigurer.groovy deleted file mode 100644 index d951e14e8..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jMethodsConfigurer.groovy +++ /dev/null @@ -1,61 +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.neo4j.plugin.support - -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.neo4j.Neo4jGormEnhancer -import org.grails.datastore.gorm.neo4j.Neo4jGormInstanceApi -import org.grails.datastore.gorm.neo4j.Neo4jGormStaticApi -import org.grails.datastore.gorm.plugin.support.DynamicMethodsConfigurer -import org.grails.datastore.mapping.core.Datastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * Methods configurer implementation for Neo4j. - * - * @author Graeme Rocher - * @since 1.0 - */ -class Neo4jMethodsConfigurer extends DynamicMethodsConfigurer { - - Neo4jMethodsConfigurer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { "Neo4j" } - - @Override - protected GormStaticApi createGormStaticApi(Class cls, List finders) { - return new Neo4jGormStaticApi(cls, datastore, finders) - } - - @Override - protected GormInstanceApi createGormInstanceApi(Class cls) { - def api = new Neo4jGormInstanceApi(cls, datastore) - api.failOnError = failOnError - api - } - - @Override - protected GormEnhancer createEnhancer() { - def ge = new Neo4jGormEnhancer(datastore, transactionManager) - ge.failOnError = failOnError - ge - } -} diff --git a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jOnChangeHandler.groovy b/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jOnChangeHandler.groovy deleted file mode 100644 index dc47a3cd2..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jOnChangeHandler.groovy +++ /dev/null @@ -1,35 +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.neo4j.plugin.support - -import org.grails.datastore.gorm.plugin.support.OnChangeHandler -import org.grails.datastore.mapping.core.Datastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * onChange handler for neo4j. - * - * @author Graeme Rocher - * @since 1.0 - */ -class Neo4jOnChangeHandler extends OnChangeHandler { - - Neo4jOnChangeHandler(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { "Neo4j" } -} 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 deleted file mode 100644 index 69c8c7abd..000000000 --- a/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/plugin/support/Neo4jSpringConfigurer.groovy +++ /dev/null @@ -1,132 +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.neo4j.plugin.support - -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.grails.datastore.gorm.neo4j.Neo4jOpenSessionInViewInterceptor -import org.neo4j.kernel.impl.transaction.SpringTransactionManager -import org.neo4j.kernel.impl.transaction.UserTransactionImpl -import org.neo4j.kernel.AbstractGraphDatabase -import org.springframework.transaction.jta.JtaTransactionManager - -/** - * Spring configurer for Neo4j - * - * @author Graeme Rocher - * @since 1.0 - */ -class Neo4jSpringConfigurer extends SpringConfigurer { - @Override - String getDatastoreType() { - return "Neo4j" - } - - @Override - Closure getSpringCustomizer() { - return { - def neo4jConfig = application.config?.grails?.neo4j // use config from app's Datasource.groovy - if (!neo4jConfig) { - throw new IllegalArgumentException("Unable to find 'grails.neo4j' in application config.") - } - Class neo4jGraphDatabaseClass - - if (neo4jConfig.type == "rest") { - neo4jGraphDatabaseClass = "org.neo4j.rest.graphdb.RestGraphDatabase" as Class - - // env paramters have precedence (Heroku uses this) - def location = System.env['NEO4J_HOST'] ? - "http://${System.env['NEO4J_HOST']}:${System.env['NEO4J_PORT']}/db/data" : - neo4jConfig.location ?: "http://localhost:7474/db/data/" - def login = System.env['NEO4J_LOGIN'] ?: neo4jConfig.login ?: null - def password = System.env['NEO4J_PASSWORD'] ?: neo4jConfig.password ?: null - - graphDatabaseService(neo4jGraphDatabaseClass, location, login, password) { bean -> - bean.destroyMethod = "shutdown" - } - } else { - String neo4jGraphDatabaseClassName - String neo4jDefaultLocation - switch (neo4jConfig.type) { - case "ha": - neo4jGraphDatabaseClassName = "org.neo4j.kernel.HighlyAvailableGraphDatabase" - neo4jDefaultLocation = "data/neo4j" - break - case "embedded": - neo4jGraphDatabaseClassName = "org.neo4j.kernel.EmbeddedGraphDatabase" - neo4jDefaultLocation = "data/neo4j" - break - case "impermanent": - neo4jGraphDatabaseClassName = "org.neo4j.test.ImpermanentGraphDatabase" - neo4jDefaultLocation = "data/neo4j" - break - default: // otherwise type is used as classname - if (neo4jConfig.type) { - neo4jGraphDatabaseClassName = neo4jConfig.type - neo4jDefaultLocation = "data/neo4j" - } else { - throw new RuntimeException("no config for neo4j found") - } - break - } - - try { - neo4jGraphDatabaseClass = neo4jGraphDatabaseClassName as Class - } catch (ClassNotFoundException e) { - throw new RuntimeException("could not load $neo4jGraphDatabaseClassName, maybe add neo4j-enterprise to dependecies section", e) - } - - graphDatabaseService( - neo4jGraphDatabaseClass, - neo4jConfig.location ?: neo4jDefaultLocation, - neo4jConfig.params ?: [:] - ) { bean -> - bean.destroyMethod = "shutdown" - } - - } - - neo4jMappingContext(Neo4jMappingContextFactoryBean) { - grailsApplication = ref('grailsApplication') - pluginManager = ref('pluginManager') - } - - neo4jDatastore(Neo4jDatastoreFactoryBean) { - graphDatabaseService = graphDatabaseService - mappingContext = neo4jMappingContext - - } - - if (manager?.hasGrailsPlugin("controllers")) { - neo4jOpenSessionInViewInterceptor(Neo4jOpenSessionInViewInterceptor) { - datastore = ref("neo4jDatastore") - } - /*if (getSpringConfig().containsBean("controllerHandlerMappings")) { - controllerHandlerMappings.interceptors << neo4jOpenSessionInViewInterceptor - } - if (getSpringConfig().containsBean("annotationHandlerMapping")) { - if (annotationHandlerMapping.interceptors) { - annotationHandlerMapping.interceptors << neo4jOpenSessionInViewInterceptor - } - else { - annotationHandlerMapping.interceptors = [neo4jOpenSessionInViewInterceptor] - } - } */ - } - - } - } -} diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/DomainEventsSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/DomainEventsSpec.groovy deleted file mode 100644 index 773c296aa..000000000 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/DomainEventsSpec.groovy +++ /dev/null @@ -1,291 +0,0 @@ -package grails.gorm.tests - -import groovy.transform.NotYetImplemented -import org.grails.datastore.mapping.core.Session -import grails.gorm.DetachedCriteria -import spock.lang.Issue - -/** - * @author graemerocher - */ -class DomainEventsSpec extends GormDatastoreSpec { - - def setup() { - PersonEvent.resetStore() - } - @Issue('GPMONGODB-262') - void "Test that returning false from beforeUpdate evicts the event"() { - when:"An entity is saved" - def p = new PersonEvent(name: "Fred") - p.save(flush: true) - session.clear() - p = PersonEvent.get(p.id) - then:"The person is saved" - p != null - - when:"The beforeUpdate event returns false" - p.name = "Bad" - p.save(flush: true) - session.clear() - - then:"The person is never updated" - PersonEvent.get(p.id).name == "Fred" - } - - @Issue('GPMONGODB-262') - @NotYetImplemented - void "Test that returning false from beforeInsert evicts the event"() { - when:"false is returned from a beforeInsert event" - def p = new PersonEvent(name: "Bad") - try { - p.save() - session.flush() - } catch (e) { - // ignore hibernate related flush errors - } - session.clear() - - then:"The person is never saved" - !PersonEvent.get(p.id) - } - - @Issue('GPMONGODB-262') - void "Test that returning false from beforeDelete evicts the event"() { - when:"a new person is saved" - def p = new PersonEvent(name: "DontDelete") - p.save(flush: true) - session.clear() - p = PersonEvent.get(p.id) - - - then:"The person exists" - p != null - - when:"The beforeDelete event returns false" - p.delete(flush: true) - session.clear() - - then:"The event was cancelled" - PersonEvent.get(p.id) - } - - void "Test modify property before save"() { - given: - session.datastore.mappingContext.addPersistentEntity(ModifyPerson) - def p = new ModifyPerson(name:"Bob").save(flush:true) - session.clear() - - when:"An object is queried by id" - p = ModifyPerson.get(p.id) - - then: "the correct object is returned" - p.name == "Fred" - - when:"An object is queried by the updated value" - p = ModifyPerson.findByName("Fred") - - then:"The correct person is returned" - p.name == "Fred" - } - - void "Test auto time stamping working"() { - - given: - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - sleep(2000) - - p.dateCreated == p.lastUpdated - - when: - p.name = "Wilma" - p.save(flush:true) - - then: - p.dateCreated.before(p.lastUpdated) - } - - void "Test delete events"() { - given: - def p = new PersonEvent() - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - 0 == PersonEvent.STORE.beforeDelete - 0 == PersonEvent.STORE.afterDelete - - when: - p.delete(flush:true) - - then: - 1 == PersonEvent.STORE.beforeDelete - 1 == PersonEvent.STORE.afterDelete - } - - void "Test multi-delete events"() { - given: - def freds = (1..3).collect { - new PersonEvent(name: "Fred$it").save(flush:true) - } - session.clear() - - when: - freds = PersonEvent.findAllByIdInList(freds*.id) - - then: - 3 == freds.size() - 0 == PersonEvent.STORE.beforeDelete - 0 == PersonEvent.STORE.afterDelete - - when: - new DetachedCriteria(PersonEvent).build { - 'in'('id', freds*.id) - }.deleteAll() - session.flush() - - then: - 0 == PersonEvent.count() - 0 == PersonEvent.list().size() - - // removed the below assertions because in the case of batch DML statements neither Hibernate nor JPA triggers delete events for individual entities -// 3 == PersonEvent.STORE.beforeDelete -// 3 == PersonEvent.STORE.afterDelete - } - - void "Test before update event"() { - given: - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - 0 == PersonEvent.STORE.beforeUpdate - 0 == PersonEvent.STORE.afterUpdate - - when: - p.name = "Bob" - p.save(flush:true) - session.clear() - p = PersonEvent.get(p.id) - - then: - "Bob" == p.name - 1 == PersonEvent.STORE.beforeUpdate - 1 == PersonEvent.STORE.afterUpdate - } - - void "Test insert events"() { - given: - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - 0 == PersonEvent.STORE.beforeUpdate - 1 == PersonEvent.STORE.beforeInsert - 0 == PersonEvent.STORE.afterUpdate - 1 == PersonEvent.STORE.afterInsert - - when: - p.name = "Bob" - p.save(flush:true) - session.clear() - p = PersonEvent.get(p.id) - - then: - "Bob" == p.name - 1 == PersonEvent.STORE.beforeUpdate - 1 == PersonEvent.STORE.beforeInsert - 1 == PersonEvent.STORE.afterUpdate - 1 == PersonEvent.STORE.afterInsert - } - - void "Test load events"() { - given: - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - if (!'JpaSession'.equals(session.getClass().simpleName)) { - // JPA doesn't seem to support a pre-load event - 1 == PersonEvent.STORE.beforeLoad - } - 1 == PersonEvent.STORE.afterLoad - } - - void "Test multi-load events"() { - given: - def freds = (1..3).collect { - new PersonEvent(name: "Fred$it").save(flush:true) - } - session.clear() - - when: - freds = PersonEvent.findAllByIdInList(freds*.id) - for(f in freds) {} // just to trigger load - - then: - 3 == freds.size() - if (!'JpaSession'.equals(session.getClass().simpleName)) { - // JPA doesn't seem to support a pre-load event - 3 == PersonEvent.STORE.beforeLoad - } - 3 == PersonEvent.STORE.afterLoad - } - - void "Test bean autowiring"() { - given: - def personService = new Object() - session.datastore.applicationContext.beanFactory.registerSingleton 'personService', personService - - def p = new PersonEvent() - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - personService.is p.personService - } - - - def cleanup() { - session.datastore.applicationContext.beanFactory.destroySingleton 'personService' - } -} - diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/EnumSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/EnumSpec.groovy deleted file mode 100644 index 835638a53..000000000 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/EnumSpec.groovy +++ /dev/null @@ -1,141 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -import org.grails.datastore.mapping.core.Session -import spock.lang.Ignore - -@Ignore -class EnumSpec extends GormDatastoreSpec { - - void "Test save()"() { - given: - - EnumThing t = new EnumThing(name: 'e1', en: TestEnum.V1) - - when: - t.save(failOnError: true) - - then: - t != null - !t.hasErrors() - - when: - t = t.get(t.id) - - then: - t != null - 'e1' == t.name - TestEnum.V1 == t.en - } - - void "Test findBy()"() { - given: - - new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true) - - EnumThing instance1 - EnumThing instance2 - EnumThing instance3 - - when: - instance1 = EnumThing.findByEn(TestEnum.V1) - instance2 = EnumThing.findByEn(TestEnum.V2) - instance3 = EnumThing.findByEn(TestEnum.V3) - - then: - instance1 != null - instance1.en == TestEnum.V1 - - instance2 != null - instance2.en == TestEnum.V2 - - instance3 == null - } - - void "Test findBy() with clearing the session"() { - given: - - new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true, flush: true) - new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true, flush: true) - new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true, flush: true) - session.clear() - - EnumThing instance1 - EnumThing instance2 - EnumThing instance3 - - when: - instance1 = EnumThing.findByEn(TestEnum.V1) - instance2 = EnumThing.findByEn(TestEnum.V2) - instance3 = EnumThing.findByEn(TestEnum.V3) - - then: - instance1 != null - instance1.en == TestEnum.V1 - - instance2 != null - instance2.en == TestEnum.V2 - - instance3 == null - } - - void "Test findAllBy()"() { - given: - - new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true) - - def v1Instances - def v2Instances - def v3Instances - def v12Instances - - when: - v1Instances = EnumThing.findAllByEn(TestEnum.V1) - v2Instances = EnumThing.findAllByEn(TestEnum.V2) - v3Instances = EnumThing.findAllByEn(TestEnum.V3) - v12Instances = EnumThing.findAllByEnInList([TestEnum.V1, TestEnum.V2]) - - then: - v1Instances != null - v1Instances.size() == 2 - v1Instances.every { it.en == TestEnum.V1 } - - v2Instances != null - v2Instances.size() == 1 - v2Instances.every { it.en == TestEnum.V2 } - - v3Instances != null - v3Instances.isEmpty() - - v12Instances != null - v12Instances.size() == 3 - } - - - void "Test countBy()"() { - given: - - new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true) - - def v1Count - def v2Count - def v3Count - - when: - v1Count = EnumThing.countByEn(TestEnum.V1) - v2Count = EnumThing.countByEn(TestEnum.V2) - v3Count = EnumThing.countByEn(TestEnum.V3) - - then: - 2 == v1Count - 1 == v2Count - 0 == v3Count - } -} diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/FindWhereSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/FindWhereSpec.groovy deleted file mode 100644 index 94659ebd5..000000000 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/FindWhereSpec.groovy +++ /dev/null @@ -1,45 +0,0 @@ -package grails.gorm.tests - -/** - * @author stefan armbruster - */ -class FindWhereSpec extends GormDatastoreSpec { - - def setup() { - new Person(firstName: 'Jake', lastName: 'Brown', age: 11).save() - new Person(firstName: 'Zack', lastName: 'Brown', age: 14).save() - new Person(firstName: 'Jeff', lastName: 'Brown', age: 41).save() - new Person(firstName: 'Zack', lastName: 'Galifianakis', age: 41).save(flush: true) - session.clear() - } - - void 'findWhere with simple property'() { - expect: - Person.findWhere(lastName: 'Brown').lastName == 'Brown' - } - - void 'findWhere with multiple properties'() { - expect: - Person.findWhere(lastName: 'Brown', age: 41).firstName == 'Jeff' - } - - void 'findWhere with non matching property'() { - expect: - Person.findWhere(lastName: 'Meyer') == null - } - - void 'findWhere with non-declared property'() { - expect: - Person.findWhere(invalidProperty: 'Brown') == null - } - - void 'findWhere with dynamic property'() { - when: - def property = 'lastName' - then: - Person.findWhere((property): 'Brown').lastName == 'Brown' - } - -} - - diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/JoinCriteriaSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/JoinCriteriaSpec.groovy deleted file mode 100644 index 2250a36a3..000000000 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/JoinCriteriaSpec.groovy +++ /dev/null @@ -1,62 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -class JoinCriteriaSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [AclClass, AclObjectIdentity] - } - - def "check if a criteria join get the expected results"() { - given: - def aclc1 = new AclClass(className:'classname1').save(flush:true) - def aclc2 = new AclClass(className:'classname2').save(flush:true) - - def aclObjId1 = new AclObjectIdentity('aclClass':aclc1, objectId:1L).save(flush:true) - def aclObjId2 = new AclObjectIdentity('aclClass':aclc2, objectId:2L).save(flush:true) - - session.clear() - - when: - def theObjs = AclObjectIdentity.createCriteria().list { - aclClass { eq('className', 'classname2') } - } - - then: - theObjs.size() == 1 - theObjs[0].objectId == 2L - } -} - -@Entity -class AclClass { - Long id - Long version - String className - - @Override - String toString() { - "AclClass id $id, className $className" - } -} - -@Entity -class AclObjectIdentity { - - Long id - Long version - - Long objectId - AclClass aclClass - - static embedded = ['aclClass'] - - @Override - String toString() { - "AclObjectIdentity id $id, aclClass $aclClass.className, objectId $objectId" - } -} - - 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 deleted file mode 100644 index e90f01e78..000000000 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/ManyToManySpec.groovy +++ /dev/null @@ -1,275 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -class ManyToManySpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [Role, User, MBook, MBookworm] - } - - /*def setupSpec() { - new BasicConfigurator().configure() - }*/ - - def "check if manytomany relationships are persistent correctly"() { - setup: - def user = new User(username: 'user1').addToRoles(new Role(role:'role1')) - user.save(flush:true) - session.clear() - - when: - user = User.findByUsername('user1') - - then: - user.roles - 1 == user.roles.size() - user.roles.every { it instanceof Role } - - when: - def role = Role.findByRole('role1') - - then: - role.people - 1 == role.people.size() - role.people.every { it instanceof User } - } - - def "insert multiple instances with many-to-many"() { - - setup: - ['ROLE_USER', 'ROLE_ADMIN'].each { - new Role(role:it).save() - } - - def user = new User(username: 'initial') - user.addToRoles(Role.findByRole('ROLE_ADMIN')) - user.save(flush:true) - session.clear() - - when: - ['user1': ['ROLE_USER'], - 'user2': ['ROLE_ADMIN', 'ROLE_USER']].each { username, roles -> - user = new User(username: username) - roles.each { - user.addToRoles(Role.findByRole(it)) - } - user.save() - } - - session.flush() - session.clear() - - then: - 3 == User.count() - 1 == User.findByUsername('user1').roles.size() - 2 == User.findByUsername('user2').roles.size() - 2 == Role.findByRole('ROLE_USER').people.size() - 2 == Role.findByRole('ROLE_ADMIN').people.size() - } - - def "test if setter on m2m property also updates reverse collection"() { - setup: - def roleAdmin = new Role(role:'ROLE_ADMIN').save() - def roleUser = new Role(role:'ROLE_USER').save() - def roleSpecial = new Role(role:'ROLE_SPECIAL').save() - def user = new User(username: 'user', roles: [roleUser]).save() - session.flush() - session.clear() - - when: - user = User.get(user.id) - roleAdmin = Role.get(roleAdmin.id) - roleUser = Role.get(roleUser.id) - roleSpecial = Role.get(roleSpecial.id) - then: - user.roles.size()==1 - - when: "using setter for a bidi collection" - user.roles = [ roleAdmin, roleUser, roleSpecial ] - session.flush() - session.clear() - user = User.get(user.id) - - then: - user.roles.size() == 3 - user.roles.every { it.people.size()==1 } - - } - - // TODO: this testcase belongs semantically into OneToManySpec - def "check multiple one-to-many relationships of the same type"() { - setup: - def user = new User(username: 'person1') - user.save(flush:true) - session.clear() - - when: "creating a lonely user" - user = User.findByUsername('person1') - - then: "user has no friends and foes" - user - user.friends.size() == 0 - user.foes.size() == 0 - user.bestBuddy == null - - when: "adding some friend and foe" - user.addToFriends(username:'friend1') - user.addToFoes(username:'foe1') - user.save() - session.flush() - session.clear() - user = User.findByUsername('person1') - - then: "friends and foes are found" - user - user.friends.size() == 1 - user.friends.every { it.username =~ /friend\d/ } - user.foes.size() == 1 - user.foes.every { it.username =~ /foe\d/ } - user.bestBuddy == null - - when: "setting bestbuddy" - user.bestBuddy = new User(username:'bestBuddy') - user.save() - session.flush() - session.clear() - user = User.findByUsername('person1') - - then: "bestBuddy is there" - user.bestBuddy.username == 'bestBuddy' - - and: 'friends and foes are not modified' - user.friends.size() == 1 - user.friends.every { it.username =~ /friend\d/ } - user.foes.size() == 1 - user.foes.every { it.username =~ /foe\d/ } - - } - - def "test if addToXXX modifies the nodespace even if it's the only operation in a session"() { - when: - def friend = new User(username: 'friend').save() - def user = new User(username: 'user').save(flush:true) - user.addToFriends(friend) - session.flush() - session.clear() - user = User.get(user.id) - - then: - user.friends.size()==1 - - } - - def "should two one-to-one relationships be independent"() { - - setup: - def randy = new MBookworm(name: 'Randy', favoriteBook: null) - randy.save(failOnError: true) - def encyclopedia = new MBook(name: 'Encyclopedia Volume 1', checkedOutBy: randy) - encyclopedia.save(failOnError: true) - session.flush() - session.clear() - - when: - randy = MBookworm.findByName('Randy') - - then: - randy.favoriteBook==null - - } - -} - -@Entity -class User { - Long id - Long version - String username - User bestBuddy - Set roles = [] - Set friends = [] - Set foes = [] - - boolean equals(other) { - if (!(other instanceof User)) { - return false - } - other?.username == username - } - - int hashCode() { - username ? username.hashCode() : 0 - } - - static hasMany = [ roles: Role, friends: User, foes: User ] - static mappedBy = [ bestBuddy:null, friends: null, foes: null ] - static belongsTo = Role - - static constraints = { - bestBuddy nullable:true - } -} - -@Entity -class Role { - Long id - Long version - String role - Set people = [] - - boolean equals(other) { - if ((other==null) || !(other instanceof Role)) { - return false - } - other?.role == role - } - - int hashCode() { - role ? role.hashCode() : 0 - } - - static hasMany = [people: User] - - static constraints = { - role(blank: false, unique: true) - } -} - -@Entity -class MBook implements Serializable { - Long id - Long version - - String name - MBookworm checkedOutBy - - static constraints = { - name(nullable: false) - checkedOutBy(nullable: false) - } - - public String toString() { - return "Book [name: ${this.name}, checkedOutBy: ${this.checkedOutBy?.name}]" - } - -} - -@Entity -class MBookworm implements Serializable { - Long id - Long version - - String name - MBook favoriteBook - - static constraints = { - name(nullable: false, blank: false) - favoriteBook(nullable: true) - } - - public String toString() { - return "Bookworm: [name: ${this.name}, favoriteBook: ${this.favoriteBook?.name}]" - } -} 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 deleted file mode 100644 index 24a5138dc..000000000 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/MiscSpec.groovy +++ /dev/null @@ -1,415 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity -import groovy.beans.Bindable -import groovyx.gpars.GParsPool -import org.grails.datastore.gorm.neo4j.GrailsRelationshipTypes -import org.neo4j.graphdb.Direction -import org.neo4j.graphdb.Node -import org.neo4j.helpers.collection.IteratorUtil -import spock.lang.Ignore -import spock.lang.Issue - -/** - * some more unrelated testcases, in more belong together logically, consider refactoring them into a seperate spec - */ -class MiscSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [ Club, Team, Tournament, User, Role ] - } - - def "test object identity, see if cache is being used"() { - setup: - new User(username: 'user1').save() - new User(username: 'user2').save(flush:true) - session.clear() - - when: "retrieve the same object twice" - def user = User.findByUsername('user1') - def user2 = User.findByUsername('user1') - - then: "see if the same instance is returned" - user.is(user2) - 2 == User.count() - user in User.list() - } - - def "test object identity in relationships"() { - setup: - def user = new User(username: 'user1') - user.addToRoles new Role(role: 'role1') - user.addToRoles new Role(role: 'role2') - user.save(flush:true) - session.clear() - - when: - user = User.findByUsername('user1') - def role = Role.findByRole('role1') - - then: - role in user.roles - } - - def "test unique constraint"() { - setup: - def role1 = new Role(role: 'role') - role1.save(flush:true) - def result = new Role(role:'role').save(flush:true) - session.clear() - - expect: - Role.findAllByRole('role').size() == 1 - - } - - void "Test modification of a persistent instance with explicit save"() { - given: - def t = new TestEntity(name:"Bob") - t.save(flush:true) - session.clear() - when: - t = TestEntity.get(t.id) - t.name = "Sam" - t.save() // explicit save necessary - session.flush() - session.clear() - then: - TestEntity.findByName("Bob") == null - TestEntity.findByName("Sam") != null - } - - void "test if addtoXXXX gets persisted correctly"() { - given: - new PlantCategory(name: 'category').save(flush:true) - session.clear() - - when: - def category = PlantCategory.findByName('category') - session.clear() - - category = PlantCategory.get(category.id) - def plant1 = new Plant(name:'plant1') - category.addToPlants(plant1).save() - category.save(flush:true) - session.clear() - category = PlantCategory.get(category.id) - - then: - category - category.name =='category' - category.plants.size() == 1 - category.plants*.name == ['plant1'] - - } - - // this test belongs semantically to grails.gorm.tests.CircularOneToManySpec but will fail in some existing - // implementations, that's why it's located here - void "test circular one-to-many using addToXX"() { - setup: - def user1 = new User(username: 'user1') - def user2 = new User(username: 'user2') - user1.addToFriends( user2) - user2.addToFriends( user1) - user1.save() - user2.save() - session.flush() - session.clear() - - when: - user1 = User.get(user1.id) - user2 = User.get(user2.id) - - then: - new ArrayList(user1.friends) == [ user2 ] - new ArrayList(user2.friends) == [ user1 ] - } - - void "test multiple relations with the same name"() { - setup: - def team = new Team(name: 'team') - def club = new Club(name: 'club') - club.addToTeams(team).save() - def tournament = new Tournament(name:'tournament') - tournament.addToTeams(team).save(flush:true) - session.clear() - - when: - tournament = Tournament.get(tournament.id) - - then: - tournament.teams.size() == 1 - tournament.teams*.name == ['team'] - tournament.teams[0].club.name == 'club' - } - - // TODO: more tests for indexing are required, add a IndexSearchSpec.groovy - void "test indexing"() { - setup: - def task1 = new Task(name: 'task1') - task1.save() - new Task(name: 'task2').save(flush: true) - session.clear() - def index = session.datastore.indexManager.nodeAutoIndexer.autoIndex - - expect: "run native neo4j index query" - index.get('name', 'task1').single == task1.node - - and: "a dynamic finder works" - Task.findAllByName('task1')*.id == [task1.id] - - } - - void "verify correct behaviour of version incrementing"() { - setup: - def club = new Club(name: 'club') - club.save(flush: true) - session.clear() - - expect: - club.version == 0 - - when: - club = Club.get(club.id) - - then: - club.version == 0 - - when: - session.flush() - - then: - club.version == 0 - } - - def "verify concurrent adding does not cause LockingExceptions"() { - when: - GParsPool.withPool(numberOfThreads) { - (1..numberOfTeams).eachParallel { counter -> - Team.withNewTransaction { - new Team(name: "Team $counter").save(failOnError: true) - } - } - } - Node subReferenceNode = session.datastore.subReferenceNodes[Team.class.name] - - then: "correct number of teams has been created" - Team.count() == numberOfTeams - - and: "the number of subsubreferenceNodes is correct" - subReferenceNode.getRelationships(GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.OUTGOING).iterator().size() == numberOfThreads - - where: - numberOfThreads | numberOfTeams | numberOfSubSubReferenceNodes - 1 | 20 | 1 - 2 | 20 | 2 - 4 | 20 | 4 - 8 | 20 | 8 - - } - - @Ignore - def "do peformance tests"() { - when: - def start = System.currentTimeMillis() - Team.withNewTransaction { - for (i in 1..10000) { - new Team(name: "Team $i").save() - } - } - def delta = System.currentTimeMillis() - start - println "create 10000 in $delta msec" - - then: - delta > 0 - - when: - start = System.currentTimeMillis() - def count = Team.count() - delta = System.currentTimeMillis() - start - println "count is $count, delta $delta" - - then: - delta > 0 - - } - - @Ignore - def "manual perf test"() { - when: - - Node subRef - Team.withNewTransaction { - subRef = session.nativeInterface.createNode() - } - def start = System.currentTimeMillis() - Team.withNewTransaction { - for (i in 1..10000) { - Node node = session.nativeInterface.createNode() - node.setProperty("name", "Team $i".toString()) - subRef.createRelationshipTo(node, GrailsRelationshipTypes.INSTANCE) - } - } - def delta = System.currentTimeMillis() - start - println "create 10000 in $delta msec" - - then: - delta > 0 - - when: - start = System.currentTimeMillis() - def count = IteratorUtil.count((Iterator)subRef.getRelationships(Direction.OUTGOING, GrailsRelationshipTypes.INSTANCE)) - delta = System.currentTimeMillis() - start - println "count is $count, delta $delta" - - then: - delta > 0 - - } - - @Issue("https://github.com/SpringSource/grails-data-mapping/issues/52") - def "check that date properties are stored natively as longs"() { - when: - def pet = new Pet(birthDate: new Date()).save(flush: true) - then: - pet.node.getProperty("birthDate") instanceof Long - } - - @Issue("https://github.com/SpringSource/grails-data-mapping/issues/52") - def "verify backward compatibility, check that date properties stored as string can be read"() { - when: "create a instance with a date property and manually assign a string to it" - def date = new Date() - def pet = new Pet(birthDate: date).save(flush: true) - then: - pet.node.getProperty("birthDate") instanceof Long - - when: - pet.node.setProperty("birthDate", date.time.toString()) - pet = Pet.get(pet.id) - then: "the string stored date gets parsed correctly" - pet.birthDate == date - } - - def "byte arrays work as domain class properties"() { - when: - def team = new Team(name: 'name', binaryData: 'abc'.bytes) - team.save(flush: true) - def value = team.node.getProperty('binaryData') - then: - value.class == byte[].class - value == 'abc'.bytes - } - - @Issue("https://github.com/SpringSource/grails-data-mapping/issues/34") - def "domain classes use propertyChangeListener when possible"() { - expect: "Team is @Bindable, so propertyChangeListeners are used" - new Team().respondsTo("addPropertyChangeListener") - and: "User does not use @Bindable" - !new User().respondsTo("addPropertyChangeListener") - when: "force evaluation if class supports propertyChangeListeners" - new Team(name: 'team1').save() - then: - session.memoizePropertyChangeListener[Team.class] == true - } - - def "serialization should work with proxies"() { - setup: - Team team = new Team(name: "team", - club: new Club(name: 'club') - ).save(flush: true) - session.clear() - team = Team.get(team.id) - - def bos = new ByteArrayOutputStream() - - bos.withObjectOutputStream { - it.writeObject(team) - } - - when: - Team deserializedTeam = new ByteArrayInputStream(bos.toByteArray()).withObjectInputStream { - it.readObject() - } - - then: - deserializedTeam instanceof Team -// team.club.metaClass.getMetaMethod("isProxy", null) != null - team.name == deserializedTeam.name - team.club.name == deserializedTeam.club.name - } - - def "operations on deserialized instance with hasMany works"() { - setup: - Tournament tournament = new Tournament(name: "tournament", - teams: [new Team(name: 'team1'), new Team(name: 'team2')] - ).save(flush: true) - session.clear() - tournament = Tournament.get(tournament.id) - - def bos = new ByteArrayOutputStream() - bos.withObjectOutputStream { - it.writeObject(tournament) - } - Tournament deserializedTournament = new ByteArrayInputStream(bos.toByteArray()).withObjectInputStream { - it.readObject() - } - - when: - def firstTeam = deserializedTournament.teams[0] - deserializedTournament.teams.remove(firstTeam) - session.flush() - - tournament = Tournament.get(tournament.id) - - then: - deserializedTournament.teams.size()==1 - tournament.teams.size()==1 - - } - - def "null values on complex properties work on save"() { - when: - def c = new CommonTypes() - - then: - c.save(flush: true) - } -} - -@Entity -class Tournament implements Serializable { - Long id - Long version - String name - List teams - static hasMany = [teams: Team ] - static mapping = { - teams(lazy: true) - } -} - -@Bindable -@Entity -class Team implements Serializable { - Long id - Long version - String name - Club club - byte[] binaryData -} - -@Entity -class Club implements Serializable { - Long id - Long version - String name - List teams - static hasMany = [teams: Team ] - - // TODO: maybe refactor this into a AST - protected Object writeReplace() - throws ObjectStreamException { - return get(id) - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy deleted file mode 100644 index fd130b773..000000000 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy +++ /dev/null @@ -1,135 +0,0 @@ -package grails.gorm.tests - -import org.grails.datastore.mapping.core.OptimisticLockingException - -import spock.lang.Ignore -import grails.persistence.Entity - -/** - * @author Burt Beckwith - */ -class OptimisticLockingSpec extends GormDatastoreSpec { - - void "Test versioning"() { - - given: - def o = new OptLockVersioned(name: 'locked') - - when: - o.save flush: true - - then: - o.version == 0 - - when: - session.clear() - o = OptLockVersioned.get(o.id) - o.name = 'Fred' - o.save flush: true - - then: - o.version == 1 - - when: - session.clear() - o = OptLockVersioned.get(o.id) - - then: - o.name == 'Fred' - o.version == 1 - } - - @Ignore("fails due to neo4j's flat transaction model") - void "Test optimistic locking"() { - - given: - def o = new OptLockVersioned(name: 'locked').save(flush: true) - session.clear() - - when: - o = OptLockVersioned.get(o.id) - - Thread.start { - OptLockVersioned.withNewSession { s -> - def reloaded = OptLockVersioned.get(o.id) - reloaded.name += ' in new session' - reloaded.save(flush: true) - } - }.join() - sleep 2000 // heisenbug - - o.name += ' in main session' - def ex - try { - o.save(flush: true) - } - catch (e) { - ex = e - e.printStackTrace() - } - - session.clear() - o = OptLockVersioned.get(o.id) - - then: - ex instanceof OptimisticLockingException - o.version == 1 - o.name == 'locked in new session' - } - - @Ignore("fails due to neo4j's flat transaction model") - void "Test optimistic locking disabled with 'version false'"() { - - given: - def o = new OptLockNotVersioned(name: 'locked').save(flush: true) - session.clear() - - when: - o = OptLockNotVersioned.get(o.id) - - Thread.start { - OptLockNotVersioned.withNewSession { s -> - def reloaded = OptLockNotVersioned.get(o.id) - reloaded.name += ' in new session' - reloaded.save(flush: true) - } - }.join() - sleep 2000 // heisenbug - - o.name += ' in main session' - def ex - try { - o.save(flush: true) - } - catch (e) { - ex = e - e.printStackTrace() - } - - session.clear() - o = OptLockNotVersioned.get(o.id) - - then: - ex == null - o.name == 'locked in main session' - } -} - -@Entity -class OptLockVersioned implements Serializable { - Long id - Long version - - String name -} - -@Entity -class OptLockNotVersioned implements Serializable { - Long id - - String name - - static mapping = { - version false - } -} diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy deleted file mode 100644 index 6df695c79..000000000 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.PagedResultList -import spock.lang.Ignore - -/** - * - */ -class PagedResultSpec extends GormDatastoreSpec{ - - - void "Test that a paged result list is returned from the list() method with pagination params"() { - given:"Some people" - createPeople() - - when:"The list method is used with pagination params" - def results = Person.list(offset:2, max:2) - - then:"You get a paged result list back" - results instanceof PagedResultList - results.size() == 2 - results[0].firstName == "Bart" - results[1].firstName == "Lisa" - results.totalCount == 6 - - } - - @Ignore("temporary disabled due to undefined sorting order") - void "Test that a paged result list is returned from the critera with pagination params"() { - given:"Some people" - createPeople() - - when:"The list method is used with pagination params" - def results = Person.createCriteria().list(offset:1, max:2) { - eq 'lastName', 'Simpson' - } - - then:"You get a paged result list back" - results instanceof PagedResultList - results.size() == 2 - results[0].firstName == "Marge" - results[1].firstName == "Bart" - results.totalCount == 4 - - } - - - protected def createPeople() { - new Person(firstName: "Homer", lastName: "Simpson", age:45).save() - new Person(firstName: "Marge", lastName: "Simpson", age:40).save() - new Person(firstName: "Bart", lastName: "Simpson", age:9).save() - new Person(firstName: "Lisa", lastName: "Simpson", age:7).save() - new Person(firstName: "Barney", lastName: "Rubble", age:35).save() - new Person(firstName: "Fred", lastName: "Flinstone", age:41).save() - } - -} diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/WithTransactionSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/WithTransactionSpec.groovy deleted file mode 100644 index a45293566..000000000 --- a/grails-datastore-gorm-neo4j/src/test/groovy/grails/gorm/tests/WithTransactionSpec.groovy +++ /dev/null @@ -1,71 +0,0 @@ -package grails.gorm.tests - -import spock.lang.Ignore - -/** - * Transaction tests. - */ -class WithTransactionSpec extends GormDatastoreSpec { - - void "Test save() with transaction"() { - given: - TestEntity.withTransaction { - new TestEntity(name:"Bob", age:50, child:new ChildEntity(name:"Bob Child")).save() - new TestEntity(name:"Fred", age:45, child:new ChildEntity(name:"Fred Child")).save() - } - - when: - int count = TestEntity.count() -// def results = TestEntity.list(sort:"name") // TODO this fails but doesn't appear to be tx-related, so manually sorting - def results = TestEntity.list().sort { it.name } - - then: - 2 == count - "Bob" == results[0].name - "Fred" == results[1].name - } - - @Ignore - void "Test rollback transaction"() { - given: - TestEntity.withNewTransaction { status -> - new TestEntity(name:"Bob", age:50, child:new ChildEntity(name:"Bob Child")).save() - status.setRollbackOnly() - new TestEntity(name:"Fred", age:45, child:new ChildEntity(name:"Fred Child")).save() - } - - when: - int count = TestEntity.count() - def results = TestEntity.list() - - then: - count == 0 - results.size() == 0 - } - - @Ignore - void "Test rollback transaction with Exception"() { - given: - def ex - try { - TestEntity.withNewTransaction { status -> - new TestEntity(name:"Bob", age:50, child:new ChildEntity(name:"Bob Child")).save() - throw new RuntimeException("bad") - new TestEntity(name:"Fred", age:45, child:new ChildEntity(name:"Fred Child")).save() - } - } - catch (e) { - ex = e - } - - when: - int count = TestEntity.count() - def results = TestEntity.list() - - then: - count == 0 - results.size() == 0 - ex instanceof RuntimeException - ex.message == 'bad' - } -} 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 deleted file mode 100644 index c18a41f62..000000000 --- a/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ /dev/null @@ -1,126 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.Role -import org.codehaus.groovy.grails.commons.DefaultGrailsApplication -import org.codehaus.groovy.grails.validation.ConstrainedProperty -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.Neo4jDatastore -import org.grails.datastore.gorm.neo4j.Neo4jGormEnhancer -import org.grails.datastore.gorm.neo4j.constraints.UniqueConstraint -import org.grails.datastore.gorm.proxy.GroovyProxyFactory -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager -import org.neo4j.test.ImpermanentGraphDatabase -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.context.support.GenericApplicationContext -import org.springframework.util.StringUtils -import org.springframework.validation.Errors -import org.springframework.validation.Validator -import org.neo4j.rest.graphdb.RestGraphDatabase -import org.neo4j.rest.graphdb.LocalTestServer -import org.neo4j.rest.graphdb.util.Config - -class Setup { - - static HOST = "localhost" - static PORT = 7473 - protected final Logger log = LoggerFactory.getLogger(getClass()) - - static datastore - static transaction - static server - static graphDb - - static destroy() { - transaction.failure() - transaction.finish() - graphDb.shutdown() - server?.stop() - } - - static Session setup(classes) { - - def ctx = new GenericApplicationContext() - ctx.refresh() - - if (System.properties.get("gorm_neo4j_test_use_rest")) { - System.setProperty(Config.CONFIG_BATCH_TRANSACTION,"false") // TODO: remove when support for batch has been finished - //System.setProperty(Config.CONFIG_LOG_REQUESTS,"true") // enable for verbose request/response logging - server = new LocalTestServer(HOST, PORT).withPropertiesFile("neo4j-server.properties"); - server.start() - graphDb = new RestGraphDatabase("http://localhost:7473/db/data/") - } else { - graphDb = new ImpermanentGraphDatabase() - } - - datastore = new Neo4jDatastore(graphDatabaseService: graphDb, applicationContext: ctx) - datastore.mappingContext.proxyFactory = new GroovyProxyFactory() - - /*Neo4jSession.metaClass.invokeMethod = { String name, args -> - def metaMethod = Neo4jSession.metaClass.getMetaMethod(name, args) - if (metaMethod==null) { - metaMethod = Neo4jSession.metaClass.methods.find {it.name==name} - } - log.warn "START $name ($args)" - try { - metaMethod.invoke(delegate, args) - - } finally { - log.warn "DONE $name" - } - }*/ - - //ConstrainedProperty.registerNewConstraint(UniqueConstraint.UNIQUE_CONSTRAINT, UniqueConstraint) - - for (cls in classes) { - datastore.mappingContext.addPersistentEntity(cls) - } - - PersistentEntity entity = datastore.mappingContext.persistentEntities.find { PersistentEntity e -> e.name.contains("TestEntity")} - - datastore.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 = datastore.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) - } - - def enhancer = new Neo4jGormEnhancer(datastore, new DatastoreTransactionManager(datastore: datastore)) - enhancer.enhance() - - datastore.afterPropertiesSet() - - datastore.mappingContext.addMappingContextListener({ e -> - enhancer.enhance e - } as MappingContext.Listener) - - - datastore.applicationContext.addApplicationListener new DomainEventListener(datastore) - datastore.applicationContext.addApplicationListener new AutoTimestampEventListener(datastore) - - transaction = graphDb.beginTx() - datastore.connect() - } -} diff --git a/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/neo4j/ApiExtensionsSpec.groovy b/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/neo4j/ApiExtensionsSpec.groovy deleted file mode 100644 index a2b1e8fd7..000000000 --- a/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/neo4j/ApiExtensionsSpec.groovy +++ /dev/null @@ -1,272 +0,0 @@ -package org.grails.datastore.gorm.neo4j - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person -import grails.gorm.tests.Pet - -import org.neo4j.graphdb.Direction -import org.neo4j.graphdb.ReturnableEvaluator -import org.neo4j.graphdb.StopEvaluator -import org.neo4j.graphdb.TraversalPosition -import org.neo4j.graphdb.Traverser -import org.neo4j.graphdb.Node -import spock.lang.IgnoreRest -import grails.gorm.tests.PetType -import org.neo4j.graphdb.GraphDatabaseService -import org.neo4j.tooling.GlobalGraphOperations -import org.neo4j.visualization.asciidoc.AsciidocHelper -import org.neo4j.graphdb.traversal.TraversalDescription -import org.neo4j.kernel.Traversal -import org.neo4j.graphdb.Path - -/** - * check the traverser extension - */ -class ApiExtensionsSpec extends GormDatastoreSpec { - - def "test static traversing"() { - given: - new Person(lastName: "person1").save() - new Person(lastName: "person2").save() - - when: - def traverserResult = Person.traverseStatic(Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH, GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.BOTH) - def size = traverserResult.size() - - then: - - size == Person.traverseStatic(StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH, GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.BOTH).size() - - size+1 == Person.traverseStatic(Traverser.Order.BREADTH_FIRST, - { TraversalPosition p -> false }, - { TraversalPosition p -> true }, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH, GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.BOTH).size() - - size+1 == Person.traverseStatic( - { TraversalPosition p -> false }, - { TraversalPosition p -> true }, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH, GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.BOTH).size() - - size+1 == Person.traverseStatic( - { TraversalPosition p -> false }, - { TraversalPosition p -> true } ).size() - - //println AsciidocHelper.createGraphViz("title", session.nativeInterface, "abc"); - - /*Node subReferenceNode = ((Neo4jDatastore)session.datastore).subReferenceNodes[Person.class.name] - Traversal.description().depthFirst() - .relationships(GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.OUTGOING) - .relationships(GrailsRelationshipTypes.INSTANCE, Direction.OUTGOING) - .traverse(subReferenceNode).each { Path p -> - println p - }*/ - - Person.count() == Person.traverseStatic( - { return false }, - { TraversalPosition p -> return p.currentNode().getProperty("__type__", null) == Person.name }, - GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.OUTGOING, - GrailsRelationshipTypes.INSTANCE, Direction.OUTGOING, - ).size() - - // +2: referenceNode + self (aka subreferenceNode) - Person.count()+2 == Person.traverseStatic( - { TraversalPosition p -> false }, - { TraversalPosition p -> true }, - GrailsRelationshipTypes.SUBREFERENCE, Direction.OUTGOING, - GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.OUTGOING, - GrailsRelationshipTypes.INSTANCE, Direction.OUTGOING, - ).size() - } - - def "test instance based traversing"() { - given: - def person = new Person(lastName: "person1") - person.save() - new Person(lastName: "person2").save() - - when: - def traverserResult = person.traverse(Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH) - def size = traverserResult.size() - - then: - - size == person.traverse(StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH).size() - - size+1 == person.traverse(Traverser.Order.BREADTH_FIRST, - { TraversalPosition p -> false }, - { TraversalPosition p -> true }, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH).size() - - size+1 == person.traverse( - { TraversalPosition p -> false }, - { TraversalPosition p -> true }, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH).size() - - size+1 == person.traverse( - { TraversalPosition p -> false }, - { TraversalPosition p -> true } ).size() - - Person.count() == person.traverse( - { TraversalPosition p -> false }, - { TraversalPosition p -> p.currentNode().getProperty("__type__",null) == Person.name } ).size() - - 1 == person.traverse( - { TraversalPosition p -> true }, - { TraversalPosition p -> true } ).size() - } - - def "test createInstanceForNode"() { - given: - def person = new Person(lastName: 'person1') - person.save() - def pet = new Pet(name: 'pet') - person.save() - - when: "retrieve a instance only by id" - def instance = Pet.createInstanceForNode(person.id) - - then: - instance instanceof Person - instance.lastName == 'person1' - - when: "look up non-existing id" - instance = Pet.createInstanceForNode(999) - - then: - instance == null - } - - def "test handling of non-declared properties"() { - when: - def person = new Person(lastName:'person1').save() - person['notDeclaredProperty'] = 'someValue' // n.b. the 'dot' notation is not valid for undeclared properties - person['emptyArray'] = [] - person['someIntArray'] = [1,2,3] - person['someStringArray'] = ['a', 'b', 'c'] - person['someDoubleArray'] = [0.9, 1.0, 1.1] - session.flush() - session.clear() - person = Person.get(person.id) - - then: - person['notDeclaredProperty'] == 'someValue' - person['lastName'] == 'person1' // declared properties are also available via map semantics - person['someIntArray'] == [1,2,3] - person['someStringArray'] == ['a', 'b', 'c'] - person['someDoubleArray'] == [0.9, 1.0, 1.1] - } - - def "test handling of non-declared properties using dot notation"() { - setup: - def person = new Person(lastName:'person1').save(flush:true) - session.clear() - person = Person.load(person.id) - when: - person.notDeclaredProperty = 'someValue' // n.b. the 'dot' notation is not valid for undeclared properties - person.emptyArray = [] - person.someIntArray = [1,2,3] - person.someStringArray = ['a', 'b', 'c'] - person.someDoubleArray= [0.9, 1.0, 1.1] - session.flush() - session.clear() - person = Person.get(person.id) - - then: - person.notDeclaredProperty == 'someValue' - person.lastName == 'person1' // declared properties are also available via map semantics - person.someIntArray == [1,2,3] - person.someStringArray == ['a', 'b', 'c'] - person.emptyArray == [] - person.someDoubleArray == [0.9, 1.0, 1.1] - } - - def "test null values on dynamic properties"() { - setup: - def person = new Person(lastName: 'person1').save(flush: true) - session.clear() - person = Person.load(person.id) - when: - person.notDeclaredProperty = null - session.flush() - session.clear() - person = Person.get(person.id) - - then: - person.notDeclaredProperty == null - - when: - person.notDeclaredProperty = 'abc' - session.flush() - session.clear() - person = Person.get(person.id) - - then: - person.notDeclaredProperty == 'abc' - - when: - person.notDeclaredProperty = null - session.flush() - session.clear() - person = Person.get(person.id) - - then: - person.notDeclaredProperty == null - - - } - - - def "test handling of non-declared properties on transient instance"() { - when: - def person = new Person(lastName:'person1') - person['notDeclaredProperty'] = 'someValue' - - then: - thrown(IllegalStateException) - } - - def "test handling of non-declared properties that do not match valid types in neo4j"() { - when: - def person = new Person(lastName:'person1') - person['notDeclaredProperty'] = new Date() - - then: - thrown(IllegalStateException) - } - - def "test cypher queries"() { - setup: - new Person(lastName:'person1').save() - new Person(lastName:'person2').save() - session.flush() - session.clear() - - when: - def result = Person.cypherStatic("start n=node({this}) match n-[:SUBSUBREFERENCE]->subRef-[:INSTANCE]->m where m.lastName='person1' return m") - - then: - result.iterator().size()==1 - - } - - def "test instance based cypher query"() { - setup: - def person = new Person(firstName: "Bob", lastName: "Builder") - def petType = new PetType(name: "snake") - def pet = new Pet(name: "Fred", type: petType, owner: person) - person.addToPets(pet) - person.save(flush: true) - session.clear() - - when: - def result = person.cypher("start n=node({this}) match n-[:pets]->m return m") - - then: - result.iterator().size() == 1 - } - -} 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 deleted file mode 100644 index d485169f9..000000000 --- a/grails-datastore-gorm-neo4j/src/test/groovy/org/grails/datastore/gorm/neo4j/Neo4jSuite.groovy +++ /dev/null @@ -1,60 +0,0 @@ -package org.grails.datastore.gorm.neo4j - -import org.junit.runner.RunWith -import org.junit.runners.Suite -import org.junit.runners.Suite.SuiteClasses -import grails.gorm.tests.* - -@RunWith(Suite) -@SuiteClasses([ - -AttachMethodSpec, -CircularOneToManySpec, -CommonTypesPersistenceSpec, -ConstraintsSpec, -CriteriaBuilderSpec, -CrudOperationsSpec, -DeleteAllSpec, -DetachedCriteriaSpec, -DomainEventsSpec, -EnumSpec, -FindByExampleSpec, -FindByMethodSpec, -FindOrCreateWhereSpec, -FindOrSaveWhereSpec, -FirstAndLastMethodSpec, -GormEnhancerSpec, -GroovyProxySpec, -InheritanceSpec, -ListOrderBySpec, -NamedQuerySpec, -NegationSpec, -OneToManySpec, -OneToOneSpec, -OptimisticLockingSpec, -OrderBySpec, -PagedResultSpec, -PersistenceEventListenerSpec, -PropertyComparisonQuerySpec, -ProxyLoadingSpec, -QueryAfterPropertyChangeSpec, -QueryByAssociationSpec, -QueryByNullSpec, -RangeQuerySpec, -SaveAllSpec, -SizeQuerySpec, -UniqueConstraintSpec, -UpdateWithProxyPresentSpec, -ValidationSpec, -WithTransactionSpec, - -// non TCK - specs, locally to neo4j -FindWhereSpec, -JoinCriteriaSpec, -ManyToManySpec, -MiscSpec, -ApiExtensionsSpec, - -]) -class Neo4jSuite { -} diff --git a/grails-datastore-gorm-neo4j/src/test/resources/neo4j-server.properties b/grails-datastore-gorm-neo4j/src/test/resources/neo4j-server.properties deleted file mode 100644 index 87c2f57db..000000000 --- a/grails-datastore-gorm-neo4j/src/test/resources/neo4j-server.properties +++ /dev/null @@ -1,12 +0,0 @@ -org.neo4j.server.database.location=neo4j-home/data -#org.neo4j.server.bundledir=neo4j-home/bundles -#org.neo4j.webserver.port=7474 -# -#org.neo4j.server.thirdparty_jaxrs_classes=org.neo4j.rest.graphdb.extension=/test -#org.neo4j.server.thirdparty.delete.key=secret-key -# -#org.neo4j.server.webadmin.rrdb.location=neo4j-home/rrd -#org.neo4j.server.webadmin.data.uri=/db/data/ -#org.neo4j.server.webadmin.management.uri=/db/manage/ -# -#org.neo4j.export.basepath=neo4j-home/export diff --git a/grails-datastore-gorm-plugin-support/build.gradle b/grails-datastore-gorm-plugin-support/build.gradle deleted file mode 100644 index 3d082ac46..000000000 --- a/grails-datastore-gorm-plugin-support/build.gradle +++ /dev/null @@ -1,16 +0,0 @@ -dependencies { - - compile project(":grails-datastore-gorm") - compile project(":grails-datastore-web") - compile "org.grails:grails-core:$grailsVersion", { - transitive = false - } - compile("org.grails:grails-bootstrap:$grailsVersion") { - transitive = false - } - - //testRuntime "org.grails:grails-web:$grailsVersion" - testRuntime 'javax.servlet:javax.servlet-api:3.0.1' - - testCompile project(":grails-datastore-gorm-test") -} 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 deleted file mode 100644 index d6cb2baf3..000000000 --- a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/AggregatePersistenceContextInterceptor.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2011 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.plugin.support; - -import java.util.List; - -import org.codehaus.groovy.grails.support.PersistenceContextInterceptor; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -public class AggregatePersistenceContextInterceptor implements PersistenceContextInterceptor { - - private final List interceptors; - - /** - * Constructor. - * @param interceptors the real interceptors - */ - public AggregatePersistenceContextInterceptor(final List interceptors) { - this.interceptors = interceptors; - } - - public boolean isOpen() { - for (PersistenceContextInterceptor interceptor : interceptors) { - if (interceptor.isOpen()) { - // true at least one is true - return true; - } - } - return false; - } - - public void reconnect() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.reconnect(); - } - } - - public void destroy() { - for (PersistenceContextInterceptor interceptor : interceptors) { - if (interceptor.isOpen()) { - interceptor.destroy(); - } - } - } - - public void clear() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.clear(); - } - } - - public void disconnect() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.disconnect(); - } - } - - public void flush() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.flush(); - } - } - - public void init() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.init(); - } - } - - public void setReadOnly() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.setReadOnly(); - } - } - - public void setReadWrite() { - for (PersistenceContextInterceptor interceptor : interceptors) { - interceptor.setReadWrite(); - } - } -} diff --git a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/ApplicationContextConfigurer.groovy b/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/ApplicationContextConfigurer.groovy deleted file mode 100644 index e238ccccf..000000000 --- a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/ApplicationContextConfigurer.groovy +++ /dev/null @@ -1,41 +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.plugin.support - -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.mapping.core.Datastore -import org.springframework.context.ConfigurableApplicationContext - -/** - * Common logic for the configuration of the ApplicationContext. - * - * @author Graeme Rocher - * @since 2.0 - */ -class ApplicationContextConfigurer { - - String datastoreType - - ApplicationContextConfigurer(String datastoreType) { - this.datastoreType = datastoreType - } - - void configure(ConfigurableApplicationContext ctx) { - final datastore = ctx.getBean("${datastoreType.toLowerCase()}Datastore", Datastore) - ctx.addApplicationListener new DomainEventListener(datastore) - ctx.addApplicationListener new AutoTimestampEventListener(datastore) - } -} diff --git a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/DynamicMethodsConfigurer.groovy b/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/DynamicMethodsConfigurer.groovy deleted file mode 100644 index e6a2e9dce..000000000 --- a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/DynamicMethodsConfigurer.groovy +++ /dev/null @@ -1,94 +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.plugin.support - -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.utils.InstanceProxy -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher -import org.springframework.transaction.PlatformTransactionManager - -/** - * Utility class for use by plugins in configuration of dynamic methods. - * Subclasses should provide the implementation of getDatastoreType and - * override protected methods to configure behavior. - * - * @author Graeme Rocher - * @since 1.0 - */ -abstract class DynamicMethodsConfigurer { - - Datastore datastore - PlatformTransactionManager transactionManager - - DynamicMethodsConfigurer(Datastore datastore, PlatformTransactionManager transactionManager) { - this.datastore = datastore - this.transactionManager = transactionManager - } - - abstract String getDatastoreType() - - boolean hasExistingDatastore = false - boolean failOnError = false - - void configure() { - def enhancer = createEnhancer() - - String type = getDatastoreType() - String typeLower = type.toLowerCase() - - for (entity in datastore.mappingContext.persistentEntities) { - def cls = entity.javaClass - def cpf = ClassPropertyFetcher.forClass(cls) - def mappedWith = cpf.getStaticPropertyValue(GrailsDomainClassProperty.MAPPING_STRATEGY, String) - if (hasExistingDatastore) { - if (mappedWith == typeLower) { - enhancer.enhance(entity) - } - else { - def staticApi = createGormStaticApi(cls, enhancer.getFinders()) - def instanceApi = createGormInstanceApi(cls) - cls.metaClass.static."get$type" = {-> staticApi } - cls.metaClass."get$type" = {-> new InstanceProxy(instance:delegate, target:instanceApi) } - } - } - else { - if (mappedWith == typeLower || mappedWith == null) { - enhancer.enhance(entity) - } - } - } - } - - protected GormStaticApi createGormStaticApi(Class cls, List finders) { - return new GormStaticApi(cls,datastore, finders) - } - - protected GormInstanceApi createGormInstanceApi(Class cls) { - def instanceApi = new GormInstanceApi(cls, datastore) - instanceApi.failOnError = failOnError - return instanceApi - } - - protected GormEnhancer createEnhancer() { - def enhancer = new GormEnhancer(datastore, transactionManager) - enhancer.failOnError = failOnError - return enhancer - } -} 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 deleted file mode 100644 index bac2bd46b..000000000 --- a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/OnChangeHandler.groovy +++ /dev/null @@ -1,111 +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.plugin.support - -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 -import org.springframework.transaction.PlatformTransactionManager -import org.springframework.transaction.annotation.Transactional -import org.springframework.validation.Validator - -/** - * Common onChange handling logic. - * - * @author Graeme Rocher - * @since 1.0 - */ -abstract class OnChangeHandler extends DynamicMethodsConfigurer{ - - OnChangeHandler(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - abstract String getDatastoreType() - - void onChange(plugin, Map event) { - Class source = event.source - if (!source || !event.ctx) { - return - } - - def application = event.application - if (application.isArtefactOfType(DomainClassArtefactHandler.TYPE, source)) { - final mappingContext = datastore.mappingContext - final entity = mappingContext.addPersistentEntity(source, true) - final domainClass = application.addArtefact(DomainClassArtefactHandler.TYPE, source) - ApplicationContext ctx = event.ctx - if (ctx.containsBean("${domainClass}Validator")) { - mappingContext.addEntityValidator(entity, ctx.getBean("${domainClass}Validator", Validator)) - } - configure() - } - else if (application.isArtefactOfType(ServiceArtefactHandler.TYPE, source)) { - - def serviceClass = application.addArtefact(ServiceArtefactHandler.TYPE, source) - if (!shouldCreateTransactionalProxy(serviceClass)) { - return - } - - def beans = plugin.beans { - def scope = serviceClass.getPropertyValue("scope") - def props = ["*": "PROPAGATION_REQUIRED"] as Properties - "${serviceClass.propertyName}"(TypeSpecifyableTransactionProxyFactoryBean, serviceClass.clazz) { bean -> - if (scope) bean.scope = scope - bean.lazyInit = true - target = { innerBean -> - innerBean.factoryBean = "${serviceClass.fullName}ServiceClass" - innerBean.factoryMethod = "newInstance" - innerBean.autowire = "byName" - if (scope) innerBean.scope = scope - } - proxyTargetClass = true - transactionAttributeSource = new GroovyAwareNamedTransactionAttributeSource(transactionalAttributes:props) - delegate.transactionManager = ref("${datastoreType.toLowerCase()}TransactionManager") - } - } - beans.registerBeans(event.ctx) - } - } - - boolean shouldCreateTransactionalProxy(GrailsServiceClass serviceClass) { - - if (serviceClass.getStaticPropertyValue('transactional', Boolean)) { - // leave it as a regular proxy - return false - } - - if (!datastoreType.equalsIgnoreCase(serviceClass.getStaticPropertyValue('transactional', String))) { - return false - } - - try { - Class javaClass = serviceClass.clazz - serviceClass.transactional && - !AnnotationUtils.findAnnotation(javaClass, Transactional) && - !javaClass.methods.any { Method m -> AnnotationUtils.findAnnotation(m, Transactional) != null } - } - catch (e) { - return false - } - } -} 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 deleted file mode 100644 index a75a035af..000000000 --- a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregator.groovy +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2011 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.plugin.support - -import org.apache.commons.logging.Log -import org.apache.commons.logging.LogFactory -import org.codehaus.groovy.grails.support.PersistenceContextInterceptor -import org.grails.datastore.gorm.support.DatastorePersistenceContextInterceptor -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory -import org.springframework.beans.factory.support.BeanDefinitionRegistry -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor -import org.springframework.core.Ordered - -/** - * Works around the issue where Grails only finds the first PersistenceContextInterceptor by - * replacing all discovered interceptors with a single aggregating instance. - * - * @author Burt Beckwith - */ -class PersistenceContextInterceptorAggregator implements BeanDefinitionRegistryPostProcessor, Ordered { - - private boolean hibernate - private boolean mongo - private boolean redis - private boolean aggregate - private boolean neo4j - private List interceptors = [] - - protected Log log = LogFactory.getLog(PersistenceContextInterceptorAggregator) - - int getOrder() { 500 } - - void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { - - log.info 'postProcessBeanDefinitionRegistry start' - - int count = 0 - if (registry.containsBeanDefinition('persistenceInterceptor')) { - count++ - hibernate = true - } - if (registry.containsBeanDefinition('mongoPersistenceInterceptor')) { - count++ - mongo = true - } - if (registry.containsBeanDefinition('redisDatastorePersistenceInterceptor')) { - count++ - redis = true - } - if (registry.containsBeanDefinition('neo4jPersistenceInterceptor')) { - count++ - neo4j = true - } - - if (count < 2) { - log.info "Not processing, there are $count interceptors" - return - } - - aggregate = true - - if (registry.containsBeanDefinition('persistenceInterceptor')) { - registry.removeBeanDefinition 'persistenceInterceptor' - } - - if (registry.containsBeanDefinition('mongoPersistenceInterceptor')) { - registry.removeBeanDefinition 'mongoPersistenceInterceptor' - } - - if (registry.containsBeanDefinition('redisDatastorePersistenceInterceptor')) { - registry.removeBeanDefinition 'redisDatastorePersistenceInterceptor' - } - - if (registry.containsBeanDefinition('neo4jPersistenceInterceptor')) { - registry.removeBeanDefinition 'neo4jPersistenceInterceptor' - } - } - - void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { - if (!aggregate) { - return - } - - log.info 'postProcessBeanFactory start' - - if (hibernate) { - def HibernatePersistenceContextInterceptor = Class.forName( - 'org.codehaus.groovy.grails.orm.hibernate.support.HibernatePersistenceContextInterceptor', - true, Thread.currentThread().contextClassLoader) - def interceptor = HibernatePersistenceContextInterceptor.newInstance() - interceptor.sessionFactory = beanFactory.getBean('sessionFactory') - interceptors << interceptor - } - - if (mongo) { - interceptors << new DatastorePersistenceContextInterceptor(beanFactory.getBean('mongoDatastore')) - } - - if (redis) { - interceptors << new DatastorePersistenceContextInterceptor(beanFactory.getBean('redisDatastore')) - } - - if (neo4j) { - interceptors << new DatastorePersistenceContextInterceptor(beanFactory.getBean('neo4jDatastore')) - } - - beanFactory.registerSingleton('persistenceInterceptor', - new AggregatePersistenceContextInterceptor(interceptors)) - } -} 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 deleted file mode 100644 index 36df01e65..000000000 --- a/grails-datastore-gorm-plugin-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/SpringConfigurer.groovy +++ /dev/null @@ -1,158 +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.plugin.support - -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 -import org.grails.datastore.mapping.web.support.OpenSessionInViewInterceptor -import org.springframework.beans.factory.support.AbstractBeanDefinition -import org.springframework.core.annotation.AnnotationUtils -import org.springframework.transaction.annotation.Transactional - -/** - * Helper class for use by plugins in configuring Spring. - * - * @author Graeme Rocher - * @since 1.0 - */ -abstract class SpringConfigurer { - - /** - * The name of the datastore type (example "Mongo" or "Neo4j") - * @return - */ - abstract String getDatastoreType() - - /** - * Additional Spring configuration that is specific to the underlying Datastore. The returned closure should use BeanBuilder syntax and must as a minimum - * define two beans named "${datastoreType.toLowerCase()}Datastore" and "${datastoreType.toLowerCase()}MappingContext" (Example "neo4jDatastore" and "neo4jMappingContext" - * - * @return BeanBuilder syntax closure. - */ - abstract Closure getSpringCustomizer() - - Closure getConfiguration() { - return configureSpring(getSpringCustomizer()) - } - - protected Closure configureSpring(Closure customizer) { - - String type = getDatastoreType() - String typeLower = type.toLowerCase() - - return { - - "${typeLower}TransactionManager"(DatastoreTransactionManager) { - datastore = ref("${typeLower}Datastore") - } - - def currentSpringConfig = getSpringConfig() - - if (!currentSpringConfig.containsBean("transactionManager") && !manager?.hasGrailsPlugin('hibernate') && !manager?.hasGrailsPlugin('hibernate4')) { - currentSpringConfig.addAlias('transactionManager', "${typeLower}TransactionManager") - } - - "${typeLower}PersistenceInterceptor"(DatastorePersistenceContextInterceptor, ref("${typeLower}Datastore")) - - "${typeLower}PersistenceContextInterceptorAggregator"(PersistenceContextInterceptorAggregator) - - if (manager?.hasGrailsPlugin("controllers")) { - String interceptorName = "${typeLower}OpenSessionInViewInterceptor" - "${interceptorName}"(OpenSessionInViewInterceptor) { - datastore = ref("${typeLower}Datastore") - } - if (currentSpringConfig.containsBean("controllerHandlerMappings")) { - controllerHandlerMappings.interceptors << ref(interceptorName) - } - if (currentSpringConfig.containsBean("annotationHandlerMapping")) { - if (annotationHandlerMapping.interceptors) { - annotationHandlerMapping.interceptors << ref(interceptorName) - } - else { - annotationHandlerMapping.interceptors = [ref(interceptorName)] - } - } - } - - // need to fix the service proxies to use TransactionManager - for (serviceGrailsClass in application.serviceClasses) { - GrailsServiceClass serviceClass = serviceGrailsClass - - if (!shouldCreateTransactionalProxy(typeLower, serviceClass)) { - continue - } - - def beanName = serviceClass.propertyName - if (springConfig.containsBean(beanName)) { - delegate."$beanName".transactionManager = ref("${typeLower}TransactionManager") - } - } - - // make sure validators for domain classes are regular GrailsDomainClassValidator - def isHibernateInstalled = manager.hasGrailsPlugin("hibernate") || manager.hasGrailsPlugin("hibernate4") - - if (!isHibernateInstalled) { - currentSpringConfig.addAlias "persistenceInterceptor", "${typeLower}PersistenceInterceptor" - } - for (dc in application.domainClasses) { - def cls = dc.clazz - def cpf = ClassPropertyFetcher.forClass(cls) - def mappedWith = cpf.getStaticPropertyValue(GrailsDomainClassProperty.MAPPING_STRATEGY, String) - if (mappedWith == typeLower || (!isHibernateInstalled && mappedWith == null)) { - String validatorBeanName = "${dc.fullName}Validator" - AbstractBeanDefinition beandef = springConfig.getBeanConfig(validatorBeanName)?.beanDefinition ?: - springConfig.getBeanDefinition(validatorBeanName) - - if (beandef != null) { - // remove the session factory attribute if present - beandef.getPropertyValues().removePropertyValue("sessionFactory") - beandef.beanClassName = GrailsDomainClassValidator.name - } - } - } - customizer.delegate = delegate - customizer.call() - } - } - - boolean shouldCreateTransactionalProxy(String type, GrailsServiceClass serviceClass) { - - if (serviceClass.getStaticPropertyValue('transactional', Boolean)) { - // leave it as a regular proxy - return false - } - - if (!type.equals(serviceClass.getStaticPropertyValue('transactional', String))) { - return false - } - - try { - Class javaClass = serviceClass.clazz - serviceClass.transactional && - !AnnotationUtils.findAnnotation(javaClass, Transactional) && - !javaClass.methods.any { Method m -> AnnotationUtils.findAnnotation(m, Transactional) != null } - } - catch (e) { - return false - } - } -} 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 deleted file mode 100644 index adce3adc4..000000000 --- a/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/DynamicMethodsConfigurerSpec.groovy +++ /dev/null @@ -1,105 +0,0 @@ -package org.grails.datastore.gorm.plugin.support - -import grails.persistence.Entity -import grails.validation.ValidationException -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 -import org.springframework.transaction.PlatformTransactionManager -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -import spock.lang.Specification - -/** - * - */ -class DynamicMethodsConfigurerSpec extends Specification{ - - void setup() { - ExpandoMetaClass.enableGlobally() - } - void cleanup() { - GroovySystem.metaClassRegistry.removeMetaClass(Simple) - } - - void "Test dynamic methods are configured correctly with no existing datastore"() { - given:"A dynamic methods configurer with a single domain class" - final configurer = systemUnderTest() - configurer.datastore.mappingContext.addPersistentEntity(Simple) - - when:"Dynamic methods are configured" - configurer.configure() - - then:"Dynamic methods can be called on the domain" - Simple.count() == 0 - } - - void "Test dynamic methods are configured correctly with an existing datastore"() { - given:"A dynamic methods configurer with a single domain class" - final configurer = systemUnderTest() - configurer.hasExistingDatastore = true - configurer.datastore.mappingContext.addPersistentEntity(Simple) - - when:"Dynamic methods are configured" - configurer.configure() - - then:"Dynamic methods are scoped to the datastore" - Simple.simple.count() == 0 - - when:"And are not included at the top level" - Simple.count() - - then:"A missing method exception is thrown" - thrown(MissingMethodException) - } - - void "Test that failOnError can be activated"() { - given:"A dynamic methods configurer with a single domain class and failOnError activated" - final configurer = systemUnderTest() - configurer.failOnError = true - def entity = configurer.datastore.mappingContext.addPersistentEntity(Simple) - configurer.datastore.mappingContext.addEntityValidator(entity, [ - supports:{java.lang.Class c -> true}, - validate:{target, Errors errors-> - def constrainedProperties = GrailsDomainConfigurationUtil.evaluateConstraints(Simple) - for (ConstrainedProperty cp in constrainedProperties.values()) { - cp.validate(target, target[cp.propertyName], errors) - } - } - ] as Validator) - - when:"Dynamic methods are configured" - configurer.configure() - new Simple(name: "").save() - - then:"Dynamic methods can be called on the domain" - thrown(ValidationException) - } - DynamicMethodsConfigurer systemUnderTest() { - return new SimpleDynamicMethodsConfigurer(new SimpleMapDatastore(), new DatastoreTransactionManager()) - } -} -class SimpleDynamicMethodsConfigurer extends DynamicMethodsConfigurer { - - SimpleDynamicMethodsConfigurer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { - return "Simple" - } - -} - -@Entity -class Simple { - Long id - String name - static constraints = { - name blank:false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/OnChangeHandlerSpec.groovy b/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/OnChangeHandlerSpec.groovy deleted file mode 100644 index dc23baa75..000000000 --- a/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/OnChangeHandlerSpec.groovy +++ /dev/null @@ -1,92 +0,0 @@ -package org.grails.datastore.gorm.plugin.support - -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.simple.SimpleMapDatastore -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager -import org.springframework.context.support.GenericApplicationContext -import org.springframework.transaction.PlatformTransactionManager - -import spock.lang.Specification - -/** - * Tests for onChange event handling - */ -class OnChangeHandlerSpec extends Specification{ - - void setup() { - datastore = new SimpleMapDatastore() - ExpandoMetaClass.enableGlobally() - } - void cleanup() { - datastore.mappingContext.persistentEntities.each { - GroovySystem.metaClassRegistry.removeMetaClass(it.javaClass) - } - } - - Datastore datastore - - void "Test onChange events for domain classes"() { - given:"A configured domain class" - def cls = classUnderTest() - final entity = datastore.mappingContext.addPersistentEntity(cls) - methodsConfigurer().configure() - - when:"A dynamic method is called" - def result = cls.count() - - then:"It works correctly" - result == 0 - - when:"A new version of the class is created on the onChange handler fired" - def newCls = classUnderTest() - final onChangeHandler = systemUnderTest() - onChangeHandler.onChange(mockPlugin(), mockEvent(newCls)) - entity = datastore.mappingContext.getPersistentEntity(cls.name) - - then:"The new class is correctly configured" - newCls.count() == 0 - entity.javaClass == newCls - } - - Map mockEvent(Class aClass) { - [ source: aClass, - application: [ - isArtefactOfType: { String name, Class c -> true }, - addArtefact:{ String name, Class c -> true } - ], - ctx: new GenericApplicationContext() - ] - } - - Object mockPlugin() { - [:] - } - - protected Class classUnderTest() { - def cls = new GroovyClassLoader().parseClass(""" -import grails.persistence.* - -@Entity -class Simple { Long id } - """) - } - - OnChangeHandler systemUnderTest() { - return new SimpleOnChangeHandler(datastore, new DatastoreTransactionManager()) - } - - DynamicMethodsConfigurer methodsConfigurer() { - return new SimpleDynamicMethodsConfigurer(datastore, new DatastoreTransactionManager()) - } -} -class SimpleOnChangeHandler extends OnChangeHandler { - - SimpleOnChangeHandler(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { - return "Simple" - } -} diff --git a/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/SpringConfigurerSpec.groovy b/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/SpringConfigurerSpec.groovy deleted file mode 100644 index f52135fc1..000000000 --- a/grails-datastore-gorm-plugin-support/src/test/groovy/org/grails/datastore/gorm/plugin/support/SpringConfigurerSpec.groovy +++ /dev/null @@ -1,54 +0,0 @@ -package org.grails.datastore.gorm.plugin.support - -import grails.spring.BeanBuilder - -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext -import org.grails.datastore.mapping.simple.SimpleMapDatastore -import org.springframework.context.ApplicationContext - -import spock.lang.Specification - -/** - * Tests for Spring configuration - */ -class SpringConfigurerSpec extends Specification { - - void "Test that the ApplicationContext constructed is valid"() { - when:"An application context is configured" - ApplicationContext ctx = systemUnderTest() - - then:"The context contains the necessary beans" - ctx.containsBean("simpleDatastore") - ctx.containsBean("simpleTransactionManager") - ctx.containsBean("transactionManager") - ctx.containsBean("simplePersistenceInterceptor") - ctx.containsBean("simplePersistenceContextInterceptorAggregator") - ctx.containsBean("simpleOpenSessionInViewInterceptor") - } - - ApplicationContext systemUnderTest() { - def bb = new BeanBuilder() - bb.beans new SimpleSpringConfigurer().getConfiguration() - - bb.createApplicationContext() - } -} - -class SimpleSpringConfigurer extends SpringConfigurer { - - Map manager = [hasGrailsPlugin:{ String name -> name != 'hibernate' && name != 'hibernate4' }] - Map application = [:] - - @Override - String getDatastoreType() { - return "Simple" - } - - @Override - Closure getSpringCustomizer() { - return { - simpleDatastore(SimpleMapDatastore) - simpleMappingContext(KeyValueMappingContext, "test") - } - } -} diff --git a/grails-datastore-gorm-redis/build.gradle b/grails-datastore-gorm-redis/build.gradle deleted file mode 100644 index 2b93cf3e3..000000000 --- a/grails-datastore-gorm-redis/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ -version = "1.0.0.BUILD-SNAPSHOT" - -dependencies { - compile project(":grails-datastore-gorm"), - project(":grails-datastore-gorm-plugin-support"), - project(":grails-datastore-redis"), - project(":grails-datastore-core") - testCompile project(":grails-datastore-gorm-test"), - project(":grails-datastore-gorm-tck") - testRuntime "org.springframework:spring-expression:$springVersion" -} - -/* -test { - jvmArgs '-Xmx1024m', '-Xdebug', '-Xnoagent', '-Dgrails.full.stacktrace=true', '-Djava.compiler=NONE', - '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005' -} -*/ diff --git a/grails-datastore-gorm-redis/src/main/groovy/grails/datastore/Redis.groovy b/grails-datastore-gorm-redis/src/main/groovy/grails/datastore/Redis.groovy deleted file mode 100644 index bb7bbbc2f..000000000 --- a/grails-datastore-gorm-redis/src/main/groovy/grails/datastore/Redis.groovy +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright (C) 2010 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 grails.datastore - -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.redis.collection.RedisCollection -import org.grails.datastore.mapping.redis.collection.RedisList -import org.grails.datastore.mapping.redis.collection.RedisMap -import org.grails.datastore.mapping.redis.collection.RedisSet -import org.grails.datastore.mapping.redis.util.RedisTemplate - -/** - * Convenience interface for access the Redis datastore. - * - * @author Graeme Rocher - */ -class Redis { - - @Delegate RedisTemplate redisTemplate - private Datastore datastore - - def getAt(String s) { - get(s) - } - - def setAt(String s, v) { - set s, v - } - - void setDatastore(Datastore ds) { - datastore = ds - boolean existing = datastore.hasCurrentSession() - Session session - if (existing) { - session = datastore.currentSession - } - else { - session = datastore.connect() - } - redisTemplate = session.nativeInterface - if (!existing) { - session.disconnect() - } - } - - /** - * Creates a Redis set for the given key. - * @param key the key - * @return the set - */ - RedisSet set(String key) { - return new RedisSet(redisTemplate, key) - } - - /** - * Creates a hash for the given key. - * @param key the key - * @return the hash - */ - RedisMap hash(String key) { - return new RedisMap(redisTemplate, key) - } - - /** - * Creates a Redis list for the given key. - * @param key the key - * @return the list - */ - RedisList list(String key) { - return new RedisList(redisTemplate, key) - } - - /** - * Returns an entity list from the specified key. - * @param key the key - * @return An entity list - */ - Collection entities(Class type, String key, int offset = 0, int max = -1) { - def set = set(key) - return entities(type, set, offset, max) - } - - /** - * Returns entities from the specified type and Redis collection. - * @param type The type - * @param col The collection - * @param offset The offset - * @param max The max - * @return entities - */ - Collection entities(Class type, RedisCollection col, int offset = 0, int max = -1) { - PersistentEntity entity = datastore.mappingContext.getPersistentEntity(type.name) - if (entity == null) { - throw new IllegalArgumentException("Class [$type.name] is not a persistent entity") - } - def results = col.members(offset, max) - - boolean existing = datastore.hasCurrentSession() - Session session - if (existing) { - session = datastore.currentSession - } - else { - session = datastore.connect() - } - - try { - return session.retrieveAll(type, results) - } - finally { - if (!existing) { - session.disconnect() - } - } - } -} diff --git a/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/RedisGormEnhancer.groovy b/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/RedisGormEnhancer.groovy deleted file mode 100644 index 907222eab..000000000 --- a/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/RedisGormEnhancer.groovy +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (C) 2010 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.redis - -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.core.SessionCallback -import org.grails.datastore.mapping.core.VoidSessionCallback -import org.springframework.transaction.PlatformTransactionManager - -/** - * Adds Redis specific functionality to GORM. - */ -class RedisGormEnhancer extends GormEnhancer { - - RedisGormEnhancer(Datastore datastore) { - super(datastore) - } - - RedisGormEnhancer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - protected GormStaticApi getStaticApi(Class cls) { - return new RedisGormStaticApi(cls, datastore, getFinders()) - } - - protected GormInstanceApi getInstanceApi(Class cls) { - final api = new RedisGormInstanceApi(cls, datastore) - api.failOnError = failOnError - return api - } -} - -class RedisGormInstanceApi extends GormInstanceApi { - - RedisGormInstanceApi(Class persistentClass, Datastore datastore) { - super(persistentClass, datastore) - } - - void expire(D instance, int ttl) { - execute (new VoidSessionCallback() { - void doInSession(Session session) { - session.expire instance, ttl - } - }) - } -} - -class RedisGormStaticApi extends GormStaticApi { - - RedisGormStaticApi(Class persistentClass, Datastore datastore, List finders) { - super(persistentClass, datastore, finders) - } - - /** - * Expires an entity for the given id and TTL. - */ - void expire(Serializable id, int ttl) { - execute (new VoidSessionCallback() { - void doInSession(Session session) { - session.expire(persistentClass, id, ttl) - } - }) - } - - /** - * A random domain class instance is returned. - * @return A random domain class - */ - D random() { - execute (new SessionCallback() { - def doInSession(Session session) { - session.random(persistentClass) - } - }) - } - - /** - * A random domain class instance is removed and returned. - * @return A random removed domain class - */ - D pop() { - execute (new SessionCallback() { - def doInSession(Session session) { - session.pop(persistentClass) - } - }) - } -} diff --git a/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/bean/factory/RedisDatastoreFactoryBean.groovy b/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/bean/factory/RedisDatastoreFactoryBean.groovy deleted file mode 100644 index 0b6e7695a..000000000 --- a/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/bean/factory/RedisDatastoreFactoryBean.groovy +++ /dev/null @@ -1,41 +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.redis.bean.factory - -import org.codehaus.groovy.grails.plugins.GrailsPluginManager -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.redis.RedisDatastore -import org.springframework.beans.factory.FactoryBean -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware - -/** - * Creates the RedisDatastore bean - */ -class RedisDatastoreFactoryBean implements FactoryBean, ApplicationContextAware { - - Map config - MappingContext mappingContext - GrailsPluginManager pluginManager - ApplicationContext applicationContext - - RedisDatastore getObject() { - new RedisDatastore(mappingContext, config, applicationContext) - } - - Class getObjectType() { RedisDatastore } - - boolean isSingleton() { true } -} diff --git a/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/bean/factory/RedisMappingContextFactoryBean.groovy b/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/bean/factory/RedisMappingContextFactoryBean.groovy deleted file mode 100644 index d71dc7478..000000000 --- a/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/bean/factory/RedisMappingContextFactoryBean.groovy +++ /dev/null @@ -1,30 +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.redis.bean.factory - -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.gorm.bean.factory.AbstractMappingContextFactoryBean - -/** - * Configures the Redis mapping context - * - * @author Graeme Rocher - */ -class RedisMappingContextFactoryBean extends AbstractMappingContextFactoryBean { - protected MappingContext createMappingContext() { - new KeyValueMappingContext("") - } -} diff --git a/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/plugin/support/RedisMethodsConfigurer.groovy b/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/plugin/support/RedisMethodsConfigurer.groovy deleted file mode 100644 index 866ed327a..000000000 --- a/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/plugin/support/RedisMethodsConfigurer.groovy +++ /dev/null @@ -1,63 +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.redis.plugin.support - -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.plugin.support.DynamicMethodsConfigurer -import org.grails.datastore.gorm.redis.RedisGormEnhancer -import org.grails.datastore.gorm.redis.RedisGormInstanceApi -import org.grails.datastore.gorm.redis.RedisGormStaticApi -import org.grails.datastore.mapping.core.Datastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * Methods configurer for Redis - */ -class RedisMethodsConfigurer extends DynamicMethodsConfigurer { - - RedisMethodsConfigurer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { "Redis" } - - @Override - protected GormStaticApi createGormStaticApi(Class cls, List finders) { - return new RedisGormStaticApi(cls, datastore, finders) - } - - @Override - protected GormInstanceApi createGormInstanceApi(Class cls) { - def api = new RedisGormInstanceApi(cls, datastore) - api.failOnError = failOnError - api - } - - @Override - protected GormEnhancer createEnhancer() { - def ge - if (transactionManager) { - ge = new RedisGormEnhancer(datastore, transactionManager) - } else { - ge = new RedisGormEnhancer(datastore) - } - ge.failOnError = failOnError - ge - } -} diff --git a/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/plugin/support/RedisOnChangeHandler.groovy b/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/plugin/support/RedisOnChangeHandler.groovy deleted file mode 100644 index 64c281b8f..000000000 --- a/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/plugin/support/RedisOnChangeHandler.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package org.grails.datastore.gorm.redis.plugin.support - -import org.grails.datastore.gorm.plugin.support.OnChangeHandler -import org.grails.datastore.mapping.core.Datastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * onChange handler for Redis - */ -class RedisOnChangeHandler extends OnChangeHandler { - - RedisOnChangeHandler(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { "Redis" } -} diff --git a/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/plugin/support/RedisSpringConfigurer.groovy b/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/plugin/support/RedisSpringConfigurer.groovy deleted file mode 100644 index 2a535f51a..000000000 --- a/grails-datastore-gorm-redis/src/main/groovy/org/grails/datastore/gorm/redis/plugin/support/RedisSpringConfigurer.groovy +++ /dev/null @@ -1,51 +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.redis.plugin.support - -import org.grails.datastore.gorm.plugin.support.SpringConfigurer -import grails.datastore.Redis -import org.grails.datastore.gorm.redis.bean.factory.RedisMappingContextFactoryBean -import org.grails.datastore.gorm.redis.bean.factory.RedisDatastoreFactoryBean - -/** - * Configures Spring for Redis - */ -class RedisSpringConfigurer extends SpringConfigurer{ - @Override - String getDatastoreType() { "Redis" } - - @Override - Closure getSpringCustomizer() { - return { - def redisConfig = application.config?.grails?.'redis-gorm' - - redisDatastoreMappingContext(RedisMappingContextFactoryBean) { - grailsApplication = ref('grailsApplication') - pluginManager = ref('pluginManager') - defaultExternal = false // manager.hasGrailsPlugin("hibernate") - } - - redisDatastore(RedisDatastoreFactoryBean) { - config = redisConfig - mappingContext = ref("redisDatastoreMappingContext") - pluginManager = ref('pluginManager') - } - - redis(Redis) { bean -> - datastore = ref("redisDatastore") - } - } - } -} diff --git a/grails-datastore-gorm-redis/src/test/groovy/grails/datastore/RedisSpec.groovy b/grails-datastore-gorm-redis/src/test/groovy/grails/datastore/RedisSpec.groovy deleted file mode 100644 index 9ba6c9bae..000000000 --- a/grails-datastore-gorm-redis/src/test/groovy/grails/datastore/RedisSpec.groovy +++ /dev/null @@ -1,59 +0,0 @@ -package grails.datastore - -import grails.gorm.tests.* - -/** - * @author graemerocher - */ -class RedisSpec extends GormDatastoreSpec { - - def "Test usage of subscript operator"() { - given: - def redis = new Redis(datastore:session.datastore) - - when: - redis.flushall() - redis["foo"] = "bar" - - then: - "bar" == redis["foo"] - } - - def testRedisList() { - given: - def redis = new Redis(datastore:session.datastore) - - when: - redis.flushall() - def list = redis.list("my.list") - list << 1 << 2 << 3 - - then: - 3 == list.size() - 1 == list[0] as Integer - 2 == list[1] as Integer - 3 == list[2] as Integer - } - - def testEntities() { - given: - def redis = new Redis(datastore:session.datastore) - def age = 40 - ["Bob", "Fred", "Barney", "Frank", "Joe", "Ernie"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - def results = TestEntity.list() - - expect: - 6 == results.size() - - when: - def list = redis.list("my.list") - results.each { list << it.id } - def entities = redis.entities(TestEntity, "my.list") - - then: - 6 == entities.size() - entities.find { it.name == "Fred"} - } -} diff --git a/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy b/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy deleted file mode 100644 index 4233a2bc8..000000000 --- a/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package grails.gorm.tests - -import org.junit.Ignore - -/** - * Tests for criteria queries that compare two properties - */ -class PropertyComparisonQuerySpec extends GormDatastoreSpec { - - @Ignore - void "Test eqProperty criterion"() { - // TODO: implement eqProperty query operations - } -} diff --git a/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/QueryByNullSpec.groovy b/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/QueryByNullSpec.groovy deleted file mode 100644 index b8469e183..000000000 --- a/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/QueryByNullSpec.groovy +++ /dev/null @@ -1,9 +0,0 @@ -package grails.gorm.tests - -class QueryByNullSpec extends GormDatastoreSpec { - @spock.lang.Ignore - void 'Test passing null as the sole argument to a dynamic finder multiple times'() { - // see GRAILS-3463 - } -} - diff --git a/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy b/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy deleted file mode 100644 index 082db7656..000000000 --- a/grails-datastore-gorm-redis/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.tests.GormDatastoreSpec -import org.junit.Ignore - -/** - * Tests for querying the size of collections etc. - */ -class SizeQuerySpec extends GormDatastoreSpec { - - @Ignore - void "Test sizeEq criterion"() { - // TODO: implement sizeEq query operations - } -} diff --git a/grails-datastore-gorm-redis/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-redis/src/test/groovy/org/grails/datastore/gorm/Setup.groovy deleted file mode 100644 index c0f2fc586..000000000 --- a/grails-datastore-gorm-redis/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ /dev/null @@ -1,61 +0,0 @@ -package org.grails.datastore.gorm - -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.gorm.redis.* -import org.springframework.context.support.GenericApplicationContext -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.redis.RedisDatastore -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager -import org.springframework.util.StringUtils -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -/** - * @author graemerocher - */ -class Setup { - - static redis - - static destroy() { - redis?.destroy() - } - - static Session setup(classes) { - def ctx = new GenericApplicationContext() - ctx.refresh() - redis = new RedisDatastore(new KeyValueMappingContext(""), [pooled:"false"], ctx) - for (cls in classes) { - redis.mappingContext.addPersistentEntity(cls) - } - - PersistentEntity entity = redis.mappingContext.persistentEntities.find { PersistentEntity e -> e.name.contains("TestEntity")} - - redis.mappingContext.addEntityValidator(entity, [ - supports: { Class c -> true }, - validate: { Object o, Errors errors -> - if (!StringUtils.hasText(o.name)) { - errors.rejectValue("name", "name.is.blank") - } - } - ] as Validator) - - def enhancer = new RedisGormEnhancer(redis, new DatastoreTransactionManager(datastore: redis)) - enhancer.enhance() - - redis.mappingContext.addMappingContextListener({ e -> - enhancer.enhance e - } as MappingContext.Listener) - - redis.applicationContext.addApplicationListener new DomainEventListener(redis) - redis.applicationContext.addApplicationListener new AutoTimestampEventListener(redis) - - def con = redis.connect() - con.getNativeInterface().flushdb() - return con - } -} diff --git a/grails-datastore-gorm-redis/src/test/groovy/org/grails/datastore/gorm/redis/RedisSpecificMethodsSpec.groovy b/grails-datastore-gorm-redis/src/test/groovy/org/grails/datastore/gorm/redis/RedisSpecificMethodsSpec.groovy deleted file mode 100644 index 08ee764d9..000000000 --- a/grails-datastore-gorm-redis/src/test/groovy/org/grails/datastore/gorm/redis/RedisSpecificMethodsSpec.groovy +++ /dev/null @@ -1,60 +0,0 @@ -package org.grails.datastore.gorm.redis - -import grails.gorm.tests.* - -/** - * @author graemerocher - */ -class RedisSpecificMethodsSpec extends GormDatastoreSpec { - - def "Test expire an entity"() { - given: - new TestEntity(name:"Bob", age:45, child:new ChildEntity(name:"Child")).save() - session.flush() - - when: - def te = TestEntity.random() - - then: - te != null - - when: - te.expire(5) - session.clear() - sleep(10000) - then: - TestEntity.get(te.id) == null - } - - def "Test get random entity"() { - given: - def age = 40 - def names = ["Bob", "Fred", "Barney", "Frank", "Joe", "Ernie"] - names.each { new TestEntity(name:it, age: age--, child:new ChildEntity(name:"$it Child")).save() } - - when: - def t = TestEntity.random() - - then: - t != null - names.find { it == t.name } - } - - def "Test pop random entity"() { - given: - def age = 40 - def names = ["Bob", "Fred", "Barney", "Frank", "Joe", "Ernie"] - names.each { new TestEntity(name:it, age: age--, child:new ChildEntity(name:"$it Child")).save() } - - expect: - 6 == TestEntity.count() - - when: - def t = TestEntity.pop() - - then: - t != null - names.find { it == t.name } - 5 == TestEntity.count() - } -} diff --git a/grails-datastore-gorm-redis/src/test/groovy/org/grails/datastore/gorm/redis/RedisSuite.groovy b/grails-datastore-gorm-redis/src/test/groovy/org/grails/datastore/gorm/redis/RedisSuite.groovy deleted file mode 100644 index ec1cb699f..000000000 --- a/grails-datastore-gorm-redis/src/test/groovy/org/grails/datastore/gorm/redis/RedisSuite.groovy +++ /dev/null @@ -1,61 +0,0 @@ -package org.grails.datastore.gorm.redis - -import grails.gorm.tests.EnumSpec -import org.junit.runner.RunWith -import org.junit.runners.Suite -import org.junit.runners.Suite.SuiteClasses -import grails.gorm.tests.WithTransactionSpec -import grails.gorm.tests.InheritanceSpec -import grails.gorm.tests.FindByMethodSpec -import grails.gorm.tests.ListOrderBySpec -import grails.gorm.tests.ProxyLoadingSpec -import grails.gorm.tests.GroovyProxySpec -import grails.gorm.tests.DomainEventsSpec -import grails.gorm.tests.CriteriaBuilderSpec -import grails.gorm.tests.NegationSpec -import grails.gorm.tests.UpdateWithProxyPresentSpec -import grails.gorm.tests.AttachMethodSpec -import grails.gorm.tests.CircularOneToManySpec -import grails.gorm.tests.QueryAfterPropertyChangeSpec -import grails.gorm.tests.CrudOperationsSpec -import grails.gorm.tests.CommonTypesPersistenceSpec -import grails.gorm.tests.GormEnhancerSpec -import grails.gorm.tests.NamedQuerySpec -import grails.gorm.tests.OrderBySpec -import grails.gorm.tests.RangeQuerySpec -import grails.gorm.tests.ValidationSpec -import grails.gorm.tests.SaveAllSpec -import grails.gorm.tests.DeleteAllSpec - -/** - * @author graemerocher - */ -@RunWith(Suite) -@SuiteClasses([ -// DomainEventsSpec, -// ProxyLoadingSpec, -// QueryAfterPropertyChangeSpec, -// CircularOneToManySpec, -// InheritanceSpec, -// FindByMethodSpec, -// ListOrderBySpec, -// GroovyProxySpec, -// CommonTypesPersistenceSpec, -// GormEnhancerSpec, -// CriteriaBuilderSpec, -// NegationSpec, -// NamedQuerySpec, -// OrderBySpec, -// RangeQuerySpec, -// ValidationSpec, -// UpdateWithProxyPresentSpec, -// AttachMethodSpec, -// WithTransactionSpec, -// CrudOperationsSpec -//SaveAllSpec, -//DeleteAllSpec -// DomainEventsSpec -// EnumSpec -]) -class RedisSuite { -} diff --git a/grails-datastore-gorm-rest-client/build.gradle b/grails-datastore-gorm-rest-client/build.gradle deleted file mode 100644 index fbd7c79d6..000000000 --- a/grails-datastore-gorm-rest-client/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -version = "1.0.0.BUILD-SNAPSHOT" -dependencies { - compile 'javax.servlet:javax.servlet-api:3.0.1' - runtime "org.springframework:spring-webmvc:$springVersion" - compile("org.grails:grails-plugin-rest:$grailsVersion") { - exclude group:'org.grails', module:'grails-plugin-datasource' - exclude group:'org.grails', module:'grails-plugin-controllers' - exclude group:'org.grails', module:'grails-web' - } - compile("org.grails:grails-databinding:$grailsVersion") { - exclude group:'junit', module:'junit' - } - compile project(":grails-datastore-gorm"), - project(":grails-datastore-rest-client"), - project(":grails-datastore-gorm-plugin-support"), - project(":grails-datastore-core") - - testCompile("org.springframework:spring-test:$springVersion") -} \ No newline at end of file diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/RestClientGormEnhancer.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/RestClientGormEnhancer.groovy deleted file mode 100644 index 2f8fb0295..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/RestClientGormEnhancer.groovy +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client - -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.rest.client.RestClientDatastore -import org.springframework.transaction.PlatformTransactionManager -import org.grails.datastore.gorm.GormInstanceApi - -/** - * GORM enhancer for the GORM REST client - * - * @author Graeme Rocher - * @since 1.0 - */ -class RestClientGormEnhancer extends GormEnhancer { - RestClientGormEnhancer(RestClientDatastore datastore) { - super(datastore) - } - - RestClientGormEnhancer(RestClientDatastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - protected GormStaticApi getStaticApi(Class cls) { - new RestClientGormStaticApi(cls, (RestClientDatastore)datastore, getFinders()) - } - - @Override - protected def GormInstanceApi getInstanceApi(Class cls) { - return new RestClientGormInstanceApi(cls, datastore) - } -} 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 deleted file mode 100644 index ddef3d74a..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/RestClientGormInstanceApi.groovy +++ /dev/null @@ -1,262 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client - -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 - -/** - * Extensions to the instance API for REST - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class RestClientGormInstanceApi extends GormInstanceApi { - - RestClientGormInstanceApi(Class persistentClass, Datastore datastore) { - super(persistentClass, datastore) - } - - /** - * Converter an instance from one format to another - * - * @param instance The instance - * @param clazz The type to convert to - * @return the converted object - */ - public Object asType(Object instance, Class clazz) { - new ConvertersApi().asType(instance, clazz) - } - - - - - /** - * Save the instance to the given URL - * - * @param instance The instance - * @param url The URL - * @return The instance if saved, null otherwise - */ - public Object save(Object instance, @DelegatesTo(RequestCustomizer) Closure requestCustomizer) { - put(instance, requestCustomizer) - } - - /** - * Deletes an instances for the given URL - * - * @param instance The instance - * @param url The URL to send the DELETE request to - */ - @CompileStatic(TypeCheckingMode.SKIP) // TODO: Report JIRA, removal causes GroovyCastException - public void delete(Object instance,@DelegatesTo(RequestCustomizer) Closure requestCustomizer) { - execute({ Session session -> - withRequestCustomizer(session, instance, requestCustomizer) { - delete(instance) - } - } as SessionCallback) - } - - /** - * Synonym for save() - * - * @param instance The instance - * @return The instance if it was saved, null otherwise - */ - @CompileStatic(TypeCheckingMode.SKIP) // TODO: Report JIRA, removal causes GroovyCastException - public Object put(Object instance, @DelegatesTo(RequestCustomizer) Closure requestCustomizer ) { - execute({ Session session -> - withRequestCustomizer(session, instance, requestCustomizer) { - save(instance) - } - } as SessionCallback) - } - - /** - * Synonym for insert() - * - * @param instance The instance - * @return The instance if it was saved, null otherwise - */ - @CompileStatic(TypeCheckingMode.SKIP) // TODO: Report JIRA, removal causes GroovyCastException - public Object post(Object instance, @DelegatesTo(RequestCustomizer) Closure requestCustomizer) { - execute({ Session session -> - withRequestCustomizer(session, instance, requestCustomizer) { - insert(instance) - } - } as SessionCallback) - } - - - /** - * Save the instance to the given URL - * - * @param instance The instance - * @param url The URL - * @return The instance if saved, null otherwise - */ - public Object save(Object instance, URL url,@DelegatesTo(RequestCustomizer) Closure requestCustomizer = null) { - put(instance, url, requestCustomizer) - } - - /** - * Deletes an instances for the given URL - * - * @param instance The instance - * @param url The URL to send the DELETE request to - */ - @CompileStatic(TypeCheckingMode.SKIP) // TODO: Report JIRA, removal causes GroovyCastException - public void delete(Object instance, URL url,@DelegatesTo(RequestCustomizer) Closure requestCustomizer = null) { - execute({ Session session -> - withCustomUrl(session,instance, url) { - withRequestCustomizer(session,instance, requestCustomizer) { - delete(instance) - } - } - } as SessionCallback) - } - - /** - * Synonym for save() - * - * @param instance The instance - * @return The instance if it was saved, null otherwise - */ - @CompileStatic(TypeCheckingMode.SKIP) // TODO: Report JIRA, removal causes GroovyCastException - public Object put(Object instance, URL url = null, @DelegatesTo(RequestCustomizer) Closure requestCustomizer = null) { - execute({ Session session -> - withCustomUrl(session, instance, url) { - withRequestCustomizer(session, instance, requestCustomizer) { - save(instance) - } - } - } as SessionCallback) - } - - /** - * Synonym for insert() - * - * @param instance The instance - * @return The instance if it was saved, null otherwise - */ - @CompileStatic(TypeCheckingMode.SKIP) // TODO: Report JIRA, removal causes GroovyCastException - public Object post(Object instance, URL url= null, @DelegatesTo(RequestCustomizer) Closure requestCustomizer = null) { - execute({ Session session -> - withCustomUrl(session, instance, url) { - withRequestCustomizer(session, instance, requestCustomizer) { - insert(instance) - } - } - } as SessionCallback) - } - - - /** - * Save the instance to the given URL - * - * @param instance The instance - * @param url The URL - * @return The instance if saved, null otherwise - */ - public Object save(Object instance, Map params, URL url, @DelegatesTo(RequestCustomizer) Closure requestCustomizer = null) { - put(instance, params,url, requestCustomizer) - } - - /** - * Deletes an instances for the given URL - * - * @param instance The instance - * @param url The URL to send the DELETE request to - */ - @CompileStatic(TypeCheckingMode.SKIP) // TODO: Report JIRA, removal causes GroovyCastException - public void delete(Object instance, Map params, URL url,@DelegatesTo(RequestCustomizer) Closure requestCustomizer = null) { - execute({ Session session -> - withCustomUrl(session,instance, url) { - withRequestCustomizer(session,instance, requestCustomizer) { - delete(instance) - } - } - } as SessionCallback) - } - - /** - * Synonym for save() - * - * @param instance The instance - * @return The instance if it was saved, null otherwise - */ - @CompileStatic(TypeCheckingMode.SKIP) // TODO: Report JIRA, removal causes GroovyCastException - public Object put(Object instance, Map params, URL url,@DelegatesTo(RequestCustomizer) Closure requestCustomizer = null) { - execute({ Session session -> - withCustomUrl(session, instance, url) { - withRequestCustomizer(session, instance, requestCustomizer) { - save(instance, params) - } - } - } as SessionCallback) - } - - /** - * Synonym for insert() - * - * @param instance The instance - * @return The instance if it was saved, null otherwise - */ - @CompileStatic(TypeCheckingMode.SKIP) // TODO: Report JIRA, removal causes GroovyCastException - public Object post(Object instance, Map params, URL url, @DelegatesTo(RequestCustomizer) Closure requestCustomizer = null) { - execute({ Session session -> - withCustomUrl(session, instance, url) { - withRequestCustomizer(session, instance, requestCustomizer) { - insert(instance, params) - } - } - } as SessionCallback) - } - - protected Object withCustomUrl(Session currentSession, Object instance, URL url, Closure callable) { - if (url) { - currentSession.setAttribute(instance, RestClientSession.ATTRIBUTE_URL, url) - } - try { - return callable.call() - } finally { - if (url) { - currentSession.setAttribute(instance, RestClientSession.ATTRIBUTE_URL, null) - } - } - } - - protected Object withRequestCustomizer(Session currentSession, Object instance, @DelegatesTo(RequestCustomizer) Closure customizer, Closure callable) { - if (customizer) { - currentSession.setAttribute(instance, RestClientSession.ATTRIBUTE_REQUEST_CUSTOMIZER, customizer) - } - try { - callable.call() - } finally { - if (customizer) { - currentSession.setAttribute(instance, RestClientSession.ATTRIBUTE_URL, null) - } - } - } -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/RestClientGormStaticApi.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/RestClientGormStaticApi.groovy deleted file mode 100644 index c5076f44f..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/RestClientGormStaticApi.groovy +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client - -import grails.plugins.rest.client.async.AsyncRestBuilder -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.rest.client.RestClientDatastore -import org.springframework.transaction.PlatformTransactionManager -import org.grails.datastore.mapping.core.SessionCallback -import org.grails.datastore.mapping.core.Session -import grails.plugins.rest.client.RequestCustomizer -import org.grails.datastore.mapping.rest.client.RestClientSession -import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode - -/** - * Extensions to the static API for REST - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class RestClientGormStaticApi extends GormStaticApi { - RestClientGormStaticApi(Class persistentClass, RestClientDatastore datastore, List finders) { - super(persistentClass, datastore, finders) - } - - RestClientGormStaticApi(Class persistentClass, RestClientDatastore datastore, List finders, PlatformTransactionManager transactionManager) { - super(persistentClass, datastore, finders, transactionManager) - } - - /** - * Obtains the RestBuilder instance used by this domain - */ - AsyncRestBuilder getRestBuilder() { - ((RestClientDatastore)datastore).asyncRestClients.get(persistentEntity) - } - - @CompileStatic(TypeCheckingMode.SKIP) - List getAll(URL url, Serializable... ids) { - execute({ Session session -> - withCustomUrl(session, url) { - getAll(ids) - } - } as SessionCallback) - } - - @CompileStatic(TypeCheckingMode.SKIP) - D get(URL url, Serializable id) { - execute({ Session session -> - withCustomUrl(session, url) { - get(id) - } - } as SessionCallback) - - } - - @CompileStatic(TypeCheckingMode.SKIP) - List getAll(URL url, Iterable ids, @DelegatesTo(RequestCustomizer) Closure customizer) { - execute({ Session session -> - withRequestCustomizer(session, customizer) { - withCustomUrl(session, url) { - getAll(ids.toList().toArray()) - } - } - } as SessionCallback) - } - - @CompileStatic(TypeCheckingMode.SKIP) - D get(URL url, Serializable id, @DelegatesTo(RequestCustomizer) Closure customizer) { - execute({ Session session -> - withRequestCustomizer(session, customizer) { - withCustomUrl(session, url) { - get(id) - } - } - } as SessionCallback) - - } - - - protected Object withCustomUrl(Session currentSession, URL url, Closure callable) { - if (url) { - currentSession.setAttribute(persistentEntity, RestClientSession.ATTRIBUTE_URL, url) - } - try { - return callable.call() - } finally { - if (url) { - currentSession.setAttribute(persistentEntity, RestClientSession.ATTRIBUTE_URL, null) - } - } - } - - protected Object withRequestCustomizer(Session currentSession, @DelegatesTo(RequestCustomizer) Closure customizer, Closure callable) { - if (customizer) { - currentSession.setAttribute(persistentEntity, RestClientSession.ATTRIBUTE_REQUEST_CUSTOMIZER, customizer) - } - try { - callable.call() - } finally { - if (customizer) { - currentSession.setAttribute(persistentEntity, RestClientSession.ATTRIBUTE_URL, null) - } - } - } -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/plugin/support/RestClientDatastoreFactoryBean.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/plugin/support/RestClientDatastoreFactoryBean.groovy deleted file mode 100644 index c9e748317..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/plugin/support/RestClientDatastoreFactoryBean.groovy +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client.plugin.support - -import groovy.transform.CompileStatic -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository -import org.grails.datastore.mapping.rest.client.RestClientDatastore -import org.grails.datastore.mapping.rest.client.config.RestClientMappingContext -import org.springframework.beans.factory.FactoryBean -import org.springframework.beans.factory.InitializingBean -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware -import org.springframework.context.ConfigurableApplicationContext - -/** - * Spring Factory bean for constructing the RestClientDatastore - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class RestClientDatastoreFactoryBean implements FactoryBean, ApplicationContextAware{ - ApplicationContext applicationContext - RestClientMappingContext mappingContext - Map connectionDetails - @Autowired(required = false) - TPCacheAdapterRepository cacheAdapterRepository - - - @Override - RestClientDatastore getObject() throws Exception { - final appCtx = (ConfigurableApplicationContext) applicationContext - final datastore = new RestClientDatastore(mappingContext, connectionDetails, appCtx, cacheAdapterRepository) - appCtx.addApplicationListener new DomainEventListener(datastore) - appCtx.addApplicationListener new AutoTimestampEventListener(datastore) - - return datastore - } - - @Override - Class getObjectType() { RestClientDatastore } - - @Override - boolean isSingleton() { true } - -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/plugin/support/RestClientMappingContextFactoryBean.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/plugin/support/RestClientMappingContextFactoryBean.groovy deleted file mode 100644 index a112e37a8..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/plugin/support/RestClientMappingContextFactoryBean.groovy +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client.plugin.support - -import groovy.transform.Canonical -import org.grails.datastore.gorm.bean.factory.AbstractMappingContextFactoryBean -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.rest.client.config.RestClientMappingContext - -/** - * Spring Factory bean for constructing the RestClientMappingContext - * - * @author Graeme Rocher - * @since 1.0 - */ -class RestClientMappingContextFactoryBean extends AbstractMappingContextFactoryBean { - DefaultMappingHolder defaultMapping - - @Override - protected MappingContext createMappingContext() { - new RestClientMappingContext(defaultMapping.defaultMapping) - } -} -@Canonical -class DefaultMappingHolder { - Closure defaultMapping -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/plugin/support/RestClientMethodsConfigurer.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/plugin/support/RestClientMethodsConfigurer.groovy deleted file mode 100644 index cfcee300a..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/plugin/support/RestClientMethodsConfigurer.groovy +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client.plugin.support - -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.rest.client.RestClientGormEnhancer -import org.grails.datastore.gorm.rest.client.RestClientGormStaticApi -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.rest.client.RestClientDatastore -import org.springframework.transaction.PlatformTransactionManager -import org.grails.datastore.gorm.plugin.support.DynamicMethodsConfigurer - -/** - * Methods configurer for the GORM REST client - * - * @author Graeme Rocher - * @since 1.0 - */ -class RestClientMethodsConfigurer extends DynamicMethodsConfigurer { - RestClientMethodsConfigurer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - protected GormStaticApi createGormStaticApi(Class cls, List finders) { - return new RestClientGormStaticApi(cls, (RestClientDatastore)datastore, finders, transactionManager) - } - - @Override - protected GormEnhancer createEnhancer() { - return new RestClientGormEnhancer((RestClientDatastore)datastore, transactionManager) - } - - @Override - String getDatastoreType() { - "RestClient" - } -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/plugin/support/RestClientSpringConfigurer.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/plugin/support/RestClientSpringConfigurer.groovy deleted file mode 100644 index fc1306aa1..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/plugin/support/RestClientSpringConfigurer.groovy +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client.plugin.support - -import org.grails.datastore.mapping.rest.client.config.RestClientMappingContext -import org.grails.datastore.gorm.plugin.support.SpringConfigurer - -/** - * Spring configurer for the GORM REST client - * - * @author Graeme Rocher - * @since 1.0 - */ -class RestClientSpringConfigurer extends SpringConfigurer{ - @Override - String getDatastoreType() { - return "RestClient" - } - - @Override - Closure getSpringCustomizer() { - return { - def restClientConfig = application.config?.grails?.gorm?.restClient.clone() - final configuredDefaultMapping = restClientConfig?.default?.mapping - restclientMappingContext(RestClientMappingContextFactoryBean) { - grailsApplication = ref('grailsApplication') - pluginManager = ref('pluginManager') - defaultMapping = new DefaultMappingHolder(configuredDefaultMapping instanceof Closure ? configuredDefaultMapping : {}) - } - restclientDatastore(RestClientDatastoreFactoryBean) { - mappingContext = ref("restclientMappingContext") - connectionDetails = restClientConfig - } - } - } -} 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 deleted file mode 100644 index 4bd125a81..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/RestClientDatastore.groovy +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.rest.client - -import grails.plugins.rest.client.RestBuilder -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 -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.rest.client.config.Endpoint -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.springframework.beans.factory.annotation.Autowired -import org.springframework.context.ConfigurableApplicationContext -import org.springframework.web.client.RestTemplate - -import java.util.concurrent.ConcurrentHashMap -import org.grails.datastore.mapping.rest.client.http.converters.PersistentEntityListHttpConverter - -/** - * Datastore implementation for REST clients, provides some base configuration shared by REST clients - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class RestClientDatastore extends AbstractDatastore { - - public static final String SETTING_BASE_URL = "baseUrl" - public static final String DEFAULT_BASE_URL = "http://localhost:8080" - @Autowired(required = false) - RendererRegistry rendererRegistry - - @Autowired(required = false) - DataBindingSourceRegistry bindingSourceRegistry - - String baseUrl = DEFAULT_BASE_URL - - - Map asyncRestClients = new ConcurrentHashMap<>().withDefault { PersistentEntity entity -> - new AsyncRestBuilder(syncRestClients.get(entity)) - } - - Map syncRestClients = new ConcurrentHashMap<>().withDefault { PersistentEntity entity -> - final template = new RestTemplate(((Endpoint) entity.mapping.mappedForm).httpRequestFactory) - final converters = template.getMessageConverters() - converters.add(new PersistentEntityHttpConverter(entity, rendererRegistry, bindingSourceRegistry)) - converters.add(new PersistentEntityListHttpConverter(entity, rendererRegistry, bindingSourceRegistry)) - new RestBuilder(template) - } - - RestClientDatastore() { - this(new RestClientMappingContext()) - } - - RestClientDatastore(RestClientMappingContext mappingContext) { - this(mappingContext, Collections.emptyMap(), null) - } - - RestClientDatastore(RestClientMappingContext mappingContext, Map connectionDetails, ConfigurableApplicationContext ctx) { - this(mappingContext, connectionDetails, ctx, null) - } - - RestClientDatastore(RestClientMappingContext mappingContext, Map connectionDetails, ConfigurableApplicationContext ctx, TPCacheAdapterRepository cacheAdapterRepository) { - super(mappingContext, connectionDetails, ctx, cacheAdapterRepository) - - initialize(connectionDetails) - } - - protected void initialize(Map connectionDetails) { - DefaultRendererRegistry defaultRendererRegistry = new DefaultRendererRegistry() - defaultRendererRegistry.initialize() - rendererRegistry = defaultRendererRegistry - final defaultDataBindingSourceRegistry = new DefaultDataBindingSourceRegistry() - defaultDataBindingSourceRegistry.initialize() - - bindingSourceRegistry = defaultDataBindingSourceRegistry - - baseUrl = connectionDetails.get(SETTING_BASE_URL) ?: DEFAULT_BASE_URL - } - - @Override - protected Session createSession(Map connectionDetails) { - return new RestClientSession(this, mappingContext, applicationEventPublisher, cacheAdapterRepository) - } -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/RestClientException.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/RestClientException.groovy deleted file mode 100644 index 113fa0313..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/RestClientException.groovy +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.rest.client - -import org.grails.datastore.mapping.core.DatastoreException -import grails.plugins.rest.client.RestResponse - -/** - * Exception thrown from requests made by GORM for REST - * - * @author Graeme Rocher - * @since 1.0 - */ -class RestClientException extends DatastoreException { - RestResponse response - - RestClientException(String s, RestResponse response) { - super(s) - this.response = response - } - - RestClientException(String s, Throwable throwable, RestResponse response) { - super(s, throwable) - this.response = response - } -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/RestClientSession.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/RestClientSession.groovy deleted file mode 100644 index 86fbb999c..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/RestClientSession.groovy +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.rest.client - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository -import org.grails.datastore.mapping.core.AbstractSession -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.core.impl.PendingInsert -import org.grails.datastore.mapping.core.impl.PendingUpdate -import org.grails.datastore.mapping.engine.Persister -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.rest.client.engine.RestClientEntityPersister -import org.grails.datastore.mapping.transactions.SessionOnlyTransaction -import org.grails.datastore.mapping.transactions.Transaction -import org.springframework.context.ApplicationEventPublisher - -/** - * Session implementation for REST clients - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class RestClientSession extends AbstractSession{ - - static final String ATTRIBUTE_URL = "url" - static final String ATTRIBUTE_REQUEST_CUSTOMIZER = "request-customizer" - - RestClientSession(Datastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher) { - super(datastore, mappingContext, publisher) - } - - RestClientSession(Datastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher, boolean stateless) { - super(datastore, mappingContext, publisher, stateless) - } - - RestClientSession(Datastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher, TPCacheAdapterRepository cacheAdapterRepository) { - super(datastore, mappingContext, publisher, cacheAdapterRepository) - } - - RestClientSession(Datastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher, TPCacheAdapterRepository cacheAdapterRepository, boolean stateless) { - super(datastore, mappingContext, publisher, cacheAdapterRepository, stateless) - } - - @Override - Serializable insert(Object o) { - if(o) { - RestClientEntityPersister persister = (RestClientEntityPersister)getPersister(o) - if(persister != null) { - persister.insert(o) - } - } - } - - @Override - Object getNativeInterface() { - // no native interface, just return this - return this - } - - @Override - protected Persister createPersister(Class cls, MappingContext mappingContext) { - final entity = mappingContext.getPersistentEntity(cls.name) - if(entity != null) { - return new RestClientEntityPersister(mappingContext, entity, this, publisher) - } - else { - throw new IllegalArgumentException("Class [$cls.name] is not a persistent entity") - } - } - - @Override - protected Transaction beginTransactionInternal() { - return new SessionOnlyTransaction(this, this) - } -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/config/Endpoint.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/config/Endpoint.groovy deleted file mode 100644 index 1b9376675..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/config/Endpoint.groovy +++ /dev/null @@ -1,117 +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.grails.datastore.mapping.rest.client.config - -import com.google.gson.JsonElement -import grails.plugins.rest.client.RestBuilder -import groovy.transform.CompileStatic -import groovy.util.slurpersupport.GPathResult -import org.codehaus.groovy.grails.web.mime.MimeType -import org.grails.datastore.mapping.config.Entity -import org.springframework.http.client.SimpleClientHttpRequestFactory - -/** - * Represents a configured end point for an entity mapped to a REST resource - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class Endpoint extends Entity{ - - @Delegate SimpleClientHttpRequestFactory httpRequestFactory = new SimpleClientHttpRequestFactory() - /** - * The full URL to the end point - */ - String url - /** - * The URI to the endpoint. The full URL is established from the configuration - */ - String uri - /** - * The content type of the end point to pass to the Content-Type header when sending requests - */ - String contentType = MimeType.JSON.name - /** - * The accept type of the end point to pass to the Accept header when sending requests - */ - String accept - - Class acceptType - - /** - * Any addiitonal headers to be sent as part of the request - */ - Map headers = [:] - /** - * The timeout for establishing a connection (defaults to none) - */ - int connectTimeout = -1 - /** - * The timeout for reading data (defaults to none) - */ - int readTimeout = -1 - - /** - * Whether to issue requests asynchronously and rely on timeout - */ - boolean async = true - - - Endpoint() { - final proxy = RestBuilder.getProxyForSystemProperties() - if(proxy) { - httpRequestFactory.proxy = proxy - } - } - - /** - * Set the underlying URLConnection's connect timeout (in milliseconds). - * A timeout value of 0 specifies an infinite timeout. - *

    Default is the system's default timeout. - * @see URLConnection#setConnectTimeout(int) - */ - public void setConnectTimeout(int connectTimeout) { - this.connectTimeout = connectTimeout; - this.httpRequestFactory.setConnectTimeout(connectTimeout) - } - - /** - * Set the underlying URLConnection's read timeout (in milliseconds). - * A timeout value of 0 specifies an infinite timeout. - *

    Default is the system's default timeout. - * @see URLConnection#setReadTimeout(int) - */ - public void setReadTimeout(int readTimeout) { - this.readTimeout = readTimeout; - this.httpRequestFactory.setReadTimeout(readTimeout) - } - - int getConnectTimeout() { - return connectTimeout - } - - int getReadTimeout() { - return readTimeout - } - - String getAccept() { - return accept ?: contentType - } - - void setAccept(String accept) { - this.accept = accept - } -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/config/RestClientEntity.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/config/RestClientEntity.groovy deleted file mode 100644 index a85ce2ab6..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/config/RestClientEntity.groovy +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.rest.client.config - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.AbstractClassMapping -import org.grails.datastore.mapping.model.AbstractPersistentEntity -import org.grails.datastore.mapping.model.ClassMapping -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity - -/** - * Maps a domain class to a REST endpoint - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class RestClientEntity extends AbstractPersistentEntity{ - protected RestClientClassMapping classMapping - - RestClientEntity(Class javaClass, RestClientMappingContext context) { - super(javaClass, context) - this.classMapping = new RestClientClassMapping(this, context) - } - - - public ClassMapping getMapping() { - this.classMapping - } - - - class RestClientClassMapping extends AbstractClassMapping { - Endpoint mappedForm - RestClientClassMapping(PersistentEntity entity, RestClientMappingContext context) { - super(entity, context) - this.mappedForm = (Endpoint)getMappingContext().getMappingFactory().createMappedForm(entity) - } - } -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/config/RestClientMappingContext.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/config/RestClientMappingContext.groovy deleted file mode 100644 index e86c02b1c..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/config/RestClientMappingContext.groovy +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.rest.client.config - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.AbstractMappingContext -import org.grails.datastore.mapping.model.MappingConfigurationStrategy -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.model.config.GormMappingConfigurationStrategy - -/** - * Mapping context for the GORM REST client - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class RestClientMappingContext extends AbstractMappingContext { - - private MappingConfigurationStrategy syntaxStrategy; - RestClientMappingFactory mappingFactory - - RestClientMappingContext(Closure defaultMapping = null) { - this.mappingFactory = new RestClientMappingFactory() - if(defaultMapping) { - mappingFactory.setDefaultMapping(defaultMapping) - } - this.syntaxStrategy = new GormMappingConfigurationStrategy(mappingFactory) - - } - - @Override - MappingConfigurationStrategy getMappingSyntaxStrategy() { - return this.syntaxStrategy - } - - @Override - protected PersistentEntity createPersistentEntity(Class javaClass) { - return new RestClientEntity(javaClass, this) - } -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/config/RestClientMappingFactory.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/config/RestClientMappingFactory.groovy deleted file mode 100644 index ff7590d5c..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/config/RestClientMappingFactory.groovy +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.rest.client.config - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.config.AbstractGormMappingFactory -import org.grails.datastore.mapping.config.Property - -/** - * MappingFactory for the GORM REST client - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class RestClientMappingFactory extends AbstractGormMappingFactory { - @Override - protected Class getPropertyMappedFormType() { - Property - } - - @Override - protected Class getEntityMappedFormType() { - Endpoint - } -} 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 deleted file mode 100644 index 01ff64f80..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/engine/RestClientEntityPersister.groovy +++ /dev/null @@ -1,734 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.rest.client.engine - -import grails.async.Promise -import grails.async.PromiseList -import grails.plugins.rest.client.RestBuilder -import grails.plugins.rest.client.RestResponse -import grails.plugins.rest.client.async.AsyncRestBuilder -import grails.util.GrailsNameUtils -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 -import org.grails.datastore.mapping.engine.EntityPersister -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.query.Query -import org.grails.datastore.mapping.rest.client.RestClientDatastore -import org.grails.datastore.mapping.rest.client.config.Endpoint -import org.springframework.context.ApplicationEventPublisher -import org.springframework.http.HttpStatus - -import java.util.concurrent.TimeUnit -import org.grails.datastore.mapping.core.impl.PendingUpdateAdapter -import org.grails.datastore.mapping.engine.EntityAccess -import org.grails.datastore.mapping.rest.client.config.RestClientMappingContext -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 - -/** - * - * EntityPersister implementation for the REST client - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class RestClientEntityPersister extends EntityPersister { - RestClientEntityPersister(MappingContext mappingContext, PersistentEntity entity, Session session, ApplicationEventPublisher publisher) { - super(mappingContext, entity, session, publisher) - } - - @Override - protected List retrieveAllEntities(PersistentEntity pe, Serializable[] keys) { - return retrieveAllEntities(pe, Arrays.asList(keys)) - } - - @Override - protected List retrieveAllEntities(PersistentEntity pe, Iterable keys) { - Endpoint endpoint = (Endpoint)pe.mapping.mappedForm - RestClientDatastore datastore = (RestClientDatastore)getSession().datastore - final sessionUrl = session.getAttribute(pe, RestClientSession.ATTRIBUTE_URL) - final sessionRequestCustomizer = session.getAttribute(pe, RestClientSession.ATTRIBUTE_REQUEST_CUSTOMIZER) - - List results = [] - - MimeType mimeType = new MimeType(endpoint.contentType) - List responseResults = [] - if(endpoint.async) { - PromiseList promiseList = new PromiseList<>() - AsyncRestBuilder asyncRestBuilder = datastore.asyncRestClients.get(pe) - - int count = 0 - for(objectId in keys) { - count++ - final url = sessionUrl ? sessionUrl.toString() : establishUrl(datastore.baseUrl, endpoint, pe, objectId) - Map args = [:] - args.put(GrailsDomainClassProperty.IDENTITY, objectId) - - promiseList << asyncRestBuilder.get(url, args) { - accept endpoint.acceptType ?: pe.javaClass, endpoint.accept - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - if(sessionRequestCustomizer instanceof Closure) { - Closure callable = (Closure)sessionRequestCustomizer - callable.delegate = delegate - callable.call() - } - - } - } - - if(endpoint.readTimeout > -1) { - responseResults = promiseList.get(endpoint.readTimeout * count, TimeUnit.SECONDS) - } - else { - responseResults = promiseList.get() - } - } - else { - RestBuilder builder = datastore.syncRestClients.get(pe) - for(objectId in keys) { - final url = sessionUrl ? sessionUrl.toString() : establishUrl(datastore.baseUrl, endpoint, pe, objectId) - Map args = [:] - args.put(GrailsDomainClassProperty.IDENTITY, objectId) - - responseResults << builder.get(url, args) { - accept endpoint.acceptType ?: pe.javaClass, endpoint.accept - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - if(sessionRequestCustomizer instanceof Closure) { - Closure callable = (Closure)sessionRequestCustomizer - callable.delegate = delegate - callable.call() - } - } - } - } - - for(RestResponse response in responseResults) { - if(response.statusCode.series() == HttpStatus.Series.SUCCESSFUL) { - results << bindResponseToNewEntity(response, datastore, mimeType, pe) - } - else { - results << null - } - } - - return results - } - - @Override - protected List persistEntities(PersistentEntity entity, @SuppressWarnings("rawtypes") Iterable objs) { - Endpoint endpoint = (Endpoint)entity.mapping.mappedForm - RestClientDatastore datastore = (RestClientDatastore)getSession().datastore - if(endpoint.async) { - final objectList = objs.toList() - List identifiers = [] - Map updatesAndInserts = objectList.groupBy { getObjectIdentifier(it) ? 'updates' : 'inserts' } - SessionImplementor impl = (SessionImplementor)getSession() - Collection updates = (Collection)updatesAndInserts.get("updates") - if(updates) { - - for(Object update in updates) { - identifiers[objectList.indexOf(update)] = getObjectIdentifier(update) - } - - RestClientEntityPersister entityPersister = this - impl.addPendingUpdate(new PendingUpdateAdapter(entity, null, datastore.asyncRestClients.get(entity), null) { - @Override - void run() { - AsyncRestBuilder builder = getNativeEntry() - PromiseList updateResponses = new PromiseList() - int count = 0 - for(update in updates) { - final entityAccess = new EntityAccess(entity, update) - if( cancelUpdate(entity, entityAccess) ) continue - if( (update instanceof DirtyCheckable) && !getSession().isDirty(update) ) continue - - count++ - def identifier = identifiers[objectList.indexOf(update)] - final url = establishUrl(datastore.baseUrl, endpoint, entity, identifier) - Promise updatePromise = builder.put(url) { - contentType endpoint.contentType - accept endpoint.acceptType ?: entity.javaClass, endpoint.accept - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - body update - }.then { RestResponse response -> - if(response.statusCode.series() == HttpStatus.Series.SUCCESSFUL) { - entityPersister.firePostUpdateEvent(entity, entityAccess) - } - return response - } - - updateResponses << updatePromise - } - - List responses - if(endpoint.readTimeout > -1) - responses = updateResponses.get(endpoint.readTimeout * count, TimeUnit.SECONDS) - else - responses = updateResponses.get() - for(RestResponse response in responses) { - if(response.statusCode.series() != HttpStatus.Series.SUCCESSFUL) { - throw new RestClientException("Status code [${response.statusCode}] returned for PUT request", response) - } - } - } - }) - } - - Collection inserts = (Collection)updatesAndInserts.get("inserts") - - if(inserts) { - AsyncRestBuilder restBuilder = datastore.asyncRestClients.get(entity) - PromiseList insertResponses = new PromiseList() - int count = 0 - inserts = inserts.findAll() { !cancelInsert(entity, new EntityAccess(entity, it)) } - for(insert in inserts) { - count++ - final url = establishUrl(datastore.baseUrl, endpoint, entity) - Promise insertPromise = restBuilder.post(url) { - contentType endpoint.contentType - accept endpoint.acceptType ?: entity.javaClass, endpoint.accept - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - body insert - }.then { RestResponse response -> - if(response.statusCode.series() == HttpStatus.Series.SUCCESSFUL) { - firePostInsertEvent(entity, new EntityAccess(entity, insert)) - } - - return response - } - - insertResponses << insertPromise - } - - List responses - if(endpoint.readTimeout > -1) - responses = insertResponses.get(endpoint.readTimeout * count, TimeUnit.SECONDS) - else - responses = insertResponses.get() - - responses.eachWithIndex { RestResponse response, int index -> - if(response.statusCode.series() != HttpStatus.Series.SUCCESSFUL) { - throw new RestClientException("Status code [${response.statusCode}] returned for POST request", response) - } - - def object = inserts[index] - final identifier = getObjectIdentifierFromResponseBody(datastore, response, new MimeType(endpoint.accept), entity, object) - identifiers[objectList.indexOf(object)] = identifier - } - } - - - return identifiers - } - else { - return objs.collect { persistEntity(entity, it) } - } - } - - @Override - protected Object retrieveEntity(PersistentEntity pe, Serializable key) { - Endpoint endpoint = (Endpoint)pe.mapping.mappedForm - RestClientDatastore datastore = (RestClientDatastore)getSession().datastore - - final url = establishUrl(datastore.baseUrl, endpoint, pe, key) - MimeType mimeType = new MimeType(endpoint.contentType) - RestResponse response = executeGet(endpoint, datastore, pe, url, key) - - if(response.statusCode == HttpStatus.OK) { - return bindResponseToNewEntity(response, datastore, mimeType, pe) - } - return null - } - - private RestResponse executeGet(Endpoint endpoint, RestClientDatastore datastore, PersistentEntity pe, String url, Serializable identifier) { - final sessionUrl = session.getAttribute(pe, RestClientSession.ATTRIBUTE_URL) - final sessionRequestCustomizer = session.getAttribute(pe, RestClientSession.ATTRIBUTE_REQUEST_CUSTOMIZER) - url = sessionUrl ? sessionUrl.toString() : url - Map args = [:] - args.put(GrailsDomainClassProperty.IDENTITY, identifier) - - RestResponse response - if (endpoint.async) { - AsyncRestBuilder builder = datastore.asyncRestClients.get(pe) - Promise promise = builder.get(url, args) { - accept endpoint.acceptType ?: pe.javaClass, endpoint.accept - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - if(sessionRequestCustomizer instanceof Closure) { - Closure callable = (Closure)sessionRequestCustomizer - callable.delegate = delegate - callable.call() - } - } - if (endpoint.readTimeout > -1) { - response = promise.get(endpoint.readTimeout, TimeUnit.SECONDS) - } - else { - response = promise.get() - } - } - else { - RestBuilder builder = datastore.syncRestClients.get(pe) - response = builder.get(url, args) { - accept endpoint.acceptType ?: pe.javaClass, endpoint.accept - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - if(sessionRequestCustomizer instanceof Closure) { - Closure callable = (Closure)sessionRequestCustomizer - callable.delegate = delegate - callable.call() - } - } - } - response - } - - private Object bindResponseToNewEntity(RestResponse response, RestClientDatastore datastore, MimeType mimeType, PersistentEntity pe) { - final body = response.body - if(body) { - if(pe.javaClass.isInstance(body)) { - final entityAccess = new EntityAccess(pe, body) - if( cancelLoad(pe, entityAccess)) return null - else { - try { - return body - } finally { - firePostLoadEvent(pe, entityAccess) - } - } - } - else { - final bindingSourceRegistry = datastore.bindingSourceRegistry - DataBindingSource bindingSource = body ? bindingSourceRegistry.createDataBindingSource(mimeType, pe.javaClass, body) : null - Object instance = null - if (bindingSource && bindingSource.hasIdentifier()) { - instance = pe.newInstance() - instance[pe.getIdentity().name] = mappingContext.getConversionService().convert(bindingSource.getIdentifierValue(), pe.getIdentity().getType()) - - DataBindingUtils.bindObjectToInstance(instance, bindingSource) - } - final entityAccess = new EntityAccess(pe, body) - if( cancelLoad(pe, entityAccess)) return null - else { - try { - return instance - } finally { - firePostLoadEvent(pe, entityAccess) - } - } - - } - } - return null - } - - @Override - protected Serializable persistEntity(PersistentEntity pe, Object obj) { - Endpoint endpoint = (Endpoint)pe.mapping.mappedForm - - final Session session = getSession() - RestClientDatastore datastore = (RestClientDatastore) session.datastore - - final identifier = getObjectIdentifier(obj) - if(identifier) { - // do update - final entityAccess = new EntityAccess(pe, obj) - if( cancelUpdate(pe, entityAccess) ) return getObjectIdentifier(obj) - if( (obj instanceof DirtyCheckable) && !session.isDirty(obj) ) { - return getObjectIdentifier(obj) - } - - SessionImplementor impl = (SessionImplementor) session - if(endpoint.async) { - impl.addPendingUpdate(new PendingUpdateAdapter(pe, identifier, datastore.asyncRestClients.get(pe), new EntityAccess(pe, obj)) { - @Override - void run() { - AsyncRestBuilder builder = getNativeEntry() - final sessionUrl = session.getAttribute(obj, RestClientSession.ATTRIBUTE_URL) - final sessionRequestCustomizer = session.getAttribute(obj, RestClientSession.ATTRIBUTE_REQUEST_CUSTOMIZER) - - final url = sessionUrl ? sessionUrl.toString() : establishUrl(datastore.baseUrl, endpoint, pe, identifier) - Map args = [:] - args.put('id', identifier) - Promise responsePromise = builder.put(url, args) { - contentType endpoint.contentType - accept endpoint.acceptType ?: pe.javaClass, endpoint.accept - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - body obj - if(sessionRequestCustomizer instanceof Closure) { - Closure callable = (Closure)sessionRequestCustomizer - callable.delegate = delegate - callable.call() - } - } - RestResponse response - if(endpoint.readTimeout > -1) - response = responsePromise.get(endpoint.readTimeout, TimeUnit.SECONDS) - else - response = responsePromise.get() - if(response.statusCode.series() != HttpStatus.Series.SUCCESSFUL) { - throw new RestClientException("Status code [${response.statusCode}] returned for PUT request to URL [$url]", response) - } - else { - firePostUpdateEvent(pe, new EntityAccess(pe, obj)) - } - } - }) - } - else { - RestBuilder restBuilder = datastore.syncRestClients.get(pe) - final sessionUrl = session.getAttribute(obj, RestClientSession.ATTRIBUTE_URL) - final sessionRequestCustomizer = session.getAttribute(obj, RestClientSession.ATTRIBUTE_REQUEST_CUSTOMIZER) - - final url = sessionUrl ? sessionUrl.toString() : establishUrl(datastore.baseUrl, endpoint, pe, identifier) - Map args = [:] - args['id'] = identifier - final RestResponse response = restBuilder.put(url, args) { - contentType endpoint.contentType - accept endpoint.acceptType ?: pe.javaClass, endpoint.accept - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - body obj - if(sessionRequestCustomizer instanceof Closure) { - Closure callable = (Closure)sessionRequestCustomizer - callable.delegate = delegate - callable.call() - } - - } - if(response.statusCode.series() != HttpStatus.Series.SUCCESSFUL) { - throw new RestClientException("Status code [${response.statusCode}] returned for PUT request to URL [$url]", response) - } - else { - firePostUpdateEvent(pe, entityAccess) - } - } - } - else { - return executeInsert(datastore, endpoint, pe, obj) - } - - return identifier - } - - @Override - Serializable insert(Object obj) { - RestClientMappingContext mappingContext = (RestClientMappingContext )getMappingContext() - final entity = mappingContext.getPersistentEntity(obj.getClass().name) - Endpoint endpoint = (Endpoint)entity.mapping.mappedForm - - final identifier = getObjectIdentifier(obj) - if(identifier) { - RestClientDatastore datastore = (RestClientDatastore)getSession().datastore - SessionImplementor impl = (SessionImplementor)getSession() - impl.addPendingInsert(new PendingInsertAdapter(entity, identifier, datastore.asyncRestClients.get(entity), new EntityAccess(entity, obj)) { - - @Override - void run() { - executeInsert(datastore,endpoint, entity, obj) - } - }) - return identifier - } - else { - return executeInsert((RestClientDatastore)getSession().datastore, endpoint, entity, obj) - } - } - - public Serializable executeInsert(RestClientDatastore datastore, Endpoint endpoint, PersistentEntity pe, obj) { - final sessionUrl = session.getAttribute(obj, RestClientSession.ATTRIBUTE_URL) - final sessionRequestCustomizer = session.getAttribute(obj, RestClientSession.ATTRIBUTE_REQUEST_CUSTOMIZER) - - - final url = sessionUrl ? sessionUrl.toString() : establishUrl(datastore.baseUrl, endpoint, pe) - RestResponse response - MimeType mimeType = new MimeType(endpoint.contentType) - final entityAccess = new EntityAccess(pe, obj) - if( cancelInsert(pe, entityAccess) ) return null - if (endpoint.async) { - AsyncRestBuilder builder = datastore.asyncRestClients.get(pe) - Promise result = builder.post(url) { - contentType endpoint.contentType - accept endpoint.acceptType ?: pe.javaClass, endpoint.accept - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - body obj - if(sessionRequestCustomizer instanceof Closure) { - Closure callable = (Closure)sessionRequestCustomizer - callable.delegate = delegate - callable.call() - } - }.then { RestResponse r -> - if(r.statusCode.series() == HttpStatus.Series.SUCCESSFUL) { - firePostInsertEvent(pe, entityAccess) - } - return r - } - if (endpoint.readTimeout > -1) { - response = result.get(endpoint.readTimeout, TimeUnit.SECONDS) - } - else { - response = result.get() - } - } else { - RestBuilder builder = datastore.syncRestClients.get(pe) - response = builder.post(url) { - contentType endpoint.contentType - accept endpoint.acceptType ?: pe.javaClass, endpoint.accept - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - body obj - if(sessionRequestCustomizer instanceof Closure) { - Closure callable = (Closure)sessionRequestCustomizer - callable.delegate = delegate - callable.call() - } - } - if(response.statusCode.series() == HttpStatus.Series.SUCCESSFUL) { - firePostInsertEvent(pe, entityAccess) - } - } - - return getObjectIdentifierFromResponseBody(datastore, response, mimeType, pe, obj) - } - - protected Serializable getObjectIdentifierFromResponseBody(RestClientDatastore datastore, RestResponse response, MimeType mimeType, PersistentEntity pe, obj) { - final bindingSourceRegistry = datastore.bindingSourceRegistry - final body = response.body - if(body) { - if(pe.isInstance(body)) { - final identifier = getObjectIdentifier(body) - obj[pe.getIdentity().name] = identifier - return identifier - } - else { - DataBindingSource bindingSource = body ? bindingSourceRegistry.createDataBindingSource(mimeType, pe.javaClass, body) : null - if (bindingSource) { - final objectId = (Serializable) bindingSource.getIdentifierValue() - if (objectId) { - Serializable convertedId = (Serializable)mappingContext.getConversionService().convert(objectId, pe.getIdentity().getType()) - obj[pe.getIdentity().name] = convertedId - return convertedId - } - return objectId - } - else { - return getObjectIdentifier(obj) - } - } - - } - else { - return getObjectIdentifier(obj) - } - } - - String establishUrl(String baseUrl, Endpoint endpoint, PersistentEntity entity, Object identifier) { - final url = establishUrl(baseUrl, endpoint, entity) - return "$url/$identifier" - } - - String establishUrl(String baseUrl, Endpoint endpoint, PersistentEntity entity) { - if(endpoint.url) { - return endpoint.url - } - else { - if(endpoint.uri) { - return new URL(new URL(baseUrl), endpoint.uri).toString() - } - else { - return new URL(new URL(baseUrl), "/${GrailsNameUtils.getPropertyName(entity.javaClass)}").toString() - } - } - } - - @Override - protected void deleteEntity(PersistentEntity pe, Object object) { - if(object) { - final entityAccess = new EntityAccess(pe, object) - if( cancelDelete(pe, entityAccess) ) return - final id = getObjectIdentifier(object) - if(id) { - Endpoint endpoint = (Endpoint)pe.mapping.mappedForm - RestClientDatastore datastore = (RestClientDatastore)getSession().datastore - final sessionUrl = session.getAttribute(object, RestClientSession.ATTRIBUTE_URL) - final sessionRequestCustomizer = session.getAttribute(object, RestClientSession.ATTRIBUTE_REQUEST_CUSTOMIZER) - - final url = sessionUrl ? sessionUrl.toString() : establishUrl(datastore.baseUrl, endpoint, pe, id) - if(endpoint.async) { - AsyncRestBuilder builder = datastore.asyncRestClients.get(pe) - Map args = [:] - args.put('id', id) - Promise result = builder.delete(url, args) { - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - if(sessionRequestCustomizer instanceof Closure) { - Closure callable = (Closure)sessionRequestCustomizer - callable.delegate = delegate - callable.call() - } - }.then { RestResponse response -> - if(response.statusCode.series() == HttpStatus.Series.SUCCESSFUL) { - firePostDeleteEvent(pe, entityAccess) - } - - return response - } - RestResponse response - if(endpoint.readTimeout>-1) { - response = result.get(endpoint.readTimeout, TimeUnit.SECONDS) - } - else { - response = result.get() - } - if(response.statusCode.series() != HttpStatus.Series.SUCCESSFUL) { - throw new RestClientException("Invalid status code [${response.statusCode}] returned for DELETE request to URL [$url]", response) - } - - } else { - RestBuilder builder = datastore.syncRestClients.get(pe) - Map args = [:] - args.put('id', id) - RestResponse response = builder.delete(url, args) { - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - if(sessionRequestCustomizer instanceof Closure) { - Closure callable = (Closure)sessionRequestCustomizer - callable.delegate = delegate - callable.call() - } - } - if(response.statusCode.series() != HttpStatus.Series.SUCCESSFUL) { - throw new RestClientException("Invalid status code [${response.statusCode}] returned for DELETE request to URL [$url]", response) - } - else { - firePostDeleteEvent(pe, entityAccess) - } - - } - } - } - - } - - @Override - protected void deleteEntities(PersistentEntity pe, @SuppressWarnings("rawtypes") Iterable objects) { - Endpoint endpoint = (Endpoint)pe.mapping.mappedForm - RestClientDatastore datastore = (RestClientDatastore)getSession().datastore - if(endpoint.async) { - AsyncRestBuilder restBuilder = datastore.asyncRestClients.get(pe) - PromiseList promiseList = new PromiseList() - int count = 0 - for(obj in objects) { - if( cancelDelete(pe, new EntityAccess(pe, obj)) ) continue - count++ - final id = getObjectIdentifier(obj) - if(id) { - final url = establishUrl(datastore.baseUrl, endpoint, pe, id) - Promise deletePromise = restBuilder.delete(url) { - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - } - deletePromise.then { RestResponse response -> - if(response && response.statusCode.series() == HttpStatus.Series.SUCCESSFUL) - firePostDeleteEvent(pe, new EntityAccess(pe, obj)) - } - promiseList << deletePromise - } - } - List responses - if(endpoint.readTimeout>-1) { - responses = promiseList.get(endpoint.readTimeout*count, TimeUnit.SECONDS) - } - else { - responses = promiseList.get() - } - - for(RestResponse response in responses) { - if(response.statusCode.series() != HttpStatus.Series.SUCCESSFUL) { - throw new RestClientException("Invalid status code [${response.statusCode}] returned for DELETE request. Message", response) - } - } - } - else { - for(o in objects) { - deleteEntity(pe, o) - } - } - } - - @Override - Query createQuery() { - return new RequestParameterRestClientQuery(getSession(), getPersistentEntity()) - } - - @Override - Serializable refresh(Object o) { - if(o == null) return null - - final entity = getMappingContext().getPersistentEntity(o.getClass().name) - - if(entity == null) throw new IllegalArgumentException("Argument [$o] is not a persistent entity") - - Endpoint endpoint = (Endpoint)entity.mapping.mappedForm - RestClientDatastore datastore = (RestClientDatastore)getSession().datastore - - - final id = getObjectIdentifier(o) - if(id == null) return null - - final url = establishUrl(datastore.baseUrl, endpoint, entity, id) - MimeType mimeType = new MimeType(endpoint.contentType) - RestResponse response = executeGet(endpoint, datastore, entity, url, id) - - if(response.statusCode.series() == HttpStatus.Series.SUCCESSFUL) { - final body = response.body - final bindingSourceRegistry = datastore.bindingSourceRegistry - DataBindingSource bindingSource = body ? bindingSourceRegistry.createDataBindingSource(mimeType, entity.javaClass, body) : null - if (bindingSource) { - DataBindingUtils.bindObjectToInstance(o, bindingSource) - } - } - return (Serializable)id - } -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/HttpOutputMessageRenderContext.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/HttpOutputMessageRenderContext.groovy deleted file mode 100644 index 14985b490..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/HttpOutputMessageRenderContext.groovy +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.rest.client.http.converters - -import grails.rest.render.RenderContext -import org.codehaus.groovy.grails.web.mime.MimeType -import org.grails.datastore.mapping.rest.client.config.Endpoint -import org.springframework.http.HttpMethod -import org.springframework.http.HttpOutputMessage -import org.springframework.http.HttpStatus -import org.springframework.http.MediaType - -import java.nio.charset.Charset - -/** - * A render context for RestTemplate - * - * @author Graeme Rocher - * @since 1.0 - */ -class HttpOutputMessageRenderContext implements RenderContext{ - - HttpOutputMessage httpOutputMessage - Endpoint endpoint - HttpMethod httpMethod - List includes = null - List excludes = [] - - HttpOutputMessageRenderContext(HttpMethod httpMethod, HttpOutputMessage httpOutputMessage, Endpoint endpoint) { - this.httpOutputMessage = httpOutputMessage - this.endpoint = endpoint - this.httpMethod = httpMethod - } - - @Override - Map getArguments() { - return Collections.emptyMap() - } - - @Override - String getResourcePath() { - endpoint.url - } - - @Override - MimeType getAcceptMimeType() { - final acceptList = httpOutputMessage.headers.getAccept() - if(acceptList) { - return new MimeType(acceptList[0].toString()) - } - return null - } - - @Override - Locale getLocale() { - return Locale.getDefault() - } - - @Override - Writer getWriter() { - return new OutputStreamWriter(httpOutputMessage.getBody(), getCharSetForMediaType(httpOutputMessage.headers.getContentType())) - } - - @Override - HttpMethod getHttpMethod() { - return this.httpMethod - } - - @Override - String getActionName() { null } - - @Override - String getControllerName() { null } - - @Override - String getViewName() { null } - - @Override - void setStatus(HttpStatus status) { - // noop, can't set status for output message - } - - @Override - void setContentType(String contentType) { - httpOutputMessage.headers.setContentType(MediaType.valueOf(contentType)) - } - - @Override - void setViewName(String viewName) { - // noop, can't set view for output message - } - - @Override - void setModel(Map model) { - // noop, can't set model for output message - } - - - protected Charset getCharSetForMediaType(MediaType contentType) { - contentType ? (contentType.charSet ? contentType.charSet : Charset.forName("UTF-8")) : Charset.forName("UTF-8") - } - -} 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 deleted file mode 100644 index a40625ca1..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/PersistentEntityHttpConverter.groovy +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.rest.client.http.converters - -import grails.rest.render.RendererRegistry -import grails.util.GrailsNameUtils -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.springframework.http.HttpInputMessage -import org.springframework.http.HttpMethod -import org.springframework.http.HttpOutputMessage -import org.springframework.http.MediaType -import org.springframework.http.converter.AbstractHttpMessageConverter -import org.springframework.http.converter.HttpMessageNotReadableException -import org.springframework.http.converter.HttpMessageNotWritableException - -/** - * A message converter for converting entities - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class PersistentEntityHttpConverter extends AbstractHttpMessageConverter{ - PersistentEntity entity - RendererRegistry rendererRegistry - DataBindingSourceRegistry dataBindingSourceRegistry - - PersistentEntityHttpConverter(PersistentEntity entity, RendererRegistry rendererRegistry, DataBindingSourceRegistry dataBindingSourceRegistry) { - super(MediaType.ALL) - this.entity = entity - this.rendererRegistry = rendererRegistry - this.dataBindingSourceRegistry = dataBindingSourceRegistry - } - - @Override - protected boolean supports(Class clazz) { - return entity.javaClass == clazz - } - - @Override - protected T readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - final contentType = inputMessage.headers.getContentType() ?: MediaType.APPLICATION_JSON - - final bindingSource = dataBindingSourceRegistry.createDataBindingSource(new MimeType(contentType.toString()), clazz, inputMessage.body) - if(bindingSource) { - final instance = clazz.newInstance() - if(bindingSource.hasIdentifier()) { - final idValue = bindingSource.getIdentifierValue() - final entityIdentityProperty = entity.identity - instance[entityIdentityProperty.name] = entity.mappingContext.conversionService.convert(idValue, entityIdentityProperty.type) - } - DataBindingUtils.bindObjectToInstance(instance, bindingSource) - return instance - } - else { - return null - } - } - - @Override - protected void writeInternal(T t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { - final contentType = outputMessage.headers.getContentType() ?: MediaType.APPLICATION_JSON - final renderer = rendererRegistry.findRenderer(new MimeType(contentType.toString()), t) - - final renderContext = new HttpOutputMessageRenderContext(HttpMethod.POST, outputMessage, (Endpoint) entity.mapping.mappedForm) { - @Override - String getActionName() { - return "show" - } - - @Override - String getControllerName() { - return GrailsNameUtils.getPropertyName(t.getClass()) - } - } - renderer.render(t, renderContext) - } -} 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 deleted file mode 100644 index 4040e7d4d..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/http/converters/PersistentEntityListHttpConverter.groovy +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.rest.client.http.converters - -import grails.rest.render.RendererRegistry -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.springframework.http.HttpInputMessage -import org.springframework.http.HttpOutputMessage -import org.springframework.http.MediaType -import org.springframework.http.converter.AbstractHttpMessageConverter -import org.springframework.http.converter.HttpMessageNotReadableException -import org.springframework.http.converter.HttpMessageNotWritableException - -/** - * An http converter capable of returning a list of entity results - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class PersistentEntityListHttpConverter extends AbstractHttpMessageConverter>{ - PersistentEntity entity - RendererRegistry rendererRegistry - DataBindingSourceRegistry dataBindingSourceRegistry - - PersistentEntityListHttpConverter(PersistentEntity entity, RendererRegistry rendererRegistry, DataBindingSourceRegistry dataBindingSourceRegistry) { - super(MediaType.ALL) - this.entity = entity - this.rendererRegistry = rendererRegistry - this.dataBindingSourceRegistry = dataBindingSourceRegistry - } - - @Override - protected boolean supports(Class clazz) { - return clazz == List - } - - @Override - boolean canWrite(Class clazz, MediaType mediaType) { - return false; - } - - @Override - protected List readInternal(Class> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - final contentType = inputMessage.headers.getContentType() ?: MediaType.APPLICATION_JSON - - final bindingSource = dataBindingSourceRegistry.createCollectionDataBindingSource(new MimeType(contentType.toString()), entity.javaClass, inputMessage.body) - if(bindingSource) { - List results = [] - DataBindingUtils.bindToCollection(entity.javaClass, results, bindingSource) - return results - } - else { - return [] - } - } - - @Override - protected void writeInternal(List t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { - throw new UnsupportedOperationException("Writing of list [$t] not supported") - } -} - diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/query/RequestParameterRestClientQuery.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/query/RequestParameterRestClientQuery.groovy deleted file mode 100644 index 1dd5087c6..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/query/RequestParameterRestClientQuery.groovy +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.rest.client.query - -import org.grails.datastore.mapping.query.Query -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.core.Session -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.rest.client.engine.RestClientEntityPersister -import org.grails.datastore.mapping.rest.client.config.Endpoint -import org.grails.datastore.mapping.rest.client.RestClientDatastore -import org.grails.datastore.mapping.rest.client.util.UrlBuilder -import grails.plugins.rest.client.async.AsyncRestBuilder -import grails.plugins.rest.client.RestResponse -import grails.async.Promise -import java.util.concurrent.TimeUnit -import grails.plugins.rest.client.RestBuilder -import static org.grails.datastore.mapping.query.Query.* - -/** - * A very simple implementation of the {@link Query} abstract class that uses query parameters to the REST endpoint to execute a query. - * - * The implementation only supports {@link org.grails.datastore.mapping.query.Query.Conjunction} and {@link org.grails.datastore.mapping.query.Query.Equals} criterion. All other - * criterion simply throw @{@link UnsupportedOperationException} - * - * Queries are generated in the form http://myhost/endpoint?foo=bar&bar=foo&max=10&offset=0 - * - * The server is required to handle the parameters as appropriate. - */ -@CompileStatic -class RequestParameterRestClientQuery extends Query { - - RequestParameterRestClientQuery(Session session, PersistentEntity entity) { - super(session, entity) - } - - @Override - protected List executeQuery(PersistentEntity entity, Query.Junction criteria) { - final datastore = (RestClientDatastore) session.datastore - final entityPersister = (RestClientEntityPersister)session.getPersister(entity) - Endpoint endpoint = (Endpoint)entity.mapping.mappedForm - - UrlBuilder urlBuilder = new UrlBuilder(entityPersister.establishUrl(datastore.baseUrl,endpoint, entity)) - if(offset > 0) { - urlBuilder.addParam("offset", offset) - } - if(max > -1) { - urlBuilder.addParam("max", max) - } - - if(criteria instanceof Query.Conjunction) { - Query.Conjunction conjunction = (Query.Conjunction)criteria - - for(Query.Criterion c in conjunction.getCriteria()) { - if(c instanceof Equals) { - Equals equals = (Equals) c - urlBuilder.addParam(equals.getProperty(), equals.value) - } - else { - throw new UnsupportedOperationException("Only equals queries are supported by implementation") - } - } - - - RestResponse response - if(endpoint.async) { - AsyncRestBuilder builder = datastore.asyncRestClients.get(entity) - Promise promise = builder.get(urlBuilder.toString()) { - accept List, endpoint.accept - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - } - if (endpoint.readTimeout > -1) { - response = promise.get(endpoint.readTimeout, TimeUnit.SECONDS) - } - else { - response = promise.get() - } - } - else { - RestBuilder builder = datastore.syncRestClients.get(entity) - response = builder.get(urlBuilder.toString()) { - accept List, endpoint.accept - for (entry in endpoint.headers.entrySet()) { - header entry.key, entry.value - } - } - } - - return (List)response.getBody() - } - else { - throw new UnsupportedOperationException("Only conjunctions are supported by query implementation") - } - } -} diff --git a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/util/UrlBuilder.groovy b/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/util/UrlBuilder.groovy deleted file mode 100644 index 378cf4089..000000000 --- a/grails-datastore-gorm-rest-client/src/main/groovy/org/grails/datastore/mapping/rest/client/util/UrlBuilder.groovy +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.mapping.rest.client.util - -import groovy.transform.CompileStatic - -/** - * Simply utility class for building URLs - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class UrlBuilder { - - StringBuilder url - private boolean first = true - private boolean hasPrevious = false - - UrlBuilder(String baseUrl) { - url = new StringBuilder(baseUrl) - } - - void addParam(String name, value) { - if(first) { - url << '?' - first = false - } - - if(hasPrevious) { - url << '&' - } - else { - hasPrevious = true - } - url << name << '=' << value - } - - @Override - String toString() { - url.toString() - } -} 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 deleted file mode 100644 index d5350971f..000000000 --- a/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/RestClientDatastoreSpec.groovy +++ /dev/null @@ -1,61 +0,0 @@ -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 org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.gorm.plugin.support.DynamicMethodsConfigurer -import org.grails.datastore.gorm.rest.client.plugin.support.RestClientMethodsConfigurer - -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.springframework.context.support.GenericApplicationContext -import spock.lang.Shared -import spock.lang.Specification - -/** - * @author Graeme Rocher - */ -abstract class RestClientDatastoreSpec extends Specification{ - - @Shared RestClientDatastore datastore - RestClientSession session - - - void setupSpec() { - final application = new DefaultGrailsApplication(getDomainClasses() as Class[], new GroovyClassLoader()) - application.initialise() - new ConvertersConfigurationInitializer().initialize(application) - - def applicationContext = new GenericApplicationContext() - applicationContext.refresh() - datastore = new RestClientDatastore() - datastore.applicationContext = applicationContext - for (cls in getDomainClasses()) { - datastore.mappingContext.addPersistentEntity(cls) - } - - def txMgr = new DatastoreTransactionManager(datastore: datastore) - DynamicMethodsConfigurer methodsConfigurer = new RestClientMethodsConfigurer(datastore, txMgr) - methodsConfigurer.configure() - - - datastore.applicationContext.addApplicationListener new DomainEventListener(datastore) - datastore.applicationContext.addApplicationListener new AutoTimestampEventListener(datastore) - - - } - - void cleanupSpec() { - ConvertersConfigurationHolder.clear() - } - - void setup() { - session = (RestClientSession)datastore.connect() - } - - abstract List getDomainClasses() -} 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 deleted file mode 100644 index bdfdfc0e7..000000000 --- a/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/json/CrudJsonSpec.groovy +++ /dev/null @@ -1,354 +0,0 @@ -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 org.springframework.http.HttpMethod -import org.springframework.http.MediaType -import org.springframework.test.web.client.MockRestServiceServer -import org.springframework.web.client.RestTemplate - -import static org.springframework.test.web.client.match.MockRestRequestMatchers.content -import static org.springframework.test.web.client.match.MockRestRequestMatchers.header -import static org.springframework.test.web.client.match.MockRestRequestMatchers.method -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo -import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess -import org.springframework.http.HttpStatus -import org.grails.datastore.gorm.rest.client.RestClientDatastoreSpec - -/** - * @author Graeme Rocher - */ -class CrudJsonSpec extends RestClientDatastoreSpec{ - - void "Test the list method issues a GET request and binds the results to a list of entities"() { - when:"An entity is retrieved with the get method" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString())) - .andRespond(withSuccess('[{"id":1, "title":"The Stand", "pages":200}]', MediaType.APPLICATION_JSON)) - - List results = Book.list() - - then:"The number of books that exist is correct" - results.size() == 1 - results[0].title == "The Stand" - results[0].pages == 200 - results[0].id == 1L - - } - - void "Test the list method with pagination arguments issues a GET request and binds the results to a list of entities"() { - when:"An entity is retrieved with the get method" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book?offset=5&max=10")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString())) - .andRespond(withSuccess('[{"id":1, "title":"The Stand", "pages":200}]', MediaType.APPLICATION_JSON)) - - List results = Book.list(offset:5, max:10) - - then:"The number of books that exist is correct" - results.size() == 1 - results[0].title == "The Stand" - results[0].pages == 200 - results[0].id == 1L - - } - - void "Test the get method issues a GET request and binds the result to the entity"() { - when:"An entity is retrieved with the get method" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book/1")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString())) - .andRespond(withSuccess('{"id":1, "title":"The Stand", "pages":200}', MediaType.APPLICATION_JSON)) - - Book b = Book.get(1) - - then:"The number of books that exist is correct" - b != null - b.id == 1L - b.title == "The Stand" - b.pages == 200 - mockServer.verify() - - } - - void "Test the get method issues a GET request and binds the result to the entity when using a custom URL"() { - when:"An entity is retrieved with the get method" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book-custom/1")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(header('Foo', 'Bar')) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString())) - .andRespond(withSuccess('{"id":1, "title":"The Stand", "pages":200}', MediaType.APPLICATION_JSON)) - - Book b = Book.get(new URL("http://localhost:8080/book-custom/{id}"), 1) { - headers['Foo'] = 'Bar' - } - - then:"The number of books that exist is correct" - b != null - b.id == 1L - b.title == "The Stand" - b.pages == 200 - mockServer.verify() - - } - - void "Test the getAll method issues a GET request and binds the result to the entity"() { - when:"An entity is retrieved with the get method" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book/1")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString())) - .andRespond(withSuccess('{"id":1, "title":"The Stand", "pages":200}', MediaType.APPLICATION_JSON)) - - List books = Book.getAll([1]) - - then:"The number of books that exist is correct" - books - books[0] != null - books[0].id == 1L - books[0].title == "The Stand" - books[0].pages == 200 - mockServer.verify() - - } - - void "Test the saveAll method issues a POST request with the correct data"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.POST)) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) - .andExpect(content().string('{"class":"org.grails.datastore.gorm.rest.client.json.Book","id":null,"pages":null,"title":"The Stand"}')) - .andRespond(withSuccess('{"id":1, "title":"The Stand"}', MediaType.APPLICATION_JSON)) - - mockServer.expect(requestTo("http://localhost:8080/book/2")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.PUT)) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) - .andExpect(content().string('{"class":"org.grails.datastore.gorm.rest.client.json.Book","id":2,"pages":null,"title":"The Shining"}')) - .andRespond(withSuccess('{"id":2, "title":"The Shining"}', MediaType.APPLICATION_JSON)) - - - def b = new Book(title: "The Stand") - def b2 = new Book(title: "The Shining") - b2.id = 2L - def ids = Book.withSession { session -> - def identifiers = Book.saveAll([b, b2]) - session.flush() - return identifiers - } - - - then:"The number of books that exist is correct" - b.id == 1L - ids == [1L, 2L] - mockServer.verify() - - } - - void "Test the save method issues a POST request with the correct data"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.POST)) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) - .andExpect(content().string('{"class":"org.grails.datastore.gorm.rest.client.json.Book","id":null,"pages":null,"title":"The Stand"}')) - .andRespond(withSuccess('{"id":1, "title":"The Stand"}', MediaType.APPLICATION_JSON)) - - def b = new Book(title: "The Stand") - b.save() - - then:"The number of books that exist is correct" - b.id == 1L - mockServer.verify() - - } - - void "Test the save method issues a POST request with the correct data when passing a custom URL and headers"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/other-books")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(header('Foo', 'Bar')) - .andExpect(method(HttpMethod.POST)) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) - .andExpect(content().string('{"class":"org.grails.datastore.gorm.rest.client.json.Book","id":null,"pages":null,"title":"The Stand"}')) - .andRespond(withSuccess('{"id":1, "title":"The Stand"}', MediaType.APPLICATION_JSON)) - - def b = new Book(title: "The Stand") - b.save(new URL("http://localhost:8080/other-books")) { - headers['Foo'] = 'Bar' - } - - then:"The number of books that exist is correct" - b.id == 1L - mockServer.verify() - - } - - - void "Test the insert method issues a POST request with the correct data"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.POST)) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) - .andExpect(content().string('{"class":"org.grails.datastore.gorm.rest.client.json.Book","id":1,"pages":null,"title":"The Stand"}')) - .andRespond(withSuccess('{"id":1, "title":"The Stand"}', MediaType.APPLICATION_JSON)) - - def b = new Book(title: "The Stand") - b.id = 1L - b.insert(flush:true) - - then:"The number of books that exist is correct" - b.id == 1L - mockServer.verify() - - } - - void "Test the save method issues a PUT request for an update with the correct data"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book/1")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.PUT)) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) - .andExpect(content().string('{"class":"org.grails.datastore.gorm.rest.client.json.Book","id":1,"pages":null,"title":"The Stand"}')) - .andRespond(withSuccess('{"id":1, "title":"The Stand"}', MediaType.APPLICATION_JSON)) - - def b = new Book(title: "The Stand") - b.id = 1L - b.save(flush:true) - - then:"The number of books that exist is correct" - b.id == 1L - mockServer.verify() - - } - - void "Test the save method issues a PUT request for an update with the correct data when using a custom URL"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book-custom/1")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.PUT)) - .andExpect(header('Foo', 'Bar')) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) - .andExpect(content().string('{"class":"org.grails.datastore.gorm.rest.client.json.Book","id":1,"pages":null,"title":"The Stand"}')) - .andRespond(withSuccess('{"id":1, "title":"The Stand"}', MediaType.APPLICATION_JSON)) - - def b = new Book(title: "The Stand") - b.id = 1L - b.save([flush:true], new URL("http://localhost:8080/book-custom/{id}")) { - headers['Foo'] = 'Bar' - } - - then:"The number of books that exist is correct" - b.id == 1L - mockServer.verify() - - } - - - void "Test the delete method issues a DELETE request for an update with the correct data"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book/1")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.DELETE)) - .andRespond(withStatus(HttpStatus.NO_CONTENT)) - - def b = new Book(title: "The Stand") - b.id = 1L - b.delete(flush:true) - - then:"The number of books that exist is correct" - b.id == 1L - mockServer.verify() - - } - - void "Test the deleteAll method issues a DELETE request for an update with the correct data"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book/1")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.DELETE)) - .andRespond(withStatus(HttpStatus.NO_CONTENT)) - - def b = new Book(title: "The Stand") - b.id = 1L - Book.withSession { session -> - Book.deleteAll([b]) - session.flush() - } - - - - then:"The number of books that exist is correct" - b.id == 1L - mockServer.verify() - - } - @Override - List getDomainClasses() { - [Book] - } -} - -@Entity -class Book { - Long id - Long version - String title - Integer pages - - static mapping = { -// async false - headers user: "apiUser", pass: "apiPass" - } -} 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 deleted file mode 100644 index 4b6b35120..000000000 --- a/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/json/DirtyCheckingSpec.groovy +++ /dev/null @@ -1,85 +0,0 @@ -package org.grails.datastore.gorm.rest.client.json - -import grails.gorm.dirty.checking.DirtyCheck -import grails.persistence.Entity -import org.codehaus.groovy.grails.web.servlet.HttpHeaders -import org.grails.datastore.gorm.rest.client.RestClientDatastoreSpec -import org.grails.datastore.mapping.dirty.checking.DirtyCheckable -import org.springframework.http.HttpMethod -import org.springframework.http.MediaType -import org.springframework.test.web.client.MockRestServiceServer -import org.springframework.web.client.RestTemplate - -import static org.springframework.test.web.client.match.MockRestRequestMatchers.content -import static org.springframework.test.web.client.match.MockRestRequestMatchers.content -import static org.springframework.test.web.client.match.MockRestRequestMatchers.header -import static org.springframework.test.web.client.match.MockRestRequestMatchers.method -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess - -/** - */ -class DirtyCheckingSpec extends RestClientDatastoreSpec{ - - void "Test dirty checking prevents unnecessary updates"() { - when:"An object is read" - RestTemplate rt = Author.getRestBuilder().restTemplate - def mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/author/1")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString())) - .andRespond(withSuccess('{"id":1, "name":"Stephen King"}', MediaType.APPLICATION_JSON)) - - Author author = Author.get(1) - - then:"The instance is initially not dirty" - author instanceof DirtyCheckable - !author.isDirty() - author.id == 1L - - when:"The entity is saved then no PUT is issued because it isn't dirty" - mockServer = MockRestServiceServer.createServer(rt) - author.save(flush:true) - - then:'Verify no requests were sent' - mockServer.verify() - - when:"The entity is changed" - author.name = "James Patterson" - mockServer.expect(requestTo("http://localhost:8080/author/1")) - .andExpect(method(HttpMethod.PUT)) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) - .andExpect(content().string('{"class":"org.grails.datastore.gorm.rest.client.json.Author","id":1,"name":"James Patterson"}')) - .andRespond(withSuccess('{"id":1, "name":"James Patterson"}', MediaType.APPLICATION_JSON)) - author.save(flush: true) - - then:"a PUT request should be issued for the dirty instance" - mockServer.verify() - - when:"The entity is saved then no PUT is issued because it isn't dirty" - mockServer = MockRestServiceServer.createServer(rt) - author.save(flush:true) - - then:'Verify no requests were sent' - mockServer.verify() - - - - - } - @Override - List getDomainClasses() { - [Author] - } -} - -@DirtyCheck -@Entity -class Author { - Long id - String name - - static mapping = { -// async false - } -} 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 deleted file mode 100644 index c3bb39976..000000000 --- a/grails-datastore-gorm-rest-client/src/test/groovy/org/grails/datastore/gorm/rest/client/xml/CrudXmlSpec.groovy +++ /dev/null @@ -1,230 +0,0 @@ -package org.grails.datastore.gorm.rest.client.xml - -import grails.persistence.Entity -import org.codehaus.groovy.grails.web.servlet.HttpHeaders -import org.grails.datastore.gorm.rest.client.RestClientDatastoreSpec -import org.springframework.http.HttpMethod -import org.springframework.http.HttpStatus -import org.springframework.http.MediaType -import org.springframework.test.web.client.MockRestServiceServer -import org.springframework.web.client.RestTemplate - -import static org.springframework.test.web.client.match.MockRestRequestMatchers.* -import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess - -/** - */ -class CrudXmlSpec extends RestClientDatastoreSpec{ - void "Test the get method issues a GET request and binds the result to the entity"() { - when:"An entity is retrieved with the get method" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book/1")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML.toString())) - .andRespond(withSuccess('The Stand200', MediaType.APPLICATION_XML)) - - Book b = Book.get(1) - - then:"The number of books that exist is correct" - b != null - b.id == 1L - b.title == "The Stand" - b.pages == 200 - mockServer.verify() - - } - - void "Test the getAll method issues a GET request and binds the result to the entity"() { - when:"An entity is retrieved with the get method" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book/1")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML.toString())) - .andRespond(withSuccess('The Stand200', MediaType.APPLICATION_XML)) - - List books = Book.getAll([1]) - - then:"The number of books that exist is correct" - books - books[0] != null - books[0].id == 1L - books[0].title == "The Stand" - books[0].pages == 200 - mockServer.verify() - - } - - void "Test the saveAll method issues a POST request with the correct data"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.POST)) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_XML)) - .andExpect(content().string('The Stand')) - .andRespond(withSuccess('The Stand200', MediaType.APPLICATION_XML)) - - mockServer.expect(requestTo("http://localhost:8080/book/2")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.PUT)) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_XML)) - .andExpect(content().string('The Shining')) - .andRespond(withSuccess('The Shining', MediaType.APPLICATION_XML)) - - - def b = new Book(title: "The Stand") - def b2 = new Book(title: "The Shining") - b2.id = 2L - def ids = Book.withSession { session -> - def identifiers = Book.saveAll([b, b2]) - session.flush() - return identifiers - } - - - then:"The number of books that exist is correct" - b.id == 1L - ids == [1L, 2L] - mockServer.verify() - - } - - void "Test the save method issues a POST request with the correct data"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.POST)) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_XML)) - .andExpect(content().string('The Stand')) - .andRespond(withSuccess('The Stand', MediaType.APPLICATION_XML)) - - def b = new Book(title: "The Stand") - b.save() - - then:"The number of books that exist is correct" - b.id == 1L - mockServer.verify() - - } - - void "Test the insert method issues a POST request with the correct data"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.POST)) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_XML)) - .andExpect(content().string('The Stand')) - .andRespond(withSuccess('The Stand', MediaType.APPLICATION_XML)) - - def b = new Book(title: "The Stand") - b.id = 1L - b.insert(flush:true) - - then:"The number of books that exist is correct" - b.id == 1L - mockServer.verify() - - } - - void "Test the save method issues a PUT request for an update with the correct data"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book/1")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.PUT)) - .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_XML)) - .andExpect(content().string('The Stand')) - .andRespond(withSuccess('The Stand', MediaType.APPLICATION_XML)) - - def b = new Book(title: "The Stand") - b.id = 1L - b.save(flush:true) - - then:"The number of books that exist is correct" - b.id == 1L - mockServer.verify() - - } - - void "Test the delete method issues a DELETE request for an update with the correct data"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book/1")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.DELETE)) - .andRespond(withStatus(HttpStatus.NO_CONTENT)) - - def b = new Book(title: "The Stand") - b.id = 1L - b.delete(flush:true) - - then:"The number of books that exist is correct" - b.id == 1L - mockServer.verify() - - } - - void "Test the deleteAll method issues a DELETE request for an update with the correct data"() { - when:"A new entity is saved" - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book/1")) - .andExpect(header("user", "apiUser")) - .andExpect(header("pass", "apiPass")) - .andExpect(method(HttpMethod.DELETE)) - .andRespond(withStatus(HttpStatus.NO_CONTENT)) - - def b = new Book(title: "The Stand") - b.id = 1L - Book.withSession { session -> - Book.deleteAll([b]) - session.flush() - } - - - - then:"The number of books that exist is correct" - b.id == 1L - mockServer.verify() - - } - @Override - List getDomainClasses() { - return [Book] - } -} - -@Entity -class Book { - Long id - Long version - String title - Integer pages - - static mapping = { - contentType "application/xml" - accept "application/xml" - headers user: "apiUser", pass: "apiPass" -// async false - } -} diff --git a/grails-datastore-gorm-riak/build.gradle b/grails-datastore-gorm-riak/build.gradle deleted file mode 100644 index b3c4cd8a6..000000000 --- a/grails-datastore-gorm-riak/build.gradle +++ /dev/null @@ -1,37 +0,0 @@ -version = "1.0.0.BUILD-SNAPSHOT" - -configurations { - grails -} - -dependencies { - - grails("org.grails:grails-core:$grailsVersion") { - transitive = false - } - grails("org.grails:grails-bootstrap:$grailsVersion") { - transitive = false - } - - - compile project(":grails-datastore-gorm"), - project(":grails-datastore-gorm-plugin-support"), - project(":grails-datastore-riak"), - project(":grails-datastore-core") - - compile 'org.springframework.data:spring-data-riak:1.0.0.M3' - - testCompile project(":grails-datastore-gorm-test"), - project(":grails-datastore-gorm-tck") -} - -configurations { - compile.exclude module: "org.slf4j" - testCompile.exclude module: "org.slf4j" -} - -sourceSets { - main { - compileClasspath += configurations.grails - } -} diff --git a/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/RiakDatastoreFactoryBean.groovy b/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/RiakDatastoreFactoryBean.groovy deleted file mode 100644 index 2e54d9257..000000000 --- a/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/RiakDatastoreFactoryBean.groovy +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.riak - -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener - -import org.springframework.beans.factory.FactoryBean -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.riak.RiakDatastore -import org.codehaus.groovy.grails.plugins.GrailsPluginManager - -/** - * @author J. Brisbin - */ -class RiakDatastoreFactoryBean implements FactoryBean, ApplicationContextAware { - - Map config - MappingContext mappingContext - ApplicationContext applicationContext - GrailsPluginManager pluginManager - - RiakDatastore getObject() { - RiakDatastore datastore = new RiakDatastore(mappingContext, config, applicationContext) - datastore.afterPropertiesSet() - datastore - } - - Class getObjectType() { RiakDatastore } - - boolean isSingleton() { true } -} diff --git a/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/RiakGormEnhancer.groovy b/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/RiakGormEnhancer.groovy deleted file mode 100644 index 0714e4ceb..000000000 --- a/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/RiakGormEnhancer.groovy +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.riak - -import org.grails.datastore.gorm.AbstractDatastoreApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.data.keyvalue.riak.core.QosParameters -import org.springframework.data.keyvalue.riak.core.RiakQosParameters -import org.springframework.data.keyvalue.riak.core.RiakTemplate -import org.springframework.data.keyvalue.riak.core.SimpleBucketKeyPair -import org.springframework.data.keyvalue.riak.mapreduce.* -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.core.SessionCallback -import org.grails.datastore.mapping.riak.RiakDatastore - -/** - * @author J. Brisbin - */ -class RiakGormEnhancer extends GormEnhancer { - - RiakGormEnhancer(datastore) { - super(datastore) - } - - RiakGormEnhancer(datastore, transactionManager) { - super(datastore, transactionManager) - } - - protected GormStaticApi getStaticApi(Class cls) { - return new RiakGormStaticApi(cls, datastore, finders) - } - - protected GormInstanceApi getInstanceApi(Class cls) { - return new RiakGormInstanceApi(cls, datastore) - } -} - -class RiakGormInstanceApi extends GormInstanceApi { - - RiakGormInstanceApi(Class persistentClass, datastore) { - super(persistentClass, datastore) - } - - D save(D instance, Map params) { - execute (new SessionCallback() { - def doInSession(Session session) { - def currentQosParams = session.qosParameters - if (params?.w || params?.dw) { - QosParameters qos = new RiakQosParameters() - qos.durableWriteThreshold = params?.dw - qos.writeThreshold = params?.w - session.qosParameters = qos - } - - try { - return doSave(instance, params, session) - } - finally { - if (params?.w || params?.dw) { - session.qosParameters = currentQosParams - } - } - } - }) - } -} - -class RiakGormStaticApi extends GormStaticApi { - - MapReduceApi mapReduceApi - - RiakGormStaticApi(D persistentClass, datastore, List finders) { - super(persistentClass, datastore, finders) - mapReduceApi = new MapReduceApi(persistentClass, datastore) - } - - MapReduceApi getMapreduce() { - mapReduceApi - } -} - -class MapReduceApi extends AbstractDatastoreApi { - - static Logger log = LoggerFactory.getLogger(MapReduceApi) - - Class type - - MapReduceApi(Class type, RiakDatastore datastore) { - super(datastore) - this.type = type - } - - def invokeMethod(String methodName, args) { - if (methodName != "execute") { - return - } - - log.debug "Invoking $methodName with ${args}" - - execute (new SessionCallback() { - def doInSession(Session session) { - RiakTemplate riak = session.nativeInterface - RiakMapReduceJob mr = new RiakMapReduceJob(riak) - mr.addInputs([type.name]) - def params = args[0] - if (params["map"]) { - def oper = extractMapReduceOperation(params["map"]) - mr.addPhase(new RiakMapReducePhase(MapReducePhase.Phase.MAP, params["map"]["language"] ?: "javascript", oper)) - } - if (params["reduce"]) { - def oper = extractMapReduceOperation(params["reduce"]) - mr.addPhase(new RiakMapReducePhase(MapReducePhase.Phase.REDUCE, params["map"]["language"] ?: "javascript", oper)) - } - riak.execute(mr) - } - }) - } - - protected MapReduceOperation extractMapReduceOperation(param) { - def oper - def lang = param.language ?: "javascript" - if (lang == "javascript") { - if (param.source) { - oper = new JavascriptMapReduceOperation(param.source) - } else if (param.bucket && param.key) { - def bkp = new SimpleBucketKeyPair(param.bucket, param.key) - oper = new JavascriptMapReduceOperation(bkp) - } - } else if (lang == "erlang") { - oper = new ErlangMapReduceOperation(param.module, param.function) - } - oper - } -} diff --git a/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/RiakMappingContextFactoryBean.groovy b/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/RiakMappingContextFactoryBean.groovy deleted file mode 100644 index 1e3365bdf..000000000 --- a/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/RiakMappingContextFactoryBean.groovy +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.riak - -import org.grails.datastore.gorm.bean.factory.AbstractMappingContextFactoryBean -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext -import org.grails.datastore.mapping.model.MappingContext - -/** - * @author J. Brisbin - */ -class RiakMappingContextFactoryBean extends AbstractMappingContextFactoryBean { - - protected MappingContext createMappingContext() { new KeyValueMappingContext("") } -} diff --git a/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/plugin/support/RiakMethodsConfigurer.groovy b/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/plugin/support/RiakMethodsConfigurer.groovy deleted file mode 100644 index 1b64b7e5f..000000000 --- a/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/plugin/support/RiakMethodsConfigurer.groovy +++ /dev/null @@ -1,58 +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.riak.plugin.support - -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.plugin.support.DynamicMethodsConfigurer -import org.grails.datastore.gorm.riak.RiakGormStaticApi -import org.grails.datastore.gorm.riak.RiakGormInstanceApi -import org.grails.datastore.gorm.riak.RiakGormEnhancer -import org.springframework.transaction.PlatformTransactionManager - -/** - * @author Graeme Rocher - * @since 1.0 - */ -class RiakMethodsConfigurer extends DynamicMethodsConfigurer { - - RiakMethodsConfigurer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { "Riak" } - - @Override - protected GormStaticApi createGormStaticApi(Class cls, List finders) { - return new RiakGormStaticApi(cls, datastore, finders) - } - - @Override - protected GormInstanceApi createGormInstanceApi(Class cls) { - return new RiakGormInstanceApi(cls, datastore) - } - - @Override - protected GormEnhancer createEnhancer() { - if (transactionManager) { - return new RiakGormEnhancer(datastore, transactionManager) - } - return new RiakGormEnhancer(datastore) - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/plugin/support/RiakOnChangeHandler.groovy b/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/plugin/support/RiakOnChangeHandler.groovy deleted file mode 100644 index a5906d8a2..000000000 --- a/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/plugin/support/RiakOnChangeHandler.groovy +++ /dev/null @@ -1,31 +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.riak.plugin.support - -import org.grails.datastore.gorm.plugin.support.OnChangeHandler -import org.grails.datastore.mapping.core.Datastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * onChange handler for Riak - */ -class RiakOnChangeHandler extends OnChangeHandler{ - RiakOnChangeHandler(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { "Riak" } -} diff --git a/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/plugin/support/RiakSpringConfigurer.groovy b/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/plugin/support/RiakSpringConfigurer.groovy deleted file mode 100644 index d2f04a27a..000000000 --- a/grails-datastore-gorm-riak/src/main/groovy/org/grails/datastore/gorm/riak/plugin/support/RiakSpringConfigurer.groovy +++ /dev/null @@ -1,85 +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.riak.plugin.support - -import org.grails.datastore.gorm.plugin.support.SpringConfigurer -import org.grails.datastore.gorm.riak.RiakMappingContextFactoryBean -import org.grails.datastore.gorm.riak.RiakDatastoreFactoryBean -import org.springframework.data.keyvalue.riak.groovy.RiakBuilder -import org.springframework.data.keyvalue.riak.core.AsyncRiakTemplate -import org.springframework.data.keyvalue.riak.core.RiakTemplate - -/** - * Configures Spring for Riak - * - * @author Graeme Rocher - * @since 1.0 - */ -class RiakSpringConfigurer extends SpringConfigurer{ - @Override - String getDatastoreType() { "Riak" } - - @Override - Closure getSpringCustomizer() { - return { - def riakConfig = application.config?.grails?.riak - - riakDatastoreMappingContext(RiakMappingContextFactoryBean) { - grailsApplication = ref('grailsApplication') - pluginManager = ref('pluginManager') - } - - riakDatastore(RiakDatastoreFactoryBean) { - config = riakConfig - mappingContext = ref("riakDatastoreMappingContext") - pluginManager = ref('pluginManager') - } - - riakTemplate(RiakTemplate) { bean -> - def riakDefaultUri = riakConfig?.remove("defaultUri") - if (riakDefaultUri) { - defaultUri = riakDefaultUri - } - def riakMapRedUri = riakConfig?.remove("mapReduceUri") - if (riakMapRedUri) { - mapReduceUri = riakMapRedUri - } - def riakUseCache = riakConfig?.remove("useCache") - if (null != riakUseCache) { - useCache = riakUseCache - } - } - - asyncRiakTemplate(AsyncRiakTemplate) { bean -> - def riakDefaultUri = riakConfig?.remove("defaultUri") - if (riakDefaultUri) { - defaultUri = riakDefaultUri - } - def riakMapRedUri = riakConfig?.remove("mapReduceUri") - if (riakMapRedUri) { - mapReduceUri = riakMapRedUri - } - def riakUseCache = riakConfig?.remove("useCache") - if (riakUseCache) { - useCache = riakUseCache - } - } - - riak(RiakBuilder, asyncRiakTemplate) { bean -> - bean.scope = "prototype" - } - } - } -} diff --git a/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy b/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy deleted file mode 100644 index e3c1f3f62..000000000 --- a/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy +++ /dev/null @@ -1,220 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.DetachedCriteria -import spock.lang.Ignore - -/** - * Created by IntelliJ IDEA. - * User: graemerocher - * Date: 9/6/11 - * Time: 12:09 PM - * To change this template use File | Settings | File Templates. - */ -class DetachedCriteriaSpec extends GormDatastoreSpec{ - - void "Test exists method"() { - given:"A bunch of people" - createPeople() - - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - then:"The count method returns the right results" - criteria.exists() == true - } - void "Test updateAll method"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria is created that deletes all matching records" - def criteria = new DetachedCriteria(Person).build { - eq 'lastName', 'Simpson' - } - int total = criteria.updateAll(lastName:"Bloggs") - - - then:"The number of deletions is correct" - total == 4 - Person.count() == 6 - criteria.count() == 0 - Person.countByLastName("Bloggs") == 4 - } - - void "Test deleteAll method"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria is created that deletes all matching records" - def criteria = new DetachedCriteria(Person).build { - eq 'lastName', 'Simpson' - } - int total = criteria.deleteAll() - - - then:"The number of deletions is correct" - total == 4 - Person.count() == 2 - } - - void "Test iterate of detached criteria"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria is created that matches the last name and then iterated over" - def criteria = new DetachedCriteria(Person).build { - eq 'lastName', 'Simpson' - } - int total = 0 - criteria.each { - total++ - } - - then:"The number of iterations is correct" - total == 4 - } - void "Test dynamic finder on detached criteria"() { - given:"A bunch of people" - createPeople() - - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - def result = criteria.findByFirstNameLike("B%") - - then:"The list method returns the right results" - result != null - result.firstName == "Bart" - } - - void "Test get method on detached criteria and additional criteria"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - def result = criteria.get { - like 'firstName', 'B%' - } - then:"The list method returns the right results" - result != null - result.firstName == "Bart" - } - - void "Test list method on detached criteria and additional criteria"() { - given:"A bunch of people" - createPeople() - - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - def results = criteria.list { - like 'firstName', 'B%' - } - then:"The list method returns the right results" - results.size() == 1 - results[0].firstName == "Bart" - - when:"The original detached criteria is queried" - results = criteria.list() - - then:"The additional criteria didn't modify the original instance and the correct results are returned" - results.size() == 4 - results.every { it.lastName == 'Simpson'} - } - - void "Test count method on detached criteria and additional criteria"() { - given:"A bunch of people" - createPeople() - - - when:"A detached criteria instance is created matching the last name and count is called with additional criteria" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - def result = criteria.count { - like 'firstName', 'B%' - } - then:"The count method returns the right results" - result == 1 - - } - - void "Test count method on detached criteria"() { - given:"A bunch of people" - createPeople() - - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - def result = criteria.count() - then:"The count method returns the right results" - result == 4 - - } - void "Test list method on detached criteria"() { - given:"A bunch of people" - createPeople() - - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - - def results = criteria.list() - then:"The list method returns the right results" - results.size() == 4 - results.every { it.lastName == 'Simpson'} - } - - @Ignore // TODO: pagination not behaving correctly in Riak - void "Test list method on detached criteria with pagination"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria instance is created matching the last name" - def criteria = new DetachedCriteria(Person) - criteria.build { - eq 'lastName', 'Simpson' - } - - def results = criteria.list(max: 2) - then:"The list method returns the right results" - results.size() == 2 - results.every { it.lastName == 'Simpson'} - } - - - protected def createPeople() { - new Person(firstName: "Homer", lastName: "Simpson").save() - new Person(firstName: "Marge", lastName: "Simpson").save() - new Person(firstName: "Bart", lastName: "Simpson").save() - new Person(firstName: "Lisa", lastName: "Simpson").save() - new Person(firstName: "Barney", lastName: "Rubble").save() - new Person(firstName: "Fred", lastName: "Flinstone").save() - } - -} diff --git a/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/OneToOneSpec.groovy b/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/OneToOneSpec.groovy deleted file mode 100644 index 32c5c7620..000000000 --- a/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/OneToOneSpec.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package grails.gorm.tests - -import spock.lang.Ignore - -/** - * Created by IntelliJ IDEA. - * User: graemerocher - * Date: 8/5/11 - * Time: 11:17 AM - * To change this template use File | Settings | File Templates. - */ -class OneToOneSpec extends GormDatastoreSpec{ - - static { - TEST_CLASSES << Face << Nose - } - - 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.owner != null - pet.owner.firstName == "Fred" - - } - - @Ignore - 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) - - then:"The domain model is valid" - - face != null - 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-riak/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy b/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy deleted file mode 100644 index 7b8653813..000000000 --- a/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy +++ /dev/null @@ -1,9 +0,0 @@ -package grails.gorm.tests - -/** - * @author Burt Beckwith - */ -class OptimisticLockingSpec { - // TODO implement optimistic locking for Gemfire and delete this - void testNothing() {} -} diff --git a/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy b/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy deleted file mode 100644 index db1718600..000000000 --- a/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.PagedResultList -import spock.lang.Ignore - -/** - * TODO: Pagination not implemented correctly with Riak - */ -@Ignore -class PagedResultSpec extends GormDatastoreSpec{ - - - void "Test that a paged result list is returned from the list() method with pagination params"() { - given:"Some people" - createPeople() - - when:"The list method is used with pagination params" - def results = Person.list(offset:2, max:2) - - then:"You get a paged result list back" - results instanceof PagedResultList - results.size() == 2 - results[0].firstName == "Bart" - results[1].firstName == "Lisa" - results.totalCount == 6 - - } - - void "Test that a paged result list is returned from the critera with pagination params"() { - given:"Some people" - createPeople() - - when:"The list method is used with pagination params" - def results = Person.createCriteria().list(offset:1, max:2) { - eq 'lastName', 'Simpson' - } - - then:"You get a paged result list back" - results instanceof PagedResultList - results.size() == 2 - results[0].firstName == "Marge" - results[1].firstName == "Bart" - results.totalCount == 4 - - } - - - protected def createPeople() { - new Person(firstName: "Homer", lastName: "Simpson", age:45).save() - new Person(firstName: "Marge", lastName: "Simpson", age:40).save() - new Person(firstName: "Bart", lastName: "Simpson", age:9).save() - new Person(firstName: "Lisa", lastName: "Simpson", age:7).save() - new Person(firstName: "Barney", lastName: "Rubble", age:35).save() - new Person(firstName: "Fred", lastName: "Flinstone", age:41).save() - } - -} diff --git a/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy b/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy deleted file mode 100644 index 5547a7197..000000000 --- a/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package grails.gorm.tests - -import org.junit.Ignore - -/** - * Tests for criteria queries that compare two properties - */ -class PropertyComparisonQuerySpec extends GormDatastoreSpec{ - - @Ignore - void "Test eqProperty criterion"() { - // TODO: implement eqProperty query operations - } -} diff --git a/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy b/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy deleted file mode 100644 index 082db7656..000000000 --- a/grails-datastore-gorm-riak/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.tests.GormDatastoreSpec -import org.junit.Ignore - -/** - * Tests for querying the size of collections etc. - */ -class SizeQuerySpec extends GormDatastoreSpec { - - @Ignore - void "Test sizeEq criterion"() { - // TODO: implement sizeEq query operations - } -} diff --git a/grails-datastore-gorm-riak/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-riak/src/test/groovy/org/grails/datastore/gorm/Setup.groovy deleted file mode 100644 index 8fa9e3a61..000000000 --- a/grails-datastore-gorm-riak/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2010 by NPC International, Inc. - * - * 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 org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.gorm.riak.RiakGormEnhancer -import org.springframework.context.support.GenericApplicationContext -import org.springframework.data.keyvalue.riak.core.QosParameters -import org.springframework.data.keyvalue.riak.core.RiakQosParameters -import org.springframework.data.keyvalue.riak.core.RiakTemplate -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.riak.RiakDatastore -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager -import org.springframework.util.StringUtils -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -/** - * @author J. Brisbin - */ -class Setup { - - static riak - - static destroy() {} - - static Session setup(classes) { - def ctx = new GenericApplicationContext() - ctx.refresh() - - riak = new RiakDatastore(new KeyValueMappingContext(""), [ - defaultUri: "http://localhost:8098/riak/{bucket}/{key}", - mapReduceUri: "http://localhost:8098/mapred" - ], ctx) - - for (cls in classes) { - riak.mappingContext.addPersistentEntity(cls) - } - - PersistentEntity entity = riak.mappingContext.persistentEntities.find { PersistentEntity e -> - e.name.contains("TestEntity") - } - - riak.mappingContext.addEntityValidator(entity, [ - supports: { Class c -> true }, - validate: { Object o, Errors errors -> - if (!StringUtils.hasText(o.name)) { - errors.rejectValue("name", "name.is.blank") - } - } - ] as Validator) - - def enhancer = new RiakGormEnhancer(riak, new DatastoreTransactionManager(datastore: riak)) - enhancer.enhance() - - riak.mappingContext.addMappingContextListener({ e -> enhancer.enhance e } as MappingContext.Listener) - - riak.applicationContext.addApplicationListener new DomainEventListener(riak) - riak.applicationContext.addApplicationListener new AutoTimestampEventListener(riak) - - Session con = riak.connect() - RiakTemplate riakTmpl = con.nativeInterface - QosParameters qos = new RiakQosParameters() - qos.durableWriteThreshold = "3" - riakTmpl.defaultQosParameters = qos - riakTmpl.useCache = false - ["grails.gorm.tests.TestEntity", - "grails.gorm.tests.ChildEntity", - "grails.gorm.tests.Publication", - "grails.gorm.tests.Location", - "grails.gorm.tests.City", - "grails.gorm.tests.Country", - "grails.gorm.tests.Highway", - "grails.gorm.tests.Book", - "grails.gorm.tests.Pet", - "grails.gorm.tests.Person", - "grails.gorm.tests.Task", - "grails.gorm.tests.Plant", - "grails.gorm.tests.EnumThing", - "grails.gorm.tests.UniqueGroup", - "grails.gorm.tests.GroupWithin"].each { type -> - def schema = riakTmpl.getBucketSchema(type, true) - schema.keys.each { key -> - try { - riakTmpl.deleteKeys("$type:$key") - } catch (err) { - } - } - } - - con - } -} diff --git a/grails-datastore-gorm-riak/src/test/groovy/org/grails/datastore/gorm/riak/RiakSuite.groovy b/grails-datastore-gorm-riak/src/test/groovy/org/grails/datastore/gorm/riak/RiakSuite.groovy deleted file mode 100644 index 245c6422f..000000000 --- a/grails-datastore-gorm-riak/src/test/groovy/org/grails/datastore/gorm/riak/RiakSuite.groovy +++ /dev/null @@ -1,38 +0,0 @@ -package org.grails.datastore.gorm.riak - -import grails.gorm.tests.CriteriaBuilderSpec -import org.junit.runner.RunWith -import org.junit.runners.Suite -import org.junit.runners.Suite.SuiteClasses - - /** - * @author J. Brisbin - */ -@RunWith(Suite) -@SuiteClasses([ -// AttachMethodSpec, -// CircularOneToManySpec, -// CommonTypesPersistenceSpec, -// CriteriaBuilderSpec, -// CrudOperationsSpec, -// DomainEventsSpec, -// FindByMethodSpec, -// GormEnhancerSpec, -// GroovyProxySpec, -// InheritanceSpec, -// ListOrderBySpec, -// NamedQuerySpec, -// NegationSpec, -// OneToManySpec, -// OrderBySpec, -// ProxyLoadingSpec, -// QueryAfterPropertyChangeSpec, -// QueryByAssociationSpec, -// RangeQuerySpec, -// SaveAllSpec, -// UpdateWithProxyPresentSpec, -// ValidationSpec, -// WithTransactionSpec -]) -class RiakSuite { -} diff --git a/grails-datastore-gorm-simpledb/build.gradle b/grails-datastore-gorm-simpledb/build.gradle deleted file mode 100644 index 70a719260..000000000 --- a/grails-datastore-gorm-simpledb/build.gradle +++ /dev/null @@ -1,37 +0,0 @@ -version = "0.6.BUILD-SNAPSHOT" - -configurations { - grails -} - -dependencies { - - grails("org.grails:grails-core:$grailsVersion") - grails("org.grails:grails-bootstrap:$grailsVersion") { - transitive = false - } - - compile project(":grails-datastore-gorm"), - project(":grails-datastore-gorm-plugin-support"), - project(":grails-datastore-simpledb"), - project(":grails-datastore-core") - - testCompile project(":grails-datastore-gorm-test"), - project(":grails-datastore-gorm-tck") -} - -configurations { - compile.exclude module: "org.slf4j" - testCompile.exclude module: "org.slf4j" -} - -sourceSets { - main { - compileClasspath += configurations.grails - } -} - -//test { -// maxParallelForks = 4 -// forkEvery = 25 -//} diff --git a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/SimpleDBCriteriaBuilder.java b/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/SimpleDBCriteriaBuilder.java deleted file mode 100644 index 30b445fc4..000000000 --- a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/SimpleDBCriteriaBuilder.java +++ /dev/null @@ -1,37 +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.simpledb; - -import grails.gorm.CriteriaBuilder; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.query.Query; - -/** - * Extends the default CriteriaBuilder implementation. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -public class SimpleDBCriteriaBuilder extends CriteriaBuilder { - - public SimpleDBCriteriaBuilder(final Class targetClass, final Session session, final Query query) { - super(targetClass, session, query); - } - - public SimpleDBCriteriaBuilder(final Class targetClass, final Session session) { - super(targetClass, session); - } -} diff --git a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/SimpleDBGormEnhancer.groovy b/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/SimpleDBGormEnhancer.groovy deleted file mode 100644 index fb9f3a510..000000000 --- a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/SimpleDBGormEnhancer.groovy +++ /dev/null @@ -1,129 +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.simpledb - -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.core.SessionCallback -import org.springframework.transaction.PlatformTransactionManager - -import org.grails.datastore.mapping.engine.EntityPersister -import org.grails.datastore.mapping.simpledb.engine.SimpleDBNativeItem -import org.grails.datastore.mapping.simpledb.util.SimpleDBTemplate - -/** - * GORM enhancer for SimpleDB. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -class SimpleDBGormEnhancer extends GormEnhancer { - - SimpleDBGormEnhancer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - SimpleDBGormEnhancer(Datastore datastore) { - this(datastore, null) - } - - protected GormStaticApi getStaticApi(Class cls) { - return new SimpleDBGormStaticApi(cls, datastore, getFinders()) - } - - protected GormInstanceApi getInstanceApi(Class cls) { - final api = new SimpleDBGormInstanceApi(cls, datastore) - api.failOnError = failOnError - return api - } -} - -class SimpleDBGormInstanceApi extends GormInstanceApi { - - SimpleDBGormInstanceApi(Class persistentClass, Datastore datastore) { - super(persistentClass, datastore) - } - - /** - * Allows subscript access to schemaless attributes. - * - * @param instance The instance - * @param name The name of the field - */ - void putAt(D instance, String name, value) { - if (instance.hasProperty(name)) { - instance.setProperty(name, value) - } - else { - getDbo(instance)?.put name, value - } - } - - /** - * Allows subscript access to schemaless attributes. - * - * @param instance The instance - * @param name The name of the field - * @return the value - */ - def getAt(D instance, String name) { - if (instance.hasProperty(name)) { - return instance.getProperty(name) - } - - def dbo = getDbo(instance) - if (dbo != null && dbo.containsField(name)) { - return SimpleDBTemplate.get(name) - } - return null - } - - /** - * Return the DBObject instance for the entity - * - * @param instance The instance - * @return The NativeSimpleDBItem instance - */ - SimpleDBNativeItem getDbo(D instance) { - execute (new SessionCallback() { - SimpleDBNativeItem doInSession(Session session) { - - if (!session.contains(instance) && !instance.save()) { - throw new IllegalStateException( - "Cannot obtain DBObject for transient instance, save a valid instance first") - } - - EntityPersister persister = session.getPersister(instance) - def id = persister.getObjectIdentifier(instance) - return session.getCachedEntry(persister.getPersistentEntity(), id) - } - }) - } -} - -class SimpleDBGormStaticApi extends GormStaticApi { - SimpleDBGormStaticApi(Class persistentClass, Datastore datastore, List finders) { - super(persistentClass, datastore, finders) - } - - @Override - SimpleDBCriteriaBuilder createCriteria() { - return new SimpleDBCriteriaBuilder(persistentClass, datastore.currentSession) - } -} diff --git a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/bean/factory/SimpleDBDatastoreFactoryBean.groovy b/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/bean/factory/SimpleDBDatastoreFactoryBean.groovy deleted file mode 100644 index 4b2ebfe73..000000000 --- a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/bean/factory/SimpleDBDatastoreFactoryBean.groovy +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (C) 2010 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.simpledb.bean.factory - -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.springframework.beans.factory.FactoryBean -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.simpledb.SimpleDBDatastore -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository -import org.grails.datastore.mapping.simpledb.engine.SimpleDBNativeItem - -/** - * Factory bean for constructing a {@link org.grails.datastore.mapping.simpledb.SimpleDBDatastore} instance. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ - -class SimpleDBDatastoreFactoryBean implements FactoryBean, ApplicationContextAware { - - MappingContext mappingContext - Map config = [:] - ApplicationContext applicationContext - TPCacheAdapterRepository cacheAdapterRepository - - SimpleDBDatastore getObject() { - - SimpleDBDatastore datastore = new SimpleDBDatastore(mappingContext, config, applicationContext, cacheAdapterRepository) - - applicationContext.addApplicationListener new DomainEventListener(datastore) - applicationContext.addApplicationListener new AutoTimestampEventListener(datastore) - - datastore.afterPropertiesSet() - datastore - } - - Class getObjectType() { SimpleDBDatastore } - - boolean isSingleton() { true } -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/bean/factory/SimpleDBMappingContextFactoryBean.groovy b/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/bean/factory/SimpleDBMappingContextFactoryBean.groovy deleted file mode 100644 index c1fbec688..000000000 --- a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/bean/factory/SimpleDBMappingContextFactoryBean.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package org.grails.datastore.gorm.simpledb.bean.factory - -import org.grails.datastore.gorm.bean.factory.AbstractMappingContextFactoryBean -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.simpledb.config.SimpleDBMappingContext - -/** - * Factory bean for construction the SimpleDB MappingContext. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -class SimpleDBMappingContextFactoryBean extends AbstractMappingContextFactoryBean { - @Override - protected MappingContext createMappingContext() { - return new SimpleDBMappingContext() - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/plugin/support/SimpleDBApplicationContextConfigurer.groovy b/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/plugin/support/SimpleDBApplicationContextConfigurer.groovy deleted file mode 100644 index e53bf1e59..000000000 --- a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/plugin/support/SimpleDBApplicationContextConfigurer.groovy +++ /dev/null @@ -1,166 +0,0 @@ -package org.grails.datastore.gorm.simpledb.plugin.support - -import java.util.concurrent.CountDownLatch -import java.util.concurrent.Executor -import java.util.concurrent.Executors - -import org.codehaus.groovy.grails.commons.GrailsApplication -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty -import org.codehaus.groovy.grails.plugins.GrailsPluginManager -import org.grails.datastore.gorm.plugin.support.ApplicationContextConfigurer -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher -import org.grails.datastore.mapping.simpledb.SimpleDBDatastore -import org.grails.datastore.mapping.simpledb.config.SimpleDBMappingContext -import org.grails.datastore.mapping.simpledb.engine.SimpleDBAssociationInfo -import org.grails.datastore.mapping.simpledb.engine.SimpleDBDomainResolver -import org.grails.datastore.mapping.simpledb.engine.SimpleDBDomainResolverFactory -import org.grails.datastore.mapping.simpledb.util.SimpleDBConst -import org.grails.datastore.mapping.simpledb.util.SimpleDBTemplate -import org.grails.datastore.mapping.simpledb.util.SimpleDBUtil -import org.springframework.context.ConfigurableApplicationContext - -class SimpleDBApplicationContextConfigurer extends ApplicationContextConfigurer { - - SimpleDBApplicationContextConfigurer() { - super("SimpleDB") - } - - @Override - void configure(ConfigurableApplicationContext ctx) { - super.configure(ctx) - - GrailsPluginManager pluginManager = ctx.pluginManager - GrailsApplication application = ctx.grailsApplication - - def simpleDBDomainClasses = [] - simpleDBDomainClassProcessor(application, pluginManager, { dc -> - simpleDBDomainClasses.add(dc) //collect domain classes which are stored via SimpleDB - }) - - //explicitly register simpledb domain classes with datastore - SimpleDBDatastore simpleDBDatastore = ctx.simpledbDatastore - SimpleDBMappingContext mappingContext = ctx.simpledbMappingContext - - simpleDBDomainClasses.each { domainClass -> - PersistentEntity entity = mappingContext.getPersistentEntity(domainClass.clazz.getName()) - simpleDBDatastore.persistentEntityAdded(entity) - } - - def simpleDBConfig = application.config?.grails?.simpledb - //determine dbCreate flag and create/delete AWS domains if needed - handleDBCreate(simpleDBConfig, - application, - simpleDBDomainClasses, - mappingContext, - simpleDBDatastore - ) //similar to JDBC datastore, do 'create' or 'drop-create' - } - - /** - * Iterates over all domain classes which are mapped with SimpleDB and passes them to the specified closure - */ - def simpleDBDomainClassProcessor = { application, pluginManager, closure -> - def isHibernateInstalled = pluginManager.hasGrailsPlugin("hibernate") - for (dc in application.domainClasses) { - def cls = dc.clazz - def cpf = ClassPropertyFetcher.forClass(cls) - def mappedWith = cpf.getStaticPropertyValue(GrailsDomainClassProperty.MAPPING_STRATEGY, String) - if (mappedWith == SimpleDBConst.SIMPLE_DB_MAP_WITH_VALUE || (!isHibernateInstalled && mappedWith == null)) { - closure.call(dc) - } - } - } - - def handleDBCreate = { simpleDBConfig, application, simpleDBDomainClasses, mappingContext, simpleDBDatastore -> - String dbCreate = simpleDBConfig.dbCreate - boolean drop = false - boolean create = false - if ("drop-create" == dbCreate) { - drop = true - create = true - } else if ("create" == dbCreate) { - create = true - } else if ("drop" == dbCreate) { - drop = true - } - - //protection against accidental drop - boolean disableDrop = simpleDBConfig.disableDrop - if (disableDrop && drop) { - throw new IllegalArgumentException("Value of disableDrop is " + disableDrop + " while dbCreate is " + - dbCreate + ". Throwing an exception to prevent accidental drop of the data") - } - - def numOfThreads = 30 //how many parallel threads are used to create dbCreate functionality in parallel - - Executor executor = Executors.newFixedThreadPool(numOfThreads) - - SimpleDBTemplate template = simpleDBDatastore.getSimpleDBTemplate() - List existingDomains = template.listDomains() - SimpleDBDomainResolverFactory resolverFactory = new SimpleDBDomainResolverFactory() - CountDownLatch latch = new CountDownLatch(simpleDBDomainClasses.size()) - - for (dc in simpleDBDomainClasses) { - def domainClass = dc.clazz //explicitly declare local variable which we will be using from the thread - //do simpleDB work in parallel threads for each domain class to speed things up - executor.execute({ - try { - PersistentEntity entity = mappingContext.getPersistentEntity(domainClass.getName()) - SimpleDBDomainResolver domainResolver = resolverFactory.buildResolver(entity, simpleDBDatastore) - def domains = domainResolver.getAllDomainsForEntity() - domains.each { domain -> - handleDomain(template, existingDomains, domain, drop, create) - //handle domains for associations - entity.getAssociations().each { association -> - SimpleDBAssociationInfo associationInfo = simpleDBDatastore.getAssociationInfo(association) - if (associationInfo) { - handleDomain(template, existingDomains, associationInfo.getDomainName(), drop, create) - } - } - } - } finally { - latch.countDown() - } - }) - } - - //if needed, drop/create hilo id generator domain - String hiloDomainName = SimpleDBUtil.getPrefixedDomainName(simpleDBDatastore.getDomainNamePrefix(), SimpleDBConst.ID_GENERATOR_HI_LO_DOMAIN_NAME) - handleDomain(template, existingDomains, hiloDomainName, drop, create) - - latch.await() - executor.shutdown() - } - - def clearOrCreateDomain(template, existingDomains, domainName) { - if (existingDomains.contains(domainName)) { - template.deleteAllItems(domainName) //delete all items there - } else { - //create it - template.createDomain(domainName) - } - } - - def createDomainIfDoesNotExist (template, existingDomains, domainName) { - if (!existingDomains.contains(domainName)) { - template.createDomain(domainName) - } - } - - def deleteDomainIfExists (template, existingDomains, domainName) { - if (existingDomains.contains(domainName)) { - template.deleteDomain(domainName) - } - } - - def handleDomain(template, existingDomains, domainName, boolean drop, boolean create) { - if (drop && create) { - clearOrCreateDomain(template, existingDomains, domainName) - } else if (create) { - createDomainIfDoesNotExist(template, existingDomains, domainName) - } else if (drop) { - deleteDomainIfExists(template, existingDomains, domainName) - } - } -} diff --git a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/plugin/support/SimpleDBMethodsConfigurer.groovy b/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/plugin/support/SimpleDBMethodsConfigurer.groovy deleted file mode 100644 index b6b40c9bf..000000000 --- a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/plugin/support/SimpleDBMethodsConfigurer.groovy +++ /dev/null @@ -1,69 +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.simpledb.plugin.support - -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.plugin.support.DynamicMethodsConfigurer -import org.grails.datastore.gorm.simpledb.SimpleDBGormEnhancer -import org.grails.datastore.gorm.simpledb.SimpleDBGormInstanceApi -import org.grails.datastore.gorm.simpledb.SimpleDBGormStaticApi -import org.grails.datastore.mapping.core.Datastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * SimpleDB specific dynamic methods configurer. - * - * @author Roman Stepanenko based on Graeme Rocher - * @since 0.1 - */ -class SimpleDBMethodsConfigurer extends DynamicMethodsConfigurer { - - SimpleDBMethodsConfigurer(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { - return "SimpleDB" - } - - @Override - protected GormStaticApi createGormStaticApi(Class cls, List finders) { - return new SimpleDBGormStaticApi(cls, datastore, finders) - } - - @Override - protected GormInstanceApi createGormInstanceApi(Class cls) { - def api = new SimpleDBGormInstanceApi(cls, datastore) - api.failOnError = failOnError - api - } - - @Override - protected GormEnhancer createEnhancer() { - def ge - if (transactionManager == null) { - ge = new SimpleDBGormEnhancer(datastore) - } - else { - ge = new SimpleDBGormEnhancer(datastore, transactionManager) - } - ge.failOnError = failOnError - ge - } -} diff --git a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/plugin/support/SimpleDBOnChangeHandler.groovy b/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/plugin/support/SimpleDBOnChangeHandler.groovy deleted file mode 100644 index 126132949..000000000 --- a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/plugin/support/SimpleDBOnChangeHandler.groovy +++ /dev/null @@ -1,34 +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.simpledb.plugin.support - -import org.grails.datastore.gorm.plugin.support.OnChangeHandler -import org.grails.datastore.mapping.core.Datastore -import org.springframework.transaction.PlatformTransactionManager - -/** - * On change handler for SimpleDB - */ -class SimpleDBOnChangeHandler extends OnChangeHandler{ - - SimpleDBOnChangeHandler(Datastore datastore, PlatformTransactionManager transactionManager) { - super(datastore, transactionManager) - } - - @Override - String getDatastoreType() { - return "SimpleDB" - } -} diff --git a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/plugin/support/SimpleDBSpringConfigurer.groovy b/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/plugin/support/SimpleDBSpringConfigurer.groovy deleted file mode 100644 index 413cfbdc5..000000000 --- a/grails-datastore-gorm-simpledb/src/main/groovy/org/grails/datastore/gorm/simpledb/plugin/support/SimpleDBSpringConfigurer.groovy +++ /dev/null @@ -1,63 +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.simpledb.plugin.support - -import org.grails.datastore.gorm.plugin.support.SpringConfigurer -import org.grails.datastore.gorm.simpledb.bean.factory.SimpleDBDatastoreFactoryBean -import org.grails.datastore.gorm.simpledb.bean.factory.SimpleDBMappingContextFactoryBean -import org.grails.datastore.mapping.cache.impl.TPCacheAdapterRepositoryImpl -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager - -/** - * SimpleDB specific configuration logic for Spring - * - * @author Roman Stepanenko after Graeme Rocher - * @since 1.0 - */ -class SimpleDBSpringConfigurer extends SpringConfigurer { - - @Override - String getDatastoreType() { - return "SimpleDB" - } - - @Override - Closure getSpringCustomizer() { - return { - def simpleDBConfig = application.config?.grails?.simpledb - def cacheAdapters = application.config?.grails?.cacheAdapters - - def theCacheAdapterRepository = new TPCacheAdapterRepositoryImpl() - cacheAdapters?.each { clazz, adapter -> - theCacheAdapterRepository.setTPCacheAdapter(clazz, adapter) - } - - simpledbTransactionManager(DatastoreTransactionManager) { - datastore = ref("simpledbDatastore") - } - - simpledbMappingContext(SimpleDBMappingContextFactoryBean) { - grailsApplication = ref('grailsApplication') - pluginManager = ref('pluginManager') - } - - simpledbDatastore(SimpleDBDatastoreFactoryBean) { - mappingContext = ref("simpledbMappingContext") - config = simpleDBConfig.toProperties() - cacheAdapterRepository = theCacheAdapterRepository - } - } - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Book.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Book.groovy deleted file mode 100644 index 2ac7a8c99..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Book.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Book implements Serializable { - String id - Long version - String author - String title - Boolean published = false -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ChildEntity.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ChildEntity.groovy deleted file mode 100644 index 0af34b41f..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ChildEntity.groovy +++ /dev/null @@ -1,22 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class ChildEntity implements Serializable { - String id - Long version - String name - - String toString() { - "ChildEntity{id='$id', name='$name'}" - } - - static belongsTo = [TestEntity] -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/City.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/City.groovy deleted file mode 100644 index 012b2077a..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/City.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class City extends Location{ - String id - Long version - BigDecimal latitude - BigDecimal longitude -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy deleted file mode 100644 index df17bd2b4..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy +++ /dev/null @@ -1,29 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class ClassWithListArgBeforeValidate implements Serializable { - String id - Long version - - def listArgCounter = 0 - def propertiesPassedToBeforeValidate - String name - - def beforeValidate(List properties) { - ++listArgCounter - propertiesPassedToBeforeValidate = properties - } - - static constraints = { - name blank: false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy deleted file mode 100644 index eda83bef4..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class ClassWithNoArgBeforeValidate implements Serializable { - String id - Long version - - def noArgCounter = 0 - String name - - def beforeValidate() { - ++noArgCounter - } - - static constraints = { - name blank: false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy deleted file mode 100644 index 755c6f81f..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy +++ /dev/null @@ -1,32 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class ClassWithOverloadedBeforeValidate implements Serializable { - String id - Long version - - def noArgCounter = 0 - def listArgCounter = 0 - def propertiesPassedToBeforeValidate - String name - def beforeValidate() { - ++noArgCounter - } - def beforeValidate(List properties) { - ++listArgCounter - propertiesPassedToBeforeValidate = properties - } - - static constraints = { - name blank: false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/CommonTypes.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/CommonTypes.groovy deleted file mode 100644 index dcb1487d9..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/CommonTypes.groovy +++ /dev/null @@ -1,38 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class CommonTypes implements Serializable { - String id - Long version - - String name - - Long l - Byte b - Short s - Boolean bool - Integer i - URL url - Date date - Calendar c - BigDecimal bd - BigInteger bi - Double d - Float f - TimeZone tz - Locale loc - Currency cur - byte[] ba - - String toString() { - "CommonTypes{id='$id', version=$version, name='$name', l=$l, b=$b, s=$s, bool=$bool, i=$i, url=$url, date=$date, c=$c, bd=$bd, bi=$bi, d=$d, f=$f, tz=$tz, loc=$loc, cur=$cur}" - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ConstrainedEntity.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ConstrainedEntity.groovy deleted file mode 100644 index 3d10e03a8..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ConstrainedEntity.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package grails.gorm.tests - -class ConstrainedEntity implements Serializable { - - static final MAX_VALUE = 1000 - static final List ALLOWABLE_VALUES=['ABC','DEF','GHI'] - - String id - Integer num - String str - - static constraints = { - num maxSize: MAX_VALUE /*Must be MyDomainClass.MAX_VALUE in order work with redis*/ - str validator: { val, obj -> - if (val != null && !ALLOWABLE_VALUES.contains(val)) {/*Must be MyDomainClass.ALLOWABLE_VALUES in order work with redis */ - return ['not.valid'] - } - } - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Country.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Country.groovy deleted file mode 100644 index 9dc457545..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Country.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Country extends Location { - String id - Long version - - Integer population - - static hasMany = [residents: Person] - Set residents - - String toString() { - "Country{id='$id', population=$population, residents=$residents}" - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy deleted file mode 100644 index d8448adb5..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy +++ /dev/null @@ -1,158 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.tests.ChildEntity -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.TestEntity -import spock.lang.Ignore - -/** - * Removed some projection tests from standard CriteriaBuilderSpec because SimpleDB allows only count(*) in the select. - * The rest is identical to the main CriteriaBuilderSpec. - */ - -class CriteriaBuilderSpec extends GormDatastoreSpec { - void "Test idEq method"() { - given: - def entity = new TestEntity(name:"Bob", age: 44, child:new ChildEntity(name:"Child")).save(flush:true) - - when: - def result = TestEntity.createCriteria().get { idEq entity.id } - - then: - result != null - result.name == 'Bob' - } - - void "Test disjunction query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - or { - like('name', 'B%') - eq('age', 41) - } - } - - then: - 3 == results.size() - } - - void "Test conjunction query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - and { - like('name', 'B%') - eq('age', 40) - } - } - - then: - 1 == results.size() - } - - void "Test list() query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child: new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - like('name', 'B%') - } - - then: - 2 == results.size() - - when: - criteria = TestEntity.createCriteria() - results = criteria.list { - like('name', 'B%') - maxResults 1 - } - - then: - 1 == results.size() - } - - void "Test count()"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def result = criteria.count { - like('name', 'B%') - } - - then: - 2 == result - } - - void "Test obtain a single result"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def result = criteria.get { - eq('name', 'Bob') - } - - then: - result != null - "Bob" == result.name - } - - void "Test order by a property name"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - like('name', 'B%') - order "age" - } - - then: - "Bob" == results[0].name - "Barney" == results[1].name - - when: - criteria = TestEntity.createCriteria() - results = criteria.list { - like('name', 'B%') - order "age", "desc" - } - - then: - "Barney" == results[0].name - "Bob" == results[1].name - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/EnumThing.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/EnumThing.groovy deleted file mode 100644 index fef9a5295..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/EnumThing.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class EnumThing implements Serializable { - String id - Long version - - String name - TestEnum en -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Face.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Face.groovy deleted file mode 100644 index f0ced9672..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Face.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -@Entity -class Face implements Serializable { - String id - String name - Nose nose - static hasOne = [nose: Nose] -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/GroupWithin.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/GroupWithin.groovy deleted file mode 100644 index 7f3fb534c..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/GroupWithin.groovy +++ /dev/null @@ -1,26 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class GroupWithin implements Serializable { - String id - Long version - - String name - String org - static constraints = { - name unique:"org" -// org index:true - } - - String toString() { - "GroupWithin{id='$id', version=$version, name='$name', org='$org'}" - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Highway.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Highway.groovy deleted file mode 100644 index 9b6106b09..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Highway.groovy +++ /dev/null @@ -1,19 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class Highway implements Serializable { - String id - Long version - - Boolean bypassed - String name -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/InheritanceSpec.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/InheritanceSpec.groovy deleted file mode 100644 index d27248f14..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/InheritanceSpec.groovy +++ /dev/null @@ -1,73 +0,0 @@ -package grails.gorm.tests - -import spock.lang.Ignore - -/** - * Removed "Test querying with inheritance" from InheritanceSpec because it is not supported currently. - * The rest is identical to the main CriteriaBuilderSpec. - */ -class InheritanceSpec extends GormDatastoreSpec { - - void "Test inheritance with dynamic finder"() { - - given: - def city = new City([code: "UK", name: "London", longitude: 49.1, latitude: 53.1]) - def country = new Country([code: "UK", name: "United Kingdom", population: 10000000]) - - city.save() - country.save(flush:true) - session.clear() - - when: - def cities = City.findAllByCode("UK") - def countries = Country.findAllByCode("UK") - - then: - 1 == cities.size() - 1 == countries.size() - "London" == cities[0].name - "United Kingdom" == countries[0].name - } - - @Ignore - void "Test querying with inheritance"() { - - given: - def city = new City([code: "LON", name: "London", longitude: 49.1, latitude: 53.1]) - def location = new Location([code: "XX", name: "The World"]) - def country = new Country([code: "UK", name: "United Kingdom", population: 10000000]) - - country.save() - city.save() - location.save() - - session.flush() - - when: - city = City.get(city.id) - def london = Location.get(city.id) - country = Location.findByName("United Kingdom") - def london2 = Location.findByName("London") - - then: - 1 == City.count() - 1 == Country.count() - 3 == Location.count() - - city != null - city instanceof City - london instanceof City - london2 instanceof City - "London" == london2.name - 49.1 == london2.longitude - "LON" == london2.code - - country instanceof Country - "UK" == country.code - 10000000 == country.population - } - - def clearSession() { - City.withSession { session -> session.flush() } - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/LexComparisonSpec.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/LexComparisonSpec.groovy deleted file mode 100644 index aba88f2f3..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/LexComparisonSpec.groovy +++ /dev/null @@ -1,370 +0,0 @@ -package grails.gorm.tests - -/** - * Tests correctness of lexicographical comparisons and encoding. - * - * @author Roman Stepanenko - */ -class LexComparisonSpec extends GormDatastoreSpec { - void "Test byte comparison"() { - given: - create("Alex") { it.setB(Byte.MAX_VALUE) }.save() - create("Bob") { it.setB(Byte.MIN_VALUE) }.save() - create("Sam") { it.setB(-102 as byte) }.save() - create("Carl") { it.setB(-15 as byte) }.save() - create("Don") { it.setB(-13 as byte) }.save() - create("Earl") { it.setB(0 as byte) }.save() - create("Roman") { it.setB(15 as byte) }.save() - create("Glen") { it.setB(125 as byte) }.save() - session.flush() - session.clear() - - def criteria = CommonTypes.createCriteria() - - when: - def results = CommonTypes.findAllByB(Byte.MAX_VALUE) - - then: - results.size() == 1 - results[0].name == 'Alex' - - when: - results = CommonTypes.findAllByB(Byte.MIN_VALUE) - - then: - results.size() == 1 - results[0].name == 'Bob' - - when: - results = CommonTypes.findAllByB(-13 as byte) - - then: - results.size() == 1 - results[0].name == 'Don' - - when: - results = CommonTypes.findAllByB(125 as byte) - - then: - results.size() == 1 - results[0].name == 'Glen' - - when: - results = criteria.list { - gt('b', 0 as byte) - order("b", "asc") - } - - then: - results.size() == 3 - results.collect {it.name} == ["Roman", "Glen", "Alex"] - - when: - results = criteria.list { - gt('b', -14 as byte) - order("b", "asc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Don", "Earl", "Roman", "Glen", "Alex"] - - when: - results = criteria.list { - lt('b', 0 as byte) - order("b", "asc") - } - - then: - results.size() == 4 - results.collect {it.name} == ["Bob", "Sam", "Carl", "Don"] - - when: - results = criteria.list { - lt('b', 2 as byte) - order("b", "desc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Earl", "Don", "Carl", "Sam", "Bob"] - } - - void "Test short comparison"() { - given: - create("Alex") { it.setS(Short.MAX_VALUE) }.save() - create("Bob") { it.setS(Short.MIN_VALUE) }.save() - create("Sam") { it.setS(-102 as short) }.save() - create("Carl") { it.setS(-15 as short) }.save() - create("Don") { it.setS(-13 as short) }.save() - create("Earl") { it.setS(0 as short) }.save() - create("Roman") { it.setS(15 as short) }.save() - create("Glen") { it.setS(125 as short) }.save() - session.flush() - session.clear() - - def criteria = CommonTypes.createCriteria() - - when: - def results = CommonTypes.findAllByS(Short.MAX_VALUE) - - then: - results.size() == 1 - results[0].name == 'Alex' - - when: - results = CommonTypes.findAllByS(Short.MIN_VALUE) - - then: - results.size() == 1 - results[0].name == 'Bob' - - when: - results = CommonTypes.findAllByS(-13 as short) - - then: - results.size() == 1 - results[0].name == 'Don' - - when: - results = CommonTypes.findAllByS(125 as short) - - then: - results.size() == 1 - results[0].name == 'Glen' - - when: - results = criteria.list { - gt('s', 0 as short) - order("s", "asc") - } - - then: - results.size() == 3 - results.collect {it.name} == ["Roman", "Glen", "Alex"] - - when: - results = criteria.list { - gt('s', -14 as short) - order("s", "asc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Don", "Earl", "Roman", "Glen", "Alex"] - - when: - results = criteria.list { - lt('s', 0 as short) - order("s", "asc") - } - - then: - results.size() == 4 - results.collect {it.name} == ["Bob", "Sam", "Carl", "Don"] - - when: - results = criteria.list { - lt('s', 2 as short) - order("s", "desc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Earl", "Don", "Carl", "Sam", "Bob"] - } - - void "Test integer comparison"() { - given: - create("Alex") { it.setI(Integer.MAX_VALUE) }.save() - create("Bob") { it.setI(Integer.MIN_VALUE) }.save() - create("Sam") { it.setI(-102 as int) }.save() - create("Carl") { it.setI(-15 as int) }.save() - create("Don") { it.setI(-13 as int) }.save() - create("Earl") { it.setI(0 as int) }.save() - create("Roman") { it.setI(15 as int) }.save() - create("Glen") { it.setI(125 as int) }.save() - session.flush() - session.clear() - - def criteria = CommonTypes.createCriteria() - - when: - def results = CommonTypes.findAllByI(Integer.MAX_VALUE) - - then: - results.size() == 1 - results[0].name == 'Alex' - - when: - results = CommonTypes.findAllByI(Integer.MIN_VALUE) - - then: - results.size() == 1 - results[0].name == 'Bob' - - when: - results = CommonTypes.findAllByI(-13 as int) - - then: - results.size() == 1 - results[0].name == 'Don' - - when: - results = CommonTypes.findAllByI(125 as int) - - then: - results.size() == 1 - results[0].name == 'Glen' - - when: - results = criteria.list { - gt('i', 0 as int) - order("i", "asc") - } - - then: - results.size() == 3 - results.collect {it.name} == ["Roman", "Glen", "Alex"] - - when: - results = criteria.list { - gt('i', -14 as int) - order("i", "asc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Don", "Earl", "Roman", "Glen", "Alex"] - - when: - results = criteria.list { - lt('i', 0 as int) - order("i", "asc") - } - - then: - results.size() == 4 - results.collect {it.name} == ["Bob", "Sam", "Carl", "Don"] - - when: - results = criteria.list { - lt('i', 2 as int) - order("i", "desc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Earl", "Don", "Carl", "Sam", "Bob"] - } - - void "Test long comparison"() { - given: - create("Alex") { it.setL(Long.MAX_VALUE) }.save() - create("Bob") { it.setL(Long.MIN_VALUE) }.save() - create("Sam") { it.setL(-102 as long) }.save() - create("Carl") { it.setL(-15 as long) }.save() - create("Don") { it.setL(-13 as long) }.save() - create("Earl") { it.setL(0 as long) }.save() - create("Roman") { it.setL(15 as long) }.save() - create("Glen") { it.setL(125 as long) }.save() - session.flush() - session.clear() - - def criteria = CommonTypes.createCriteria() - - when: - def results = CommonTypes.findAllByL(Long.MAX_VALUE) - - then: - results.size() == 1 - results[0].name == 'Alex' - - when: - results = CommonTypes.findAllByL(Long.MIN_VALUE) - - then: - results.size() == 1 - results[0].name == 'Bob' - - when: - results = CommonTypes.findAllByL(-13 as long) - - then: - results.size() == 1 - results[0].name == 'Don' - - when: - results = CommonTypes.findAllByL(125 as long) - - then: - results.size() == 1 - results[0].name == 'Glen' - - when: - results = criteria.list { - gt('l', 0 as long) - order("l", "asc") - } - - then: - results.size() == 3 - results.collect {it.name} == ["Roman", "Glen", "Alex"] - - when: - results = criteria.list { - gt('l', -14 as long) - order("l", "asc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Don", "Earl", "Roman", "Glen", "Alex"] - - when: - results = criteria.list { - lt('l', 0 as long) - order("l", "asc") - } - - then: - results.size() == 4 - results.collect {it.name} == ["Bob", "Sam", "Carl", "Don"] - - when: - results = criteria.list { - lt('l', 2 as long) - order("l", "desc") - } - - then: - results.size() == 5 - results.collect {it.name} == ["Earl", "Don", "Carl", "Sam", "Bob"] - } - - private CommonTypes create(name, modifier) { - def now = new Date() - def cal = new GregorianCalendar() - def ct = new CommonTypes( - name: name, - l: 10L, - b: 10 as byte, - s: 10 as short, - bool: true, - i: 10, - url: new URL("http://google.com"), - date: now, - c: cal, - bd: 1.0, - bi: 10 as BigInteger, - d: 1.0 as Double, - f: 1.0 as Float, - tz: TimeZone.getTimeZone("GMT"), - loc: Locale.UK, - cur: Currency.getInstance("USD") - ) - modifier(ct) - print "returning: "+ct - return ct - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Location.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Location.groovy deleted file mode 100644 index de3d9a217..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Location.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class Location implements Serializable { - String id - Long version - - String name - String code = "DEFAULT" - - def namedAndCode() { - "$name - $code" - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy deleted file mode 100644 index c4e87e135..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/ModifyPerson.groovy +++ /dev/null @@ -1,22 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class ModifyPerson implements Serializable { - String id - Long version - - String name - - def beforeInsert() { - name = "Fred" - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/MultilineValueSpec.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/MultilineValueSpec.groovy deleted file mode 100644 index 55ef43131..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/MultilineValueSpec.groovy +++ /dev/null @@ -1,31 +0,0 @@ -package grails.gorm.tests - -/** - * Tests whether values with line breaks are stored and retrieved correctly. - */ -class MultilineValueSpec extends GormDatastoreSpec { - void "Test multivalue with slash n"() { - given: - def multiline = "Bob\nThe coder\nBuilt decoder" - def entity = new Book(title: multiline, author: "Mark", published: true).save(flush:true) - - when: - def result = Book.get(entity.id) - - then: - result != null - result.title == multiline - } - void "Test multivalue with slash r slash n"() { - given: - def multiline = "Bob\r\nThe coder\r\nBuilt decoder" - def entity = new Book(title: multiline, author: "Mark", published: true).save(flush:true) - - when: - def result = Book.get(entity.id) - - then: - result != null - result.title == multiline - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Nose.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Nose.groovy deleted file mode 100644 index e16c0791e..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Nose.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -@Entity -class Nose implements Serializable { - String id - boolean hasFreckles - Face face - static belongsTo = [face: Face] -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/OptLockNotVersioned.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/OptLockNotVersioned.groovy deleted file mode 100644 index c68ab0bb7..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/OptLockNotVersioned.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class OptLockNotVersioned implements Serializable { - String id - - String name - - static mapping = { - version false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/OptLockVersioned.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/OptLockVersioned.groovy deleted file mode 100644 index 5b41e9a6f..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/OptLockVersioned.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class OptLockVersioned implements Serializable { - String id - Long version - String name -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy deleted file mode 100644 index a9bbaef2c..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PagedResultSpec.groovy +++ /dev/null @@ -1,53 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.PagedResultList - -import spock.lang.Ignore - -/** - * Ignored for SimpleDB because SimpleDB doesn't support pagination - */ -@Ignore -class PagedResultSpec extends GormDatastoreSpec { - - void "Test that a paged result list is returned from the list() method with pagination params"() { - given:"Some people" - createPeople() - - when:"The list method is used with pagination params" - def results = Person.list(offset:2, max:2) - - then:"You get a paged result list back" - results instanceof PagedResultList - results.size() == 2 - results[0].firstName == "Bart" - results[1].firstName == "Lisa" - results.totalCount == 6 - } - - void "Test that a paged result list is returned from the critera with pagination params"() { - given:"Some people" - createPeople() - - when:"The list method is used with pagination params" - def results = Person.createCriteria().list(offset:1, max:2) { - eq 'lastName', 'Simpson' - } - - then:"You get a paged result list back" - results instanceof PagedResultList - results.size() == 2 - results[0].firstName == "Marge" - results[1].firstName == "Bart" - results.totalCount == 4 - } - - protected void createPeople() { - new Person(firstName: "Homer", lastName: "Simpson", age:45).save() - new Person(firstName: "Marge", lastName: "Simpson", age:40).save() - new Person(firstName: "Bart", lastName: "Simpson", age:9).save() - new Person(firstName: "Lisa", lastName: "Simpson", age:7).save() - new Person(firstName: "Barney", lastName: "Rubble", age:35).save() - new Person(firstName: "Fred", lastName: "Flinstone", age:41).save() - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Person.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Person.groovy deleted file mode 100644 index 0175d85d9..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Person.groovy +++ /dev/null @@ -1,35 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Person implements Serializable { - String id - Long version - - String firstName - String lastName - Integer age = 0 - Set pets = [] as Set - static hasMany = [pets: Pet] - - static peopleWithOlderPets = where { - pets { - age > 9 - } - } - - static peopleWithOlderPets2 = where { - pets.age > 9 - } - - String toString() { - "Person{firstName='$firstName', id='$id', lastName='$lastName', pets=$pets}" - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PersonEvent.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PersonEvent.groovy deleted file mode 100644 index 67ed3444d..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PersonEvent.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class PersonEvent implements Serializable { - String id - Long version - - String name - Date dateCreated - Date lastUpdated - - def personService - - static STORE_INITIAL = [ - beforeDelete: 0, afterDelete: 0, - beforeUpdate: 0, afterUpdate: 0, - beforeInsert: 0, afterInsert: 0, - beforeLoad: 0, afterLoad: 0] - - static STORE = [:] + STORE_INITIAL - - static void resetStore() { - STORE = [:] + STORE_INITIAL - } - - def beforeDelete() { - STORE.beforeDelete++ - } - - void afterDelete() { - STORE.afterDelete++ - } - - def beforeUpdate() { - STORE.beforeUpdate++ - } - - void afterUpdate() { - STORE.afterUpdate++ - } - - def beforeInsert() { - STORE.beforeInsert++ - } - - void afterInsert() { - STORE.afterInsert++ - } - - void beforeLoad() { - STORE.beforeLoad++ - } - - void afterLoad() { - STORE.afterLoad++ - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Pet.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Pet.groovy deleted file mode 100644 index 88b7cf046..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Pet.groovy +++ /dev/null @@ -1,30 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Pet implements Serializable { - String id - Long version - - String name - Date birthDate = new Date() - PetType type = new PetType(name: "Unknown") - Person owner - Integer age - - String toString() { - "Pet{id='$id', name='$name', birthDate=$birthDate, type=$type, owner=$owner, age=$age}" - } - - static constraints = { - owner nullable:true - age nullable: true - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PetType.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PetType.groovy deleted file mode 100644 index 60b6176cd..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PetType.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class PetType implements Serializable { - String id - Long version - - String name - - static belongsTo = Pet -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Plant.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Plant.groovy deleted file mode 100644 index a7844a9e3..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Plant.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Plant implements Serializable { - String id - Long version - - boolean goesInPatch - String name -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PlantCategory.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PlantCategory.groovy deleted file mode 100644 index 9f979b449..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PlantCategory.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class PlantCategory implements Serializable { - String id - Long version - - Set plants - String name - - static hasMany = [plants:Plant] -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PlantNumericIdValue.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PlantNumericIdValue.groovy deleted file mode 100644 index afa4287b3..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PlantNumericIdValue.groovy +++ /dev/null @@ -1,26 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB, uses hilo id generator for SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class PlantNumericIdValue implements Serializable { - String id - Long version - - boolean goesInPatch - String name - - String toString() { - "PlantNumericIdValue{id='$id', version=$version, goesInPatch=$goesInPatch, name='$name'}" - } - - static mapping = { - id_generator type: 'hilo', maxLo: 5 - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy deleted file mode 100644 index 9d508239f..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package grails.gorm.tests - -import org.junit.Ignore - -/** - * Tests for criteria queries that compare two properties - */ -class PropertyComparisonQuerySpec extends GormDatastoreSpec{ - - @Ignore - void "Test eqProperty criterion"() { - // TODO: implement eqProperty query operations - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Publication.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Publication.groovy deleted file mode 100644 index c55ae7f2c..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Publication.groovy +++ /dev/null @@ -1,81 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Publication implements Serializable { - String id - Long version - - String title - Date datePublished - Boolean paperback = true - - String toString() { - "Publication{id='$id', title='$title', paperback=$paperback, datePublished=$datePublished}" - } - - static namedQueries = { - lastPublishedBefore { date -> - uniqueResult = true - le 'datePublished', date - order 'datePublished', 'desc' - } - - recentPublications { - def now = new Date() - gt 'datePublished', now - 365 - } - - publicationsWithBookInTitle { - like 'title', 'Book%' - } - - recentPublicationsByTitle { title -> - recentPublications() - eq 'title', title - } - - latestBooks { - maxResults(10) - order("datePublished", "desc") - } - - publishedBetween { start, end -> - between 'datePublished', start, end - } - - publishedAfter { date -> - gt 'datePublished', date - } - - paperbackOrRecent { - or { - def now = new Date() - gt 'datePublished', now - 365 - paperbacks() - } - } - - paperbacks { - eq 'paperback', true - } - - paperbackAndRecent { - paperbacks() - recentPublications() - } - - thisWeeksPaperbacks() { - paperbacks() - def today = new Date() - publishedBetween(today - 7, today) - } - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/SimpleDBHiloSpec.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/SimpleDBHiloSpec.groovy deleted file mode 100644 index c4a43ec52..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/SimpleDBHiloSpec.groovy +++ /dev/null @@ -1,37 +0,0 @@ -package grails.gorm.tests - -/** - * Tests hilo simpledb id generator - */ -class SimpleDBHiloSpec extends GormDatastoreSpec { - - void "Test one"() { - given: - def entity = new PlantNumericIdValue(name: "Single").save(flush:true) - - when: - def result = PlantNumericIdValue.get(entity.id) - - then: - result != null - Long.parseLong(result.id) > 0 - result.id == Long.toString(Long.parseLong(result.id)) - } - - void "Test multiple"() { - given: - def entities = [] - for (i in 1..10) { - entities.add(new PlantNumericIdValue(name: "OneOfThem-"+i).save(flush:true)) - } - - expect: - //make sure ids are monotonically increase - long previous = 0 - entities.each { it -> - long current = Long.parseLong(it.id) - assert current > previous - previous = current - } - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Simples.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Simples.groovy deleted file mode 100644 index 164fc09da..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Simples.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS DynamoDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class Simples implements Serializable { - String id - Long version - - boolean goesInPatch - String name -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy deleted file mode 100644 index 082db7656..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/SizeQuerySpec.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.tests.GormDatastoreSpec -import org.junit.Ignore - -/** - * Tests for querying the size of collections etc. - */ -class SizeQuerySpec extends GormDatastoreSpec { - - @Ignore - void "Test sizeEq criterion"() { - // TODO: implement sizeEq query operations - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/StringConversionSpec.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/StringConversionSpec.groovy deleted file mode 100644 index 277525bad..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/StringConversionSpec.groovy +++ /dev/null @@ -1,165 +0,0 @@ -package grails.gorm.tests - -import org.grails.datastore.mapping.simpledb.model.types.SimpleDBTypeConverterRegistrar - -/** - * Tests back and forth conversion to String of numeric and other datatypes. - * - * @author Roman Stepanenko - */ -class StringConversionSpec extends GormDatastoreSpec { - - void "Test byte conversion"() { - given: - def fromString = SimpleDBTypeConverterRegistrar.STRING_TO_BYTE_CONVERTER - def toString = SimpleDBTypeConverterRegistrar.BYTE_TO_STRING_CONVERTER - - expect: - fromString.convert(toString.convert(0 as byte)) == 0 as byte - fromString.convert(toString.convert(1 as byte)) == 1 as byte - fromString.convert(toString.convert(-1 as byte)) == -1 as byte - fromString.convert(toString.convert(10 as byte)) == 10 as byte - fromString.convert(toString.convert(109 as byte)) == 109 as byte - fromString.convert(toString.convert(-23 as byte)) == -23 as byte - fromString.convert(toString.convert(-123 as byte)) == -123 as byte - fromString.convert(toString.convert(Byte.MAX_VALUE as byte)) == Byte.MAX_VALUE as byte - fromString.convert(toString.convert(Byte.MAX_VALUE-1 as byte)) == Byte.MAX_VALUE-1 as byte - fromString.convert(toString.convert(Byte.MAX_VALUE-2 as byte)) == Byte.MAX_VALUE-2 as byte - fromString.convert(toString.convert(Byte.MAX_VALUE-10 as byte)) == Byte.MAX_VALUE-10 as byte - fromString.convert(toString.convert(Byte.MIN_VALUE as byte)) == Byte.MIN_VALUE as byte - fromString.convert(toString.convert(Byte.MIN_VALUE+1 as byte)) == Byte.MIN_VALUE+1 as byte - fromString.convert(toString.convert(Byte.MIN_VALUE+2 as byte)) == Byte.MIN_VALUE+2 as byte - fromString.convert(toString.convert(Byte.MIN_VALUE+30 as byte)) == Byte.MIN_VALUE+30 as byte - - //test that for short numeric string conversion happens as is - fromString.convert("1") == 1 as byte - fromString.convert("-1") == -1 as byte - fromString.convert("01") == 1 as byte - fromString.convert("001") == 1 as byte - fromString.convert("10") == 10 as byte - fromString.convert("-10") == -10 as byte - fromString.convert("010") == 10 as byte - fromString.convert("102") == 102 as byte - fromString.convert("-102") == -102 as byte - } - - void "Test short conversion"() { - given: - def fromString = SimpleDBTypeConverterRegistrar.STRING_TO_SHORT_CONVERTER - def toString = SimpleDBTypeConverterRegistrar.SHORT_TO_STRING_CONVERTER - - expect: - fromString.convert(toString.convert(0 as short)) == 0 as short - fromString.convert(toString.convert(-1 as short)) == -1 as short - fromString.convert(toString.convert(1 as short)) == 1 as short - fromString.convert(toString.convert(10 as short)) == 10 as short - fromString.convert(toString.convert(109 as short)) == 109 as short - fromString.convert(toString.convert(-23 as short)) == -23 as short - fromString.convert(toString.convert(-123 as short)) == -123 as short - fromString.convert(toString.convert(Short.MAX_VALUE as short)) == Short.MAX_VALUE as short - fromString.convert(toString.convert(Short.MAX_VALUE-1 as short)) == Short.MAX_VALUE-1 as short - fromString.convert(toString.convert(Short.MAX_VALUE-2 as short)) == Short.MAX_VALUE-2 as short - fromString.convert(toString.convert(Short.MAX_VALUE-10 as short)) == Short.MAX_VALUE-10 as short - fromString.convert(toString.convert(Short.MIN_VALUE as short)) == Short.MIN_VALUE as short - fromString.convert(toString.convert(Short.MIN_VALUE+1 as short)) == Short.MIN_VALUE+1 as short - fromString.convert(toString.convert(Short.MIN_VALUE+2 as short)) == Short.MIN_VALUE+2 as short - fromString.convert(toString.convert(Short.MIN_VALUE+30 as short)) == Short.MIN_VALUE+30 as short - - //test that for short numeric string conversion happens as is - fromString.convert("1") == 1 as short - fromString.convert("-1") == -1 as short - fromString.convert("01") == 1 as short - fromString.convert("001") == 1 as short - fromString.convert("10") == 10 as short - fromString.convert("-10") == -10 as short - fromString.convert("010") == 10 as short - fromString.convert("102") == 102 as short - fromString.convert("-102") == -102 as short - } - - void "Test integer conversion"() { - given: - def fromString = SimpleDBTypeConverterRegistrar.STRING_TO_INTEGER_CONVERTER - def toString = SimpleDBTypeConverterRegistrar.INTEGER_TO_STRING_CONVERTER - - expect: - fromString.convert(toString.convert(0 as int)) == 0 as int - fromString.convert(toString.convert(1 as int)) == 1 as int - fromString.convert(toString.convert(-1 as int)) == -1 as int - fromString.convert(toString.convert(10 as int)) == 10 as int - fromString.convert(toString.convert(109 as int)) == 109 as int - fromString.convert(toString.convert(-23 as int)) == -23 as int - fromString.convert(toString.convert(-123 as int)) == -123 as int - fromString.convert(toString.convert(Integer.MAX_VALUE as int)) == Integer.MAX_VALUE as int - fromString.convert(toString.convert(Integer.MAX_VALUE-1 as int)) == Integer.MAX_VALUE-1 as int - fromString.convert(toString.convert(Integer.MAX_VALUE-2 as int)) == Integer.MAX_VALUE-2 as int - fromString.convert(toString.convert(Integer.MAX_VALUE-10 as int)) == Integer.MAX_VALUE-10 as int - fromString.convert(toString.convert(Integer.MIN_VALUE as int)) == Integer.MIN_VALUE as int - fromString.convert(toString.convert(Integer.MIN_VALUE+1 as int)) == Integer.MIN_VALUE+1 as int - fromString.convert(toString.convert(Integer.MIN_VALUE+2 as int)) == Integer.MIN_VALUE+2 as int - fromString.convert(toString.convert(Integer.MIN_VALUE+30 as int)) == Integer.MIN_VALUE+30 as int - - fromString.convert(toString.convert(Short.MAX_VALUE as short)) == Short.MAX_VALUE as short - fromString.convert(toString.convert(Short.MAX_VALUE-1 as short)) == Short.MAX_VALUE-1 as short - fromString.convert(toString.convert(Short.MAX_VALUE-2 as short)) == Short.MAX_VALUE-2 as short - fromString.convert(toString.convert(Short.MAX_VALUE-10 as short)) == Short.MAX_VALUE-10 as short - fromString.convert(toString.convert(Short.MIN_VALUE as short)) == Short.MIN_VALUE as short - fromString.convert(toString.convert(Short.MIN_VALUE+1 as short)) == Short.MIN_VALUE+1 as short - fromString.convert(toString.convert(Short.MIN_VALUE+2 as short)) == Short.MIN_VALUE+2 as short - fromString.convert(toString.convert(Short.MIN_VALUE+30 as short)) == Short.MIN_VALUE+30 as short - - //test that for short numeric string conversion happens as is - fromString.convert("1") == 1 as int - fromString.convert("-1") == -1 as int - fromString.convert("01") == 1 as int - fromString.convert("001") == 1 as int - fromString.convert("10") == 10 as int - fromString.convert("-10") == -10 as int - fromString.convert("010") == 10 as int - fromString.convert("102") == 102 as int - fromString.convert("-102") == -102 as int - } - - void "Test long conversion"() { - given: - def fromString = SimpleDBTypeConverterRegistrar.STRING_TO_LONG_CONVERTER - def toString = SimpleDBTypeConverterRegistrar.LONG_TO_STRING_CONVERTER - - expect: - fromString.convert(toString.convert(0 as long)) == 0 as long - fromString.convert(toString.convert(-1 as long)) == -1 as long - fromString.convert(toString.convert(1 as long)) == 1 as long - fromString.convert(toString.convert(10 as long)) == 10 as long - fromString.convert(toString.convert(109 as long)) == 109 as long - fromString.convert(toString.convert(-23 as long)) == -23 as long - fromString.convert(toString.convert(-123 as long)) == -123 as long - fromString.convert(toString.convert(Long.MAX_VALUE as long)) == Long.MAX_VALUE as long - fromString.convert(toString.convert(Long.MAX_VALUE-1 as long)) == Long.MAX_VALUE-1 as long - fromString.convert(toString.convert(Long.MAX_VALUE-2 as long)) == Long.MAX_VALUE-2 as long - fromString.convert(toString.convert(Long.MAX_VALUE-10 as long)) == Long.MAX_VALUE-10 as long - fromString.convert(toString.convert(Long.MIN_VALUE as long)) == Long.MIN_VALUE as long - fromString.convert(toString.convert(Long.MIN_VALUE+1 as long)) == Long.MIN_VALUE+1 as long - fromString.convert(toString.convert(Long.MIN_VALUE+2 as long)) == Long.MIN_VALUE+2 as long - fromString.convert(toString.convert(Long.MIN_VALUE+30 as long)) == Long.MIN_VALUE+30 as long - - fromString.convert(toString.convert(Integer.MAX_VALUE as int)) == Integer.MAX_VALUE as int - fromString.convert(toString.convert(Integer.MAX_VALUE-1 as int)) == Integer.MAX_VALUE-1 as int - fromString.convert(toString.convert(Integer.MAX_VALUE-2 as int)) == Integer.MAX_VALUE-2 as int - fromString.convert(toString.convert(Integer.MAX_VALUE-10 as int)) == Integer.MAX_VALUE-10 as int - fromString.convert(toString.convert(Integer.MIN_VALUE as int)) == Integer.MIN_VALUE as int - fromString.convert(toString.convert(Integer.MIN_VALUE+1 as int)) == Integer.MIN_VALUE+1 as int - fromString.convert(toString.convert(Integer.MIN_VALUE+2 as int)) == Integer.MIN_VALUE+2 as int - fromString.convert(toString.convert(Integer.MIN_VALUE+30 as int)) == Integer.MIN_VALUE+30 as int - - //test that for short numeric string conversion happens as is - fromString.convert("1") == 1 as long - fromString.convert("-1") == -1 as long - fromString.convert("01") == 1 as long - fromString.convert("001") == 1 as long - fromString.convert("10") == 10 as long - fromString.convert("-10") == -10 as long - fromString.convert("010") == 10 as long - fromString.convert("102") == 102 as long - fromString.convert("-102") == -102 as long - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Task.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Task.groovy deleted file mode 100644 index cfca126f2..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/Task.groovy +++ /dev/null @@ -1,26 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ - -@Entity -class Task implements Serializable { - String id - Long version - - Set tasks - Task task - String name - - static mapping = { - domain 'Task' - } - - static hasMany = [tasks:Task] -} \ No newline at end of file diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/TestEntity.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/TestEntity.groovy deleted file mode 100644 index 13517204c..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/TestEntity.groovy +++ /dev/null @@ -1,34 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class TestEntity implements Serializable { - String id - Long version - - String name - Integer age = 30 - - ChildEntity child - - String toString() { - "TestEntity(AWS){id='$id', name='$name', age=$age, child=$child}" - } - - static constraints = { - name blank: false - child nullable: true - } - - static mapping = { - domain 'TestEntity' - child nullable:true - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/UniqueGroup.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/UniqueGroup.groovy deleted file mode 100644 index 7e8b4869c..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/grails/gorm/tests/UniqueGroup.groovy +++ /dev/null @@ -1,25 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Test entity for testing AWS SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@Entity -class UniqueGroup implements Serializable { - String id - Long version - - String name - - static constraints = { - name unique: true - } - - String toString() { - "UniqueGroup{id='$id', version=$version, name='$name'}" - } -} diff --git a/grails-datastore-gorm-simpledb/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-simpledb/src/test/groovy/org/grails/datastore/gorm/Setup.groovy deleted file mode 100644 index f6a0b269a..000000000 --- a/grails-datastore-gorm-simpledb/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ /dev/null @@ -1,147 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.PlantNumericIdValue - -import java.util.concurrent.CountDownLatch - -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.gorm.simpledb.SimpleDBGormEnhancer -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.simpledb.SimpleDBDatastore -import org.grails.datastore.mapping.simpledb.config.SimpleDBMappingContext -import org.grails.datastore.mapping.simpledb.engine.SimpleDBAssociationInfo -import org.grails.datastore.mapping.simpledb.engine.SimpleDBDomainResolver -import org.grails.datastore.mapping.simpledb.engine.SimpleDBDomainResolverFactory -import org.grails.datastore.mapping.simpledb.util.SimpleDBTemplate -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager -import org.springframework.context.support.GenericApplicationContext -import org.springframework.util.StringUtils -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -/** - * In order to run AWS SimpleDB tests you have to define two system variables: AWS_ACCESS_KEY and AWS_SECRET_KEY with - * your aws credentials and then invoke this command from main directory: - * gradlew grails-datastore-gorm-simpledb:test - * - * or this one to run one specific test: - * gradlew -Dtest.single=CrudOperationsSpec grails-datastore-gorm-simpledb:test - * - * @author graemerocher - * @author Roman Stepanenko - */ -class Setup { - - static simpleDB - static session - - static destroy() { - session.nativeInterface.dropDatabase() - } - - static Session setup(classes) { - classes.add(PlantNumericIdValue.class) - - def env = System.getenv() - final userHome = System.getProperty("user.home") - def settingsFile = new File(userHome, "aws.properties") - def connectionDetails = [:] - if (settingsFile.exists()) { - def props = new Properties() - settingsFile.withReader { reader -> - props.load(reader) - } - connectionDetails.put(SimpleDBDatastore.ACCESS_KEY, props['AWS_ACCESS_KEY']) - connectionDetails.put(SimpleDBDatastore.SECRET_KEY, props['AWS_SECRET_KEY']) - } - - connectionDetails.put(SimpleDBDatastore.DOMAIN_PREFIX_KEY, "TEST_") - connectionDetails.put(SimpleDBDatastore.DELAY_AFTER_WRITES_MS, "7000") //this flag will cause pausing for that many MS after each write - to fight eventual consistency - - simpleDB = new SimpleDBDatastore(new SimpleDBMappingContext(), connectionDetails) - def ctx = new GenericApplicationContext() - ctx.refresh() - simpleDB.applicationContext = ctx - simpleDB.afterPropertiesSet() - - for (cls in classes) { - simpleDB.mappingContext.addPersistentEntity(cls) - } - - cleanOrCreateDomainsIfNeeded(classes, simpleDB.mappingContext, simpleDB) - - PersistentEntity entity = simpleDB.mappingContext.persistentEntities.find { PersistentEntity e -> e.name.contains("TestEntity")} - - simpleDB.mappingContext.addEntityValidator(entity, [ - supports: { Class c -> true }, - validate: { Object o, Errors errors -> - if (!StringUtils.hasText(o.name)) { - errors.rejectValue("name", "name.is.blank") - } - } - ] as Validator) - - def enhancer = new SimpleDBGormEnhancer(simpleDB, new DatastoreTransactionManager(datastore: simpleDB)) - enhancer.enhance() - - simpleDB.mappingContext.addMappingContextListener({ e -> - enhancer.enhance e - } as MappingContext.Listener) - - simpleDB.applicationContext.addApplicationListener new DomainEventListener(simpleDB) - simpleDB.applicationContext.addApplicationListener new AutoTimestampEventListener(simpleDB) - - session = simpleDB.connect() - - return session - } - - /** - * Creates AWS domain if AWS domain corresponding to a test entity class does not exist, or cleans it if it does exist. - * @param domainClasses - * @param mappingContext - * @param simpleDBDatastore - */ - static void cleanOrCreateDomainsIfNeeded(def domainClasses, mappingContext, simpleDBDatastore) { - SimpleDBTemplate template = simpleDBDatastore.getSimpleDBTemplate() - List existingDomains = template.listDomains() - SimpleDBDomainResolverFactory resolverFactory = new SimpleDBDomainResolverFactory() - CountDownLatch latch = new CountDownLatch(domainClasses.size()) - for (dc in domainClasses) { - def domainClass = dc //explicitly declare local variable which we will be using from the thread - //do simpleDB work in parallel threads for each domain class to speed things up - Thread.start { - try { - PersistentEntity entity = mappingContext.getPersistentEntity(domainClass.getName()) - SimpleDBDomainResolver domainResolver = resolverFactory.buildResolver(entity, simpleDBDatastore) - def domains = domainResolver.getAllDomainsForEntity() - domains.each { domain -> - clearOrCreateDomain(template, existingDomains, domain) - //create domains for associations - entity.getAssociations().each{ association -> - SimpleDBAssociationInfo associationInfo = simpleDBDatastore.getAssociationInfo(association) - if (associationInfo) { - clearOrCreateDomain(template, existingDomains, associationInfo.getDomainName()) - } - } - } - } finally { - latch.countDown() - } - } - } - latch.await() - } - - static clearOrCreateDomain(template, existingDomains, domainName) { - if (existingDomains.contains(domainName)) { - template.deleteAllItems(domainName) //delete all items there - } else { - //create it - template.createDomain(domainName) - } - } -} diff --git a/grails-datastore-gorm-tck/build.gradle b/grails-datastore-gorm-tck/build.gradle deleted file mode 100644 index 64f86c5f9..000000000 --- a/grails-datastore-gorm-tck/build.gradle +++ /dev/null @@ -1,4 +0,0 @@ -dependencies { - compile project(":grails-datastore-gorm") - compile 'junit:junit:4.8.2' -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/AttachMethodSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/AttachMethodSpec.groovy deleted file mode 100644 index 5e0b34543..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/AttachMethodSpec.groovy +++ /dev/null @@ -1,42 +0,0 @@ -package grails.gorm.tests - -/** - * @author graemerocher - */ -class AttachMethodSpec extends GormDatastoreSpec { - - void "Test attach method"() { - given: - def test = new Person(firstName:"Bob", lastName:"Builder").save() - - when: - session.flush() - - then: - session.contains(test) == true - test.isAttached() - test.attached - - when: - test.discard() - - then: - !session.contains(test) - !test.isAttached() - !test.attached - - when: - test.attach() - - then: - session.contains(test) - test.isAttached() - test.attached - - when: - test.discard() - - then: - test == test.attach() - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ChildEntity.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ChildEntity.groovy deleted file mode 100644 index f892c9b5c..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ChildEntity.groovy +++ /dev/null @@ -1,19 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * @author graemerocher - */ -@Entity -class ChildEntity implements Serializable { - Long id - Long version - String name - - static mapping = { - name index:true - } - - static belongsTo = [TestEntity] -} \ No newline at end of file diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/CircularOneToManySpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/CircularOneToManySpec.groovy deleted file mode 100644 index 685c9bb6f..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/CircularOneToManySpec.groovy +++ /dev/null @@ -1,39 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * @author graemerocher - */ -class CircularOneToManySpec extends GormDatastoreSpec{ - - void "Test circular one-to-many"() { - given: - def parent = new Task(name:"Root").save() - def child = new Task(task:parent, name:"Finish Job").save(flush:true) - session.clear() - - when: - parent = Task.findByName("Root") - child = Task.findByName("Finish Job") - - then: - parent.task == null - child.task.id == parent.id - } -} - -@Entity -class Task implements Serializable { - Long id - Long version - Set tasks - Task task - String name - - static mapping = { - name index:true - } - - static hasMany = [tasks:Task] -} \ No newline at end of file diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy deleted file mode 100644 index fbd380fbe..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ClassWithListArgBeforeValidate.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package grails.gorm.tests - -class ClassWithListArgBeforeValidate implements Serializable { - Long id - Long version - def listArgCounter = 0 - def propertiesPassedToBeforeValidate - String name - - def beforeValidate(List properties) { - ++listArgCounter - propertiesPassedToBeforeValidate = properties - } - - static constraints = { - name blank: false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy deleted file mode 100644 index f5e097dfe..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ClassWithNoArgBeforeValidate.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package grails.gorm.tests - -class ClassWithNoArgBeforeValidate implements Serializable { - Long id - Long version - def noArgCounter = 0 - String name - - def beforeValidate() { - ++noArgCounter - } - - static constraints = { - name blank: false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy deleted file mode 100644 index 20e6314c8..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ClassWithOverloadedBeforeValidate.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package grails.gorm.tests - -class ClassWithOverloadedBeforeValidate implements Serializable { - Long id - Long version - def noArgCounter = 0 - def listArgCounter = 0 - def propertiesPassedToBeforeValidate - String name - def beforeValidate() { - ++noArgCounter - } - def beforeValidate(List properties) { - ++listArgCounter - propertiesPassedToBeforeValidate = properties - } - - static constraints = { - name blank: false - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/CommonTypesPersistenceSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/CommonTypesPersistenceSpec.groovy deleted file mode 100644 index 196c1c11d..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/CommonTypesPersistenceSpec.groovy +++ /dev/null @@ -1,76 +0,0 @@ -package grails.gorm.tests - -/** - * @author graemerocher - */ -class CommonTypesPersistenceSpec extends GormDatastoreSpec { - - def testPersistBasicTypes() { - given: - def now = new Date() - def cal = new GregorianCalendar() - def ct = new CommonTypes( - l: 10L, - b: 10 as byte, - s: 10 as short, - bool: true, - i: 10, - url: new URL("http://google.com"), - date: now, - c: cal, - bd: 1.0, - bi: 10 as BigInteger, - d: 1.0 as Double, - f: 1.0 as Float, - tz: TimeZone.getTimeZone("GMT"), - loc: Locale.UK, - cur: Currency.getInstance("USD"), - ba: 'hello'.bytes - ) - - when: - ct.save(flush:true) - ct.discard() - ct = CommonTypes.get(ct.id) - - then: - ct - 10L == ct.l - (10 as byte) == ct.b - (10 as short) == ct.s - true == ct.bool - 10 == ct.i - new URL("http://google.com") == ct.url - now.time == ct.date.time - cal == ct.c - 1.0 == ct.bd - 10 as BigInteger == ct.bi - (1.0 as Double) == ct.d - (1.0 as Float) == ct.f - TimeZone.getTimeZone("GMT") == ct.tz - Locale.UK == ct.loc - Currency.getInstance("USD") == ct.cur - 'hello'.bytes == ct.ba - } -} - -class CommonTypes implements Serializable { - Long id - Long version - Long l - Byte b - Short s - Boolean bool - Integer i - URL url - Date date - Calendar c - BigDecimal bd - BigInteger bi - Double d - Float f - TimeZone tz - Locale loc - Currency cur - byte[] ba -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ConstraintsSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ConstraintsSpec.groovy deleted file mode 100644 index 1ac0eed35..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ConstraintsSpec.groovy +++ /dev/null @@ -1,43 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -class ConstraintsSpec extends GormDatastoreSpec { - - void "Test constraints with static default values"() { - given: "A Test class with static constraint values" - def ce = new ConstrainedEntity(num:1000, str:"ABC") - - when: "saved is called" - ce.save() - - then: - ce.hasErrors() == false - } - - @Override - List getDomainClasses() { - [ConstrainedEntity] - } -} - -@Entity -class ConstrainedEntity implements Serializable { - - static final int MAX_VALUE = 1000 - static final List ALLOWABLE_VALUES = ['ABC','DEF','GHI'] - - Long id - Integer num - String str - - static constraints = { - - num(maxSize: MAX_VALUE) /*Must be MyDomainClass.MAX_VALUE in order work with redis*/ - str validator: { val, obj -> - if (val != null && !ALLOWABLE_VALUES.contains(val)) {/*Must be MyDomainClass.ALLOWABLE_VALUES in order work with redis */ - return ['not.valid'] - } - } - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy deleted file mode 100644 index 5a48bd94c..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/CriteriaBuilderSpec.groovy +++ /dev/null @@ -1,286 +0,0 @@ -package grails.gorm.tests - -import spock.lang.Ignore - -/** - * Abstract base test for criteria queries. Subclasses should do the necessary setup to configure GORM - */ -class CriteriaBuilderSpec extends GormDatastoreSpec { - - void "Test count distinct projection"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - new TestEntity(name:"Chuck", age: age-1, child:new ChildEntity(name:"Chuckie")).save() - - 5 == ChildEntity.count() - - def criteria = TestEntity.createCriteria() - - when: - def result = criteria.get { - projections { - countDistinct "age" - } - } - - then: - result == 4 - } - - @Ignore // ignored this test because the id() projection does not actually exist in GORM for Hibernate - void "Test id projection"() { - given: - def entity = new TestEntity(name:"Bob", age: 44, child:new ChildEntity(name:"Child")).save(flush:true) - - when: - def result = TestEntity.createCriteria().get { - projections { id() } - idEq entity.id - } - - then: - result != null - result == entity.id - } - - void "Test idEq method"() { - given: - def entity = new TestEntity(name:"Bob", age: 44, child:new ChildEntity(name:"Child")).save(flush:true) - - when: - def result = TestEntity.createCriteria().get { idEq entity.id } - - then: - result != null - result.name == 'Bob' - } - - void "Test disjunction query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - or { - like('name', 'B%') - eq('age', 41) - } - } - - then: - 3 == results.size() - } - - void "Test conjunction query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - and { - like('name', 'B%') - eq('age', 40) - } - } - - then: - 1 == results.size() - } - - void "Test list() query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child: new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - like('name', 'B%') - } - - then: - 2 == results.size() - - when: - criteria = TestEntity.createCriteria() - results = criteria.list { - like('name', 'B%') - maxResults 1 - } - - then: - 1 == results.size() - } - - void "Test count()"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def result = criteria.count { - like('name', 'B%') - } - - then: - 2 == result - } - - void "Test obtain a single result"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def result = criteria.get { - eq('name', 'Bob') - } - - then: - result != null - "Bob" == result.name - } - - void "Test order by a property name"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - like('name', 'B%') - order "age" - } - - then: - "Bob" == results[0].name - "Barney" == results[1].name - - when: - criteria = TestEntity.createCriteria() - results = criteria.list { - like('name', 'B%') - order "age", "desc" - } - - then: - "Barney" == results[0].name - "Bob" == results[1].name - } - - void "Test get minimum value with projection"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - Thread.sleep 500 - - def criteria = TestEntity.createCriteria() - - when: - def result = criteria.get { - projections { - min "age" - } - } - - then: - 40 == result - - when: - criteria = TestEntity.createCriteria() - result = criteria.get { - projections { - max "age" - } - } - - then: - 43 == result - - when: - criteria = TestEntity.createCriteria() - def results = criteria.list { - projections { - max "age" - min "age" - } - }.flatten() - - then: - 2 == results.size() - 43 == results[0] - 40 == results[1] - [43, 40] == results - } - - void "Test obtain property value using projection"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - projections { - property "age" - } - } - - then: - [40, 41, 42, 43] == results.sort() - } - - void "Test obtain association entity using property projection"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - 4 == ChildEntity.count() - - def criteria = TestEntity.createCriteria() - - when: - def results = criteria.list { - projections { - property "child" - } - } - - then: - results.find { it.name = "Bob Child"} - results.find { it.name = "Fred Child"} - results.find { it.name = "Barney Child"} - results.find { it.name = "Frank Child"} - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/CrudOperationsSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/CrudOperationsSpec.groovy deleted file mode 100644 index 026546afe..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/CrudOperationsSpec.groovy +++ /dev/null @@ -1,72 +0,0 @@ -package grails.gorm.tests - -import grails.validation.ValidationException - -/** - * @author graemerocher - */ -class CrudOperationsSpec extends GormDatastoreSpec { - - void "Test get using a string-based key"() { - given: - - def t = new TestEntity(name:"Bob", child:new ChildEntity(name:"Child")) - t.save(flush:true) - - when: - t = TestEntity.get("${t.id}") - - then: - t != null - } - - void "Test get returns null of non-existent entity"() { - given: - def t - when: - t = TestEntity.get(1) - then: - t == null - } - - void "Test basic CRUD operations"() { - given: - - def t = new TestEntity(name:"Bob", child:new ChildEntity(name:"Child")) - t.save() - - when: - def results = TestEntity.list() - t = TestEntity.get(t.id) - - then: - t != null - t.id != null - "Bob" == t.name - 1 == results.size() - "Bob" == results[0].name - } - - void "Test save method that takes a map"() { - - given: - def t = new TestEntity(name:"Bob", child:new ChildEntity(name:"Child")) - t.save(param:"one", flush: true) - when: - t = TestEntity.get(t.id) - then: - t.id != null - } - - void "Test failOnError"() { - given: - def t = new TestEntity(child: new ChildEntity(name:"Child")) - - when: - t.save(failOnError: true) - - then: - thrown ValidationException - t.id == null - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/DeleteAllSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/DeleteAllSpec.groovy deleted file mode 100644 index 8ef1e9d40..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/DeleteAllSpec.groovy +++ /dev/null @@ -1,37 +0,0 @@ -package grails.gorm.tests - -class DeleteAllSpec extends GormDatastoreSpec { - - def "Test that many objects can be deleted at once using multiple arguments"() { - given: - def bob = new Person(firstName:"Bob", lastName:"Builder").save(flush: true) - def fred = new Person(firstName:"Fred", lastName:"Flintstone").save(flush: true) - def joe = new Person(firstName:"Joe", lastName:"Doe").save(flush: true) - Person.deleteAll(bob, fred, joe) - session.flush() - - when: - def total = Person.count() - then: - total == 0 - } - def "Test that many objects can be deleted using an iterable"() { - given: - def bob = new Person(firstName:"Bob", lastName:"Builder").save(flush: true) - def fred = new Person(firstName:"Fred", lastName:"Flintstone").save(flush: true) - def joe = new Person(firstName:"Joe", lastName:"Doe").save(flush: true) - - Vector people = new Vector() - people.add(bob) - people.add(fred) - people.add(joe) - - Person.deleteAll(people) - session.flush() - - when: - def total = Person.count() - then: - total == 0 - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy deleted file mode 100644 index ed533070a..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/DetachedCriteriaSpec.groovy +++ /dev/null @@ -1,271 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.DetachedCriteria -import grails.gorm.PagedResultList - -class DetachedCriteriaSpec extends GormDatastoreSpec { - - void "Test the list method returns a PagedResultList with pagination arguments"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria instance is created and the list method used with the max parameter" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - def results = criteria.list(max:2) - - then:"The results are a PagedResultList" - results instanceof PagedResultList - results.totalCount == 4 - results.size() == 2 - results.every { it.lastName == "Simpson" } - - when:"A detached criteria instance is created and the list method used with the max parameter" - criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - results = criteria.list(offset:2, max:4) - - then:"The results are a PagedResultList" - results instanceof PagedResultList - results.totalCount == 4 - results.size() == 2 - results.every { it.lastName == "Simpson" } - } - - void "Test list method with property projection"() { - given:"A bunch of people" - createPeople() - - when:"A detached criteria instance is created that uses a property projection" - def criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - criteria = criteria.property("firstName") - - def results = criteria.list(max: 2).sort() - then:"The list method returns the right results" - results.size() == 2 - results == ["Homer", "Marge"] - - when:"A detached criteria instance is created that uses a property projection using property missing" - criteria = new DetachedCriteria(Person) - criteria.with { - eq 'lastName', 'Simpson' - } - criteria = criteria.firstName - - results = criteria.list(max: 2).sort() - then:"The list method returns the right results" - results.size() == 2 - results == ["Homer", "Marge"] - - } -// -// void "Test exists method"() { -// given:"A bunch of people" -// createPeople() -// -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// then:"The count method returns the right results" -// criteria.exists() == true -// } -// void "Test updateAll method"() { -// given:"A bunch of people" -// createPeople() -// -// when:"A detached criteria is created that deletes all matching records" -// def criteria = new DetachedCriteria(Person).build { -// eq 'lastName', 'Simpson' -// } -// int total = criteria.updateAll(lastName:"Bloggs") -// -// -// then:"The number of deletions is correct" -// total == 4 -// Person.count() == 6 -// criteria.count() == 0 -// Person.countByLastName("Bloggs") == 4 -// } -// -// void "Test deleteAll method"() { -// given:"A bunch of people" -// createPeople() -// -// when:"A detached criteria is created that deletes all matching records" -// def criteria = new DetachedCriteria(Person).build { -// eq 'lastName', 'Simpson' -// } -// int total = criteria.deleteAll() -// -// -// then:"The number of deletions is correct" -// total == 4 -// Person.count() == 2 -// } -// -// void "Test iterate of detached criteria"() { -// given:"A bunch of people" -// createPeople() -// -// when:"A detached criteria is created that matches the last name and then iterated over" -// def criteria = new DetachedCriteria(Person).build { -// eq 'lastName', 'Simpson' -// } -// int total = 0 -// criteria.each { -// total++ -// } -// -// then:"The number of iterations is correct" -// total == 4 -// } -// void "Test dynamic finder on detached criteria"() { -// given:"A bunch of people" -// createPeople() -// -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// def result = criteria.findByFirstNameLike("B%") -// -// then:"The list method returns the right results" -// result != null -// result.firstName == "Bart" -// } -// -// void "Test get method on detached criteria and additional criteria"() { -// given:"A bunch of people" -// createPeople() -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// def result = criteria.get { -// like 'firstName', 'B%' -// } -// then:"The list method returns the right results" -// result != null -// result.firstName == "Bart" -// } -// -// void "Test list method on detached criteria and additional criteria"() { -// given:"A bunch of people" -// createPeople() -// -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// def results = criteria.list { -// like 'firstName', 'B%' -// } -// then:"The list method returns the right results" -// results.size() == 1 -// results[0].firstName == "Bart" -// -// when:"The original detached criteria is queried" -// results = criteria.list() -// -// then:"The additional criteria didn't modify the original instance and the correct results are returned" -// results.size() == 4 -// results.every { it.lastName == 'Simpson'} -// } -// -// void "Test count method on detached criteria and additional criteria"() { -// given:"A bunch of people" -// createPeople() -// -// -// when:"A detached criteria instance is created matching the last name and count is called with additional criteria" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// def result = criteria.count { -// like 'firstName', 'B%' -// } -// then:"The count method returns the right results" -// result == 1 -// -// } -// -// void "Test count method on detached criteria"() { -// given:"A bunch of people" -// createPeople() -// -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// def result = criteria.count() -// then:"The count method returns the right results" -// result == 4 -// -// } -// void "Test list method on detached criteria"() { -// given:"A bunch of people" -// createPeople() -// -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.with { -// eq 'lastName', 'Simpson' -// } -// -// def results = criteria.list() -// then:"The list method returns the right results" -// results.size() == 4 -// results.every { it.lastName == 'Simpson'} -// } -// -// void "Test list method on detached criteria with pagination"() { -// given:"A bunch of people" -// createPeople() -// -// when:"A detached criteria instance is created matching the last name" -// def criteria = new DetachedCriteria(Person) -// criteria.build { -// eq 'lastName', 'Simpson' -// } -// -// def results = criteria.list(max: 2) -// then:"The list method returns the right results" -// results.size() == 2 -// results.every { it.lastName == 'Simpson'} -// } - - protected void createPeople() { - new Person(firstName: "Homer", lastName: "Simpson").save() - new Person(firstName: "Marge", lastName: "Simpson").save() - new Person(firstName: "Bart", lastName: "Simpson").save() - new Person(firstName: "Lisa", lastName: "Simpson").save() - new Person(firstName: "Barney", lastName: "Rubble").save() - new Person(firstName: "Fred", lastName: "Flinstone").save() - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/DisableAutotimeStampSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/DisableAutotimeStampSpec.groovy deleted file mode 100644 index e74136c3a..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/DisableAutotimeStampSpec.groovy +++ /dev/null @@ -1,55 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * @author Graeme Rocher - */ -class DisableAutotimeStampSpec extends GormDatastoreSpec{ - - - void "Test that when auto timestamping is disabled the dateCreated and lastUpdated properties are not set"() { - when:"An entity is persisted" - def r = new Record(name: "Test") - r.save(flush:true) - session.clear() - r = Record.get(r.id) - - then:"There are errors and dateCreated / lastUpdated were not set" - r.lastUpdated == null - r.dateCreated == null - - when:"The entity is saved successfully and updated" - def d = new Date().parse('yyyy/MM/dd', '1973/07/21') - r.lastUpdated = d - r.dateCreated = d - r.save(flush: true) - session.clear() - r = Record.get(r.id) - - then:"lastUpdated is not changed" - r != null - r.lastUpdated == d - r.dateCreated == d - } - @Override - List getDomainClasses() { - [Record] - } -} - -@Entity -class Record { - Long id - String name - Date dateCreated - Date lastUpdated - - static constraints = { - dateCreated nullable:true - lastUpdated nullable:true - } - static mapping = { - autoTimestamp false - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/DomainEventsSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/DomainEventsSpec.groovy deleted file mode 100644 index 6c853a49b..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/DomainEventsSpec.groovy +++ /dev/null @@ -1,375 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.DetachedCriteria -import spock.lang.Issue - -import org.grails.datastore.mapping.core.Session - -import spock.lang.Ignore - -/** - * @author graemerocher - */ -class DomainEventsSpec extends GormDatastoreSpec { - - def setup() { - PersonEvent.resetStore() - } - @Issue('GPMONGODB-262') - void "Test that returning false from beforeUpdate evicts the event"() { - when:"An entity is saved" - def p = new PersonEvent(name: "Fred") - p.save(flush: true) - session.clear() - p = PersonEvent.get(p.id) - then:"The person is saved" - p != null - - when:"The beforeUpdate event returns false" - p.name = "Bad" - p.save(flush: true) - session.clear() - - then:"The person is never updated" - PersonEvent.get(p.id).name == "Fred" - } - - @Issue('GPMONGODB-262') - void "Test that returning false from beforeInsert evicts the event"() { - when:"false is returned from a beforeInsert event" - def p = new PersonEvent(name: "Bad") - try { - p.save() - session.flush() - } catch (e) { - // ignore hibernate related flush errors - } - session.clear() - - then:"The person is never saved" - !PersonEvent.get(p.id) - } - - @Issue('GPMONGODB-262') - void "Test that returning false from beforeDelete evicts the event"() { - when:"a new person is saved" - def p = new PersonEvent(name: "DontDelete") - p.save(flush: true) - session.clear() - p = PersonEvent.get(p.id) - - - then:"The person exists" - p != null - - when:"The beforeDelete event returns false" - p.delete(flush: true) - session.clear() - - then:"The event was cancelled" - PersonEvent.get(p.id) - } - - void "Test modify property before save"() { - given: - session.datastore.mappingContext.addPersistentEntity(ModifyPerson) - def p = new ModifyPerson(name:"Bob").save(flush:true) - session.clear() - - when:"An object is queried by id" - p = ModifyPerson.get(p.id) - - then: "the correct object is returned" - p.name == "Fred" - - when:"An object is queried by the updated value" - p = ModifyPerson.findByName("Fred") - - then:"The correct person is returned" - p.name == "Fred" - } - - void "Test auto time stamping working"() { - - given: - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - sleep(2000) - - p.dateCreated == p.lastUpdated - - when: - p.name = "Wilma" - p.save(flush:true) - - then: - p.dateCreated.before(p.lastUpdated) - } - - void "Test delete events"() { - given: - def p = new PersonEvent() - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - 0 == PersonEvent.STORE.beforeDelete - 0 == PersonEvent.STORE.afterDelete - - when: - p.delete(flush:true) - - then: - 1 == PersonEvent.STORE.beforeDelete - 1 == PersonEvent.STORE.afterDelete - } - - void "Test multi-delete events"() { - given: - def freds = (1..3).collect { - new PersonEvent(name: "Fred$it").save(flush:true) - } - session.clear() - - when: - freds = PersonEvent.findAllByIdInList(freds*.id) - - then: - 3 == freds.size() - 0 == PersonEvent.STORE.beforeDelete - 0 == PersonEvent.STORE.afterDelete - - when: - new DetachedCriteria(PersonEvent).build { - 'in'('id', freds*.id) - }.deleteAll() - session.flush() - - then: - 0 == PersonEvent.count() - 0 == PersonEvent.list().size() - - // removed the below assertions because in the case of batch DML statements neither Hibernate nor JPA triggers delete events for individual entities -// 3 == PersonEvent.STORE.beforeDelete -// 3 == PersonEvent.STORE.afterDelete - } - - void "Test before update event"() { - given: - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - 0 == PersonEvent.STORE.beforeUpdate - 0 == PersonEvent.STORE.afterUpdate - - when: - p.name = "Bob" - p.save(flush:true) - session.clear() - p = PersonEvent.get(p.id) - - then: - "Bob" == p.name - 1 == PersonEvent.STORE.beforeUpdate - 1 == PersonEvent.STORE.afterUpdate - } - - void "Test insert events"() { - given: - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - 0 == PersonEvent.STORE.beforeUpdate - 1 == PersonEvent.STORE.beforeInsert - 0 == PersonEvent.STORE.afterUpdate - 1 == PersonEvent.STORE.afterInsert - - when: - p.name = "Bob" - p.save(flush:true) - session.clear() - p = PersonEvent.get(p.id) - - then: - "Bob" == p.name - 1 == PersonEvent.STORE.beforeUpdate - 1 == PersonEvent.STORE.beforeInsert - 1 == PersonEvent.STORE.afterUpdate - 1 == PersonEvent.STORE.afterInsert - } - - void "Test load events"() { - given: - def p = new PersonEvent() - - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - if (!'JpaSession'.equals(session.getClass().simpleName)) { - // JPA doesn't seem to support a pre-load event - 1 == PersonEvent.STORE.beforeLoad - } - 1 == PersonEvent.STORE.afterLoad - } - - void "Test multi-load events"() { - given: - def freds = (1..3).collect { - new PersonEvent(name: "Fred$it").save(flush:true) - } - session.clear() - - when: - freds = PersonEvent.findAllByIdInList(freds*.id) - for(f in freds) {} // just to trigger load - - then: - 3 == freds.size() - if (!'JpaSession'.equals(session.getClass().simpleName)) { - // JPA doesn't seem to support a pre-load event - 3 == PersonEvent.STORE.beforeLoad - } - 3 == PersonEvent.STORE.afterLoad - } - - @Ignore - void "Test bean autowiring"() { - given: - def personService = new Object() - session.datastore.applicationContext.beanFactory.registerSingleton 'personService', personService - - def p = new PersonEvent() - def saved = p - p.name = "Fred" - p.save(flush:true) - session.clear() - - when: - p = PersonEvent.get(p.id) - - then: - "Fred" == p.name - personService.is saved.personService // test Groovy constructor - if (!session.datastore.getClass().name.contains('Hibernate')) { - // autowiring is added to the real constructor by an AST, so can't test this for Hibernate - personService.is p.personService // test constructor called by the datastore - } - } - - - def cleanup() { - session.datastore.applicationContext.beanFactory.destroySingleton 'personService' - } -} - -class PersonEvent implements Serializable { - Long id - Long version - String name - Date dateCreated - Date lastUpdated - - def personService - - static STORE_INITIAL = [ - beforeDelete: 0, afterDelete: 0, - beforeUpdate: 0, afterUpdate: 0, - beforeInsert: 0, afterInsert: 0, - beforeLoad: 0, afterLoad: 0] - - static STORE = [:] + STORE_INITIAL - - static void resetStore() { - STORE = [:] + STORE_INITIAL - } - - def beforeDelete() { - if (name == "DontDelete") { - return false - } - STORE.beforeDelete++ - } - - void afterDelete() { - STORE.afterDelete++ - } - - def beforeUpdate() { - if (name == "Bad") { - return false - } - STORE.beforeUpdate++ - } - - void afterUpdate() { - STORE.afterUpdate++ - } - - def beforeInsert() { - if (name == "Bad") { - return false - } - STORE.beforeInsert++ - } - - void afterInsert() { - STORE.afterInsert++ - } - - void beforeLoad() { - STORE.beforeLoad++ - } - - void afterLoad() { - STORE.afterLoad++ - } -} - -class ModifyPerson implements Serializable { - Long id - Long version - - String name - - static mapping = { - name index:true - } - - def beforeInsert() { - name = "Fred" - } -} 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 deleted file mode 100644 index d3aedc969..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/EnumSpec.groovy +++ /dev/null @@ -1,179 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -import org.grails.datastore.mapping.core.Session -import spock.lang.Issue - -class EnumSpec extends GormDatastoreSpec { - - void "Test save()"() { - given: - - EnumThing t = new EnumThing(name: 'e1', en: TestEnum.V1) - - when: - t.save(failOnError: true, flush:true) - - then: - t != null - !t.hasErrors() - - when: - t = t.get(t.id) - - then: - t != null - 'e1' == t.name - TestEnum.V1 == t.en - } - - - @Issue('GPMONGODB-248') - void "Test findByInList()"() { - given: - - new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true) - - EnumThing instance1 - EnumThing instance2 - EnumThing instance3 - - when: - instance1 = EnumThing.findByEnInList([TestEnum.V1]) - instance2 = EnumThing.findByEnInList([TestEnum.V2]) - instance3 = EnumThing.findByEnInList([TestEnum.V3]) - - then: - instance1 != null - instance1.en == TestEnum.V1 - - instance2 != null - instance2.en == TestEnum.V2 - - instance3 == null - } - void "Test findBy()"() { - given: - - new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true) - - EnumThing instance1 - EnumThing instance2 - EnumThing instance3 - - when: - instance1 = EnumThing.findByEn(TestEnum.V1) - instance2 = EnumThing.findByEn(TestEnum.V2) - instance3 = EnumThing.findByEn(TestEnum.V3) - - then: - instance1 != null - instance1.en == TestEnum.V1 - - instance2 != null - instance2.en == TestEnum.V2 - - instance3 == null - } - - void "Test findBy() with clearing the session"() { - given: - - new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true, flush: true) - new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true, flush: true) - new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true, flush: true) - session.clear() - - EnumThing instance1 - EnumThing instance2 - EnumThing instance3 - - when: - instance1 = EnumThing.findByEn(TestEnum.V1) - instance2 = EnumThing.findByEn(TestEnum.V2) - instance3 = EnumThing.findByEn(TestEnum.V3) - - then: - instance1 != null - instance1.en == TestEnum.V1 - - instance2 != null - instance2.en == TestEnum.V2 - - instance3 == null - } - - void "Test findAllBy()"() { - given: - - new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true) - - def v1Instances - def v2Instances - def v3Instances - def v12Instances - - when: - v1Instances = EnumThing.findAllByEn(TestEnum.V1) - v2Instances = EnumThing.findAllByEn(TestEnum.V2) - v3Instances = EnumThing.findAllByEn(TestEnum.V3) - v12Instances = EnumThing.findAllByEnInList([TestEnum.V1, TestEnum.V2]) - - then: - v1Instances != null - v1Instances.size() == 2 - v1Instances.every { it.en == TestEnum.V1 } - - v2Instances != null - v2Instances.size() == 1 - v2Instances.every { it.en == TestEnum.V2 } - - v3Instances != null - v3Instances.isEmpty() - - v12Instances != null - v12Instances.size() == 3 - } - - void "Test countBy()"() { - given: - - new EnumThing(name: 'e1', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e2', en: TestEnum.V1).save(failOnError: true) - new EnumThing(name: 'e3', en: TestEnum.V2).save(failOnError: true) - - def v1Count - def v2Count - def v3Count - - when: - v1Count = EnumThing.countByEn(TestEnum.V1) - v2Count = EnumThing.countByEn(TestEnum.V2) - v3Count = EnumThing.countByEn(TestEnum.V3) - - then: - 2 == v1Count - 1 == v2Count - 0 == v3Count - } -} - -@Entity -class EnumThing { - Long id - Long version - String name - TestEnum en - - static mapping = { - name index: true - en index: true - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FindByExampleSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FindByExampleSpec.groovy deleted file mode 100644 index 6e9cc08cc..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FindByExampleSpec.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package grails.gorm.tests - -class FindByExampleSpec extends GormDatastoreSpec { - - def "Test findAll by example"() { - given: - new Plant(name:"Pineapple", goesInPatch:false).save() - new Plant(name:"Cabbage", goesInPatch:true).save() - new Plant(name:"Kiwi", goesInPatch:false).save(flush:true) - session.clear() - when: - def results = Plant.findAll(new Plant(goesInPatch:false)) - then: - results.size() == 2 - "Pineapple" in results*.name - "Kiwi" in results*.name - - when: - results = Plant.findAll(new Plant(name:"Cabbage",goesInPatch:false)) - - then: - results.size() == 0 - - when: - results = Plant.findAll(new Plant(name:"Cabbage",goesInPatch:true)) - - then: - results.size() == 1 - "Cabbage" in results*.name - } - - def "Test find by example"() { - given: - new Plant(name:"Pineapple", goesInPatch:false).save() - new Plant(name:"Cabbage", goesInPatch:true).save() - new Plant(name:"Kiwi", goesInPatch:false).save(flush:true) - session.clear() - - when: - Plant result = Plant.find(new Plant(name:"Cabbage",goesInPatch:false)) - - then: - result == null - - when: - result = Plant.find(new Plant(name:"Cabbage",goesInPatch:true)) - - then: - result != null - result.name == "Cabbage" - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FindByMethodSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FindByMethodSpec.groovy deleted file mode 100644 index 04e6763c6..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FindByMethodSpec.groovy +++ /dev/null @@ -1,455 +0,0 @@ -package grails.gorm.tests - -/** - * @author graemerocher - */ -class FindByMethodSpec extends GormDatastoreSpec { - - void 'Test Using AND Multiple Times In A Dynamic Finder'() { - given: - new Person(firstName: 'Jake', lastName: 'Brown', age: 11).save() - new Person(firstName: 'Zack', lastName: 'Brown', age: 14).save() - new Person(firstName: 'Jeff', lastName: 'Brown', age: 41).save() - new Person(firstName: 'Zack', lastName: 'Galifianakis', age: 41).save() - - when: - def people = Person.findAllByFirstNameAndLastNameAndAge('Jeff', 'Brown', 1) - - then: - 0 == people?.size() - - when: - people = Person.findAllByFirstNameAndLastNameAndAgeGreaterThan('Zack', 'Brown', 20) - - then: - 0 == people?.size() - - when: - people = Person.findAllByFirstNameAndLastNameAndAgeGreaterThan('Zack', 'Brown', 8) - - then: - 1 == people?.size() - 14 == people[0].age - - when: - def cnt = Person.countByFirstNameAndLastNameAndAge('Jake', 'Brown', 11) - - then: - 1 == cnt - - when: - cnt = Person.countByFirstNameAndLastNameAndAgeInList('Zack', 'Brown', [12, 13, 14, 15]) - - then: - 1 == cnt - } - - void 'Test Using OR Multiple Times In A Dynamic Finder'() { - given: - new Person(firstName: 'Jake', lastName: 'Brown', age: 11).save() - new Person(firstName: 'Zack', lastName: 'Brown', age: 14).save() - new Person(firstName: 'Jeff', lastName: 'Brown', age: 41).save() - new Person(firstName: 'Zack', lastName: 'Galifianakis', age: 41).save() - - when: - def people = Person.findAllByFirstNameOrLastNameOrAge('Zack', 'Tyler', 125) - - then: - 2 == people?.size() - - when: - people = Person.findAllByFirstNameOrLastNameOrAge('Zack', 'Brown', 125) - - then: - 4 == people?.size() - - when: - def cnt = Person.countByFirstNameOrLastNameOrAgeInList('Jeff', 'Wilson', [11, 41]) - - then: - 3 == cnt - } - - void testBooleanPropertyQuery() { - given: - new Highway(bypassed: true, name: 'Bypassed Highway').save() - new Highway(bypassed: true, name: 'Bypassed Highway').save() - new Highway(bypassed: false, name: 'Not Bypassed Highway').save() - new Highway(bypassed: false, name: 'Not Bypassed Highway').save() - - when: - def highways= Highway.findAllBypassedByName('Not Bypassed Highway') - - then: - 0 == highways.size() - - when: - highways = Highway.findAllNotBypassedByName('Not Bypassed Highway') - - then: - 2 == highways?.size() - 'Not Bypassed Highway' == highways[0].name - 'Not Bypassed Highway'== highways[1].name - - when: - highways = Highway.findAllBypassedByName('Bypassed Highway') - - then: - 2 == highways?.size() - 'Bypassed Highway'== highways[0].name - 'Bypassed Highway'== highways[1].name - - when: - highways = Highway.findAllNotBypassedByName('Bypassed Highway') - then: - 0 == highways?.size() - - when: - highways = Highway.findAllBypassed() - then: - 2 ==highways?.size() - 'Bypassed Highway'== highways[0].name - 'Bypassed Highway'==highways[1].name - - when: - highways = Highway.findAllNotBypassed() - then: - 2 == highways?.size() - 'Not Bypassed Highway' == highways[0].name - 'Not Bypassed Highway'== highways[1].name - - when: - def highway = Highway.findNotBypassed() - then: - 'Not Bypassed Highway' == highway?.name - - when: - highway = Highway.findBypassed() - then: - 'Bypassed Highway' == highway?.name - - when: - highway = Highway.findNotBypassedByName('Not Bypassed Highway') - then: - 'Not Bypassed Highway' == highway?.name - - when: - highway = Highway.findBypassedByName('Bypassed Highway') - then: - 'Bypassed Highway' == highway?.name - - when: - Book.newInstance(author: 'Jeff', title: 'Fly Fishing For Everyone', published: false).save() - Book.newInstance(author: 'Jeff', title: 'DGGv2', published: true).save() - Book.newInstance(author: 'Graeme', title: 'DGGv2', published: true).save() - Book.newInstance(author: 'Dierk', title: 'GINA', published: true).save() - - def book = Book.findPublishedByAuthor('Jeff') - then: - 'Jeff' == book.author - 'DGGv2'== book.title - - when: - book = Book.findPublishedByAuthor('Graeme') - then: - 'Graeme' == book.author - 'DGGv2'== book.title - - when: - book = Book.findPublishedByTitleAndAuthor('DGGv2', 'Jeff') - then: - 'Jeff'== book.author - 'DGGv2'== book.title - - when: - book = Book.findNotPublishedByAuthor('Jeff') - then: - 'Fly Fishing For Everyone'== book.title - - when: - book = Book.findPublishedByTitleOrAuthor('Fly Fishing For Everyone', 'Dierk') - then: - 'GINA'== book.title - Book.findPublished() != null - - when: - book = Book.findNotPublished() - then: - 'Fly Fishing For Everyone' == book?.title - - when: - def books = Book.findAllPublishedByTitle('DGGv2') - then: - 2 == books?.size() - - when: - books = Book.findAllPublished() - then: - 3 == books?.size() - - when: - books = Book.findAllNotPublished() - then: - 1 == books?.size() - - when: - books = Book.findAllPublishedByTitleAndAuthor('DGGv2', 'Graeme') - then: - 1 == books?.size() - - when: - books = Book.findAllPublishedByAuthorOrTitle('Graeme', 'GINA') - then: - 2 == books?.size() - - when: - books = Book.findAllNotPublishedByAuthor('Jeff') - then: - 1 == books?.size() - - when: - books = Book.findAllNotPublishedByAuthor('Graeme') - then: - 0 == books?.size() - } - - void "Test findOrCreateBy For A Record That Does Not Exist In The Database"() { - when: - def book = Book.findOrCreateByAuthor('Someone') - - then: - 'Someone' == book.author - null == book.title - null == book.id - } - - void "Test findOrCreateBy With An AND Clause"() { - when: - def book = Book.findOrCreateByAuthorAndTitle('Someone', 'Something') - - then: - 'Someone' == book.author - 'Something' == book.title - null == book.id - } - - void "Test findOrCreateBy Throws Exception If An OR Clause Is Used"() { - when: - Book.findOrCreateByAuthorOrTitle('Someone', 'Something') - - then: - thrown(MissingMethodException) - } - - void "Test findOrSaveBy For A Record That Does Not Exist In The Database"() { - when: - def book = Book.findOrSaveByAuthorAndTitle('Some New Author', 'Some New Title') - - then: - 'Some New Author' == book.author - 'Some New Title' == book.title - book.id != null - } - - void "Test findOrSaveBy For A Record That Does Exist In The Database"() { - - given: - def originalId = new Book(author: 'Some Author', title: 'Some Title').save().id - - when: - def book = Book.findOrSaveByAuthor('Some Author') - - then: - 'Some Author' == book.author - 'Some Title' == book.title - originalId == book.id - } - - void "Test patterns which shold throw MissingMethodException"() { - // Redis doesn't like Like queries... -// when: -// Book.findOrCreateByAuthorLike('B%') -// -// then: -// thrown MissingMethodException - - when: - Book.findOrCreateByAuthorInList(['Jeff']) - - then: - thrown MissingMethodException - - when: - Book.findOrCreateByAuthorOrTitle('Jim', 'Title') - - then: - thrown MissingMethodException - - when: - Book.findOrCreateByAuthorNotEqual('B') - - then: - thrown MissingMethodException - - when: - Book.findOrCreateByAuthorGreaterThan('B') - - then: - thrown MissingMethodException - - when: - Book.findOrCreateByAuthorLessThan('B') - - then: - thrown MissingMethodException - - when: - Book.findOrCreateByAuthorBetween('A', 'B') - - then: - thrown MissingMethodException - - when: - Book.findOrCreateByAuthorGreaterThanEquals('B') - - then: - thrown MissingMethodException - - when: - Book.findOrCreateByAuthorLessThanEquals('B') - - then: - thrown MissingMethodException - - // GemFire doesn't like these... -// when: -// Book.findOrCreateByAuthorIlike('B%') -// -// then: -// thrown MissingMethodException - -// when: -// Book.findOrCreateByAuthorRlike('B%') -// -// then: -// thrown MissingMethodException - -// when: -// Book.findOrCreateByAuthorIsNull() -// -// then: -// thrown MissingMethodException - -// when: -// Book.findOrCreateByAuthorIsNotNull() -// -// then: -// thrown MissingMethodException - - // Redis doesn't like Like queries... -// when: -// Book.findOrSaveByAuthorLike('B%') -// -// then: -// thrown MissingMethodException - - when: - Book.findOrSaveByAuthorInList(['Jeff']) - - then: - thrown MissingMethodException - - when: - Book.findOrSaveByAuthorOrTitle('Jim', 'Title') - - then: - thrown MissingMethodException - - when: - Book.findOrSaveByAuthorNotEqual('B') - - then: - thrown MissingMethodException - - when: - Book.findOrSaveByAuthorGreaterThan('B') - - then: - thrown MissingMethodException - - when: - Book.findOrSaveByAuthorLessThan('B') - - then: - thrown MissingMethodException - - when: - Book.findOrSaveByAuthorBetween('A', 'B') - - then: - thrown MissingMethodException - - when: - Book.findOrSaveByAuthorGreaterThanEquals('B') - - then: - thrown MissingMethodException - - when: - Book.findOrSaveByAuthorLessThanEquals('B') - - then: - thrown MissingMethodException - - // GemFire doesn't like these... -// when: -// Book.findOrSaveByAuthorIlike('B%') -// -// then: -// thrown MissingMethodException - -// when: -// Book.findOrSaveByAuthorRlike('B%') -// -// then: -// thrown MissingMethodException - -// when: -// Book.findOrSaveByAuthorIsNull() -// -// then: -// thrown MissingMethodException - -// when: -// Book.findOrSaveByAuthorIsNotNull() -// -// then: -// thrown MissingMethodException - } -} - -class Highway implements Serializable { - Long id - Long version - Boolean bypassed - String name - - static mapping = { - bypassed index:true - name index:true - } -} - -class Book implements Serializable { - Long id - Long version - String author - String title - Boolean published = false - - static mapping = { - published index:true - title index:true - author index:true - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FindOrCreateWhereSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FindOrCreateWhereSpec.groovy deleted file mode 100644 index d5ce6fc21..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FindOrCreateWhereSpec.groovy +++ /dev/null @@ -1,28 +0,0 @@ -package grails.gorm.tests - -class FindOrCreateWhereSpec extends GormDatastoreSpec { - - def "Test findOrCreateWhere returns a new instance if it doesn't exist in the database"() { - when: - def entity = TestEntity.findOrCreateWhere(name: 'Fripp', age: 64) - - then: - 'Fripp' == entity.name - 64 == entity.age - null == entity.id - } - - def "Test findOrCreateWhere returns a persistent instance if it exists in the database"() { - given: - def entityId = new TestEntity(name: 'Belew', age: 61).save().id - - when: - def entity = TestEntity.findOrCreateWhere(name: 'Belew', age: 61) - - then: - entity.id != null - entityId == entity.id - 'Belew' == entity.name - 61 == entity.age - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FindOrSaveWhereSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FindOrSaveWhereSpec.groovy deleted file mode 100644 index c9674a95b..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FindOrSaveWhereSpec.groovy +++ /dev/null @@ -1,28 +0,0 @@ -package grails.gorm.tests - -class FindOrSaveWhereSpec extends GormDatastoreSpec { - - def "Test findOrSaveWhere returns a new instance if it doesn't exist in the database"() { - when: - def entity = TestEntity.findOrSaveWhere(name: 'Lake', age: 63) - - then: - 'Lake' == entity.name - 63 == entity.age - null != entity.id - } - - def "Test findOrSaveWhere returns a persistent instance if it exists in the database"() { - given: - def entityId = new TestEntity(name: 'Levin', age: 64).save().id - - when: - def entity = TestEntity.findOrSaveWhere(name: 'Levin', age: 64) - - then: - entity.id != null - entityId == entity.id - 'Levin' == entity.name - 64 == entity.age - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FirstAndLastMethodSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FirstAndLastMethodSpec.groovy deleted file mode 100644 index 5c7b04449..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/FirstAndLastMethodSpec.groovy +++ /dev/null @@ -1,243 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -import spock.lang.Ignore - -@Ignore -class FirstAndLastMethodSpec extends GormDatastoreSpec { - - void "Test first and last method with empty datastore"() { - given: - assert SimpleWidget.count() == 0 - - when: - def result = SimpleWidget.first() - - then: - result == null - - when: - result = SimpleWidget.last() - - then: - result == null - } - - void "Test first and last method with multiple entities in the datastore"() { - given: - assert new SimpleWidget(name: 'one', spanishName: 'uno').save() - assert new SimpleWidget(name: 'two', spanishName: 'dos').save() - assert new SimpleWidget(name: 'three', spanishName: 'tres').save() - assert SimpleWidget.count() == 3 - - when: - def result = SimpleWidget.first() - - then: - result?.name == 'one' - - when: - result = SimpleWidget.last() - - then: - result?.name == 'three' - } - - void "Test first and last method with one entity"() { - given: - assert new SimpleWidget(name: 'one', spanishName: 'uno').save() - assert SimpleWidget.count() == 1 - - when: - def result = SimpleWidget.first() - - then: - result?.name == 'one' - - when: - result = SimpleWidget.last() - - then: - result?.name == 'one' - } - - void "Test first and last method with sort parameter"() { - given: - assert new SimpleWidget(name: 'one', spanishName: 'uno').save() - assert new SimpleWidget(name: 'two', spanishName: 'dos').save() - assert new SimpleWidget(name: 'three', spanishName: 'tres').save() - assert SimpleWidget.count() == 3 - - when: - def result = SimpleWidget.first(sort: 'name') - - then: - result?.name == 'one' - - when: - result = SimpleWidget.last(sort: 'name') - - then: - result?.name == 'two' - - when: - result = SimpleWidget.first('name') - - then: - result?.name == 'one' - - when: - result = SimpleWidget.last('name') - - then: - result?.name == 'two' - - when: - result = SimpleWidget.first(sort: 'spanishName') - - then: - result?.spanishName == 'dos' - - when: - result = SimpleWidget.last(sort: 'spanishName') - - then: - result?.spanishName == 'uno' - - when: - result = SimpleWidget.first('spanishName') - - then: - result?.spanishName == 'dos' - - when: - result = SimpleWidget.last('spanishName') - - then: - result?.spanishName == 'uno' - } - - void "Test first and last method with non standard identifier"() { - given: - ['one', 'two', 'three'].each { name -> - assert new SimpleWidgetWithNonStandardId(name: name).save() - } - assert SimpleWidgetWithNonStandardId.count() == 3 - - when: - def result = SimpleWidgetWithNonStandardId.first() - - then: - result?.name == 'one' - - when: - result = SimpleWidgetWithNonStandardId.last() - - then: - result?.name == 'three' - } - - void "Test first and last method with composite key"() { - given: - assert new PersonWithCompositeKey(firstName: 'Steve', lastName: 'Harris', age: 56).save() - assert new PersonWithCompositeKey(firstName: 'Dave', lastName: 'Murray', age: 54).save() - assert new PersonWithCompositeKey(firstName: 'Adrian', lastName: 'Smith', age: 55).save() - assert new PersonWithCompositeKey(firstName: 'Bruce', lastName: 'Dickinson', age: 53).save() - assert PersonWithCompositeKey.count() == 4 - - when: - def result = PersonWithCompositeKey.first() - - then: - result?.firstName == 'Steve' - - when: - result = PersonWithCompositeKey.last() - - then: - result?.firstName == 'Bruce' - - when: - result = PersonWithCompositeKey.first('firstName') - - then: - result?.firstName == 'Adrian' - - when: - result = PersonWithCompositeKey.last('firstName') - - then: - result?.firstName == 'Steve' - - when: - result = PersonWithCompositeKey.first(sort: 'firstName') - - then: - result?.firstName == 'Adrian' - - when: - result = PersonWithCompositeKey.last(sort: 'firstName') - - then: - result?.firstName == 'Steve' - - when: - result = PersonWithCompositeKey.first('age') - - then: - result?.firstName == 'Bruce' - - when: - result = PersonWithCompositeKey.last('age') - - then: - result?.firstName == 'Steve' - - when: - result = PersonWithCompositeKey.first(sort: 'age') - - then: - result?.firstName == 'Bruce' - - when: - result = PersonWithCompositeKey.last(sort: 'age') - - then: - result?.firstName == 'Steve' - } - - @Override - List getDomainClasses() { - [SimpleWidget, PersonWithCompositeKey, SimpleWidgetWithNonStandardId] - } -} - -@Entity -class SimpleWidget implements Serializable { - Long id - Long version - String name - String spanishName -} - -@Entity -class SimpleWidgetWithNonStandardId implements Serializable { - Long myIdentifier - Long version - String name - static mapping = { - id name: 'myIdentifier' - } -} - -@Entity -class PersonWithCompositeKey implements Serializable { - Long version - String firstName - String lastName - Integer age - static mapping = { - id composite: ['lastName', 'firstName'] - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/GormDatastoreSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/GormDatastoreSpec.groovy deleted file mode 100644 index 0098e6c24..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/GormDatastoreSpec.groovy +++ /dev/null @@ -1,76 +0,0 @@ -package grails.gorm.tests - -import org.grails.datastore.mapping.core.DatastoreUtils -import org.grails.datastore.mapping.core.Session - -import spock.lang.Shared -import spock.lang.Specification - -/** - * A Spec base class that manages a Session for each feature as well as - * meta class cleanup on the Entity classes in the TCK. - * - * Users of this class need to provide a "setup" class at runtime that - * provides the session instance. It *must* have the following name: - * - * - org.grails.datastore.gorm.Setup - * - * This class must contain a static no-arg method called "setup()" - * that returns a Session instance. - */ -abstract class GormDatastoreSpec extends Specification { - - static final SETUP_CLASS_NAME = 'org.grails.datastore.gorm.Setup' - static final TEST_CLASSES = [ - Book, ChildEntity, City, ClassWithListArgBeforeValidate, ClassWithNoArgBeforeValidate, - ClassWithOverloadedBeforeValidate, CommonTypes, Country, EnumThing, Face, Highway, - Location, ModifyPerson, Nose, OptLockNotVersioned, OptLockVersioned, Person, PersonEvent, - Pet, PetType, Plant, PlantCategory, Publication, Task, TestEntity] - - @Shared Class setupClass - - Session session - - def setupSpec() { - ExpandoMetaClass.enableGlobally() - setupClass = loadSetupClass() - } - - def setup() { - cleanRegistry() - session = setupClass.setup(((TEST_CLASSES + getDomainClasses()) as Set) as List) - DatastoreUtils.bindSession session - } - - List getDomainClasses() { - [] - } - - def cleanup() { - if (session) { - session.disconnect() - DatastoreUtils.unbindSession session - } - try { - setupClass.destroy() - } catch(e) { - println "ERROR: Exception during test cleanup: ${e.message}" - } - - cleanRegistry() - } - - private cleanRegistry() { - for (clazz in (TEST_CLASSES + getDomainClasses() )) { - GroovySystem.metaClassRegistry.removeMetaClass(clazz) - } - } - - static private loadSetupClass() { - try { - getClassLoader().loadClass(SETUP_CLASS_NAME) - } catch (Throwable e) { - throw new RuntimeException("Datastore setup class ($SETUP_CLASS_NAME) was not found",e) - } - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/GormEnhancerSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/GormEnhancerSpec.groovy deleted file mode 100644 index 1e32a070b..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/GormEnhancerSpec.groovy +++ /dev/null @@ -1,233 +0,0 @@ -package grails.gorm.tests - -import spock.lang.Ignore - -/** - * @author graemerocher - */ -class GormEnhancerSpec extends GormDatastoreSpec { - - void "Test basic CRUD operations"() { - given: - def t - - when: - t = TestEntity.get(1) - - then: - t == null - - when: - t = new TestEntity(name:"Bob", child:new ChildEntity(name:"Child")) - t.save() - - then: - t.id != null - - when: - def results = TestEntity.list() - - then: - 1 == results.size() - "Bob" == results[0].name - - when: - t = TestEntity.get(t.id) - - then: - t != null - "Bob" == t.name - } - - void "Test simple dynamic finder"() { - - given: - def t = new TestEntity(name:"Bob", child:new ChildEntity(name:"Child")) - t.save() - - t = new TestEntity(name:"Fred", child:new ChildEntity(name:"Child")) - t.save() - - when: - def results = TestEntity.list() - def bob = TestEntity.findByName("Bob") - - then: - 2 == results.size() - bob != null - "Bob" == bob.name - } - - void "Test dynamic finder with disjunction"() { - given: - def age = 40 - ["Bob", "Fred", "Barney"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - when: - def results = TestEntity.findAllByNameOrAge("Barney", 40) - def barney = results.find { it.name == "Barney" } - def bob = results.find { it.age == 40 } - - then: - 3 == TestEntity.count() - 2 == results.size() - barney != null - 42 == barney.age - bob != null - "Bob" == bob.name - } - - void "Test getAll() method"() { - given: - def age = 40 - def ids = [] - ["Bob", "Fred", "Barney"].each { - ids.add(new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save().id) - } - - when: - def results = TestEntity.getAll(ids[0],ids[1]) - - then: - 2 == results.size() - } - - void "Test ident() method"() { - given: - def t - - when: - t = new TestEntity(name:"Bob", child:new ChildEntity(name:"Child")) - t.save() - - then: - t.id != null - t.id == t.ident() - } - - void "Test dynamic finder with pagination parameters"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - when: - def total = TestEntity.count() - - then: - 4 == total - - 2 == TestEntity.findAllByNameOrAge("Barney", 40).size() - 1 == TestEntity.findAllByNameOrAge("Barney", 40, [max:1]).size() - } - - void "Test in list query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - when: - def total = TestEntity.count() - - then: - 4 == total - 2 == TestEntity.findAllByNameInList(["Fred", "Frank"]).size() - 1 == TestEntity.findAllByNameInList(["Joe", "Frank"]).size() - 0 == TestEntity.findAllByNameInList(["Jeff", "Jack"]).size() - 2 == TestEntity.findAllByNameInListOrName(["Joe", "Frank"], "Bob").size() - } - - void "Test like query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank", "frita"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - when: - def results = TestEntity.findAllByNameLike("Fr%") - - then: - 2 == results.size() - results.find { it.name == "Fred" } != null - results.find { it.name == "Frank" } != null - } - - @Ignore - void "Test ilike query"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank", "frita"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - when: - def results = TestEntity.findAllByNameIlike("fr%") - - then: - 3 == results.size() - results.find { it.name == "Fred" } != null - results.find { it.name == "Frank" } != null - results.find { it.name == "frita" } != null - } - - void "Test count by query"() { - - given: - def age = 40 - ["Bob", "Fred", "Barney"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - when: - def total = TestEntity.count() - - then: - 3 == total - 3 == TestEntity.list().size() - 2 == TestEntity.countByNameOrAge("Barney", 40) - 1 == TestEntity.countByNameAndAge("Bob", 40) - } - - void "Test dynamic finder with conjunction"() { - given: - def age = 40 - ["Bob", "Fred", "Barney"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - when: - def total = TestEntity.count() - - then: - 3 == total - 3 == TestEntity.list().size() - - TestEntity.findByNameAndAge("Bob", 40) - !TestEntity.findByNameAndAge("Bob", 41) - } - - void "Test count() method"() { - given: - def t - - when: - t= new TestEntity(name:"Bob", child:new ChildEntity(name:"Child")) - t.save() - - then: - 1 == TestEntity.count() - - when: - t = new TestEntity(name:"Fred", child:new ChildEntity(name:"Child")) - t.save() - - then: - 2 == TestEntity.count() - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/GroovyProxySpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/GroovyProxySpec.groovy deleted file mode 100644 index 2953b7c68..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/GroovyProxySpec.groovy +++ /dev/null @@ -1,55 +0,0 @@ -package grails.gorm.tests - -import org.grails.datastore.gorm.proxy.GroovyProxyFactory -import org.springframework.dao.DataIntegrityViolationException - -/** - * @author graemerocher - */ -class GroovyProxySpec extends GormDatastoreSpec { - - void "Test proxying of non-existent instance throws an exception"() { - given:"A groovy proxy factory" - session.mappingContext.proxyFactory = new GroovyProxyFactory() - - when:"A proxy is loaded for an instance that doesn't exist" - def location = Location.proxy(123) - - then:"The proxy is in a valid state" - - location != null - 123 == location.id - false == location.isInitialized() - false == location.initialized - - when:"The proxy is loaded" - location.code - - then:"An exception is thrown" - thrown DataIntegrityViolationException - } - - void "Test creation and behavior of Groovy proxies"() { - - given: - session.mappingContext.proxyFactory = new GroovyProxyFactory() - def id = new Location(name:"United Kingdom", code:"UK").save(flush:true)?.id - session.clear() - - when: - def location = Location.proxy(id) - - then: - - location != null - id == location.id - false == location.isInitialized() - false == location.initialized - - "UK" == location.code - "United Kingdom - UK" == location.namedAndCode() - true == location.isInitialized() - true == location.initialized - null != location.target - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/InheritanceSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/InheritanceSpec.groovy deleted file mode 100644 index 1f093770e..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/InheritanceSpec.groovy +++ /dev/null @@ -1,104 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * @author graemerocher - */ -class InheritanceSpec extends GormDatastoreSpec { - - void "Test inheritance with dynamic finder"() { - - given: - def city = new City([code: "UK", name: "London", longitude: 49.1, latitude: 53.1]) - def country = new Country([code: "UK", name: "United Kingdom", population: 10000000]) - - city.save() - country.save(flush:true) - session.clear() - - when: - def locations = Location.findAllByCode("UK") - def cities = City.findAllByCode("UK") - def countries = Country.findAllByCode("UK") - - then: - 2 == locations.size() - 1 == cities.size() - 1 == countries.size() - "London" == cities[0].name - "United Kingdom" == countries[0].name - } - - void "Test querying with inheritance"() { - - given: - def city = new City([code: "LON", name: "London", longitude: 49.1, latitude: 53.1]) - def location = new Location([code: "XX", name: "The World"]) - def country = new Country([code: "UK", name: "United Kingdom", population: 10000000]) - - country.save() - city.save() - location.save() - - session.flush() - - when: - city = City.get(city.id) - def london = Location.get(city.id) - country = Location.findByName("United Kingdom") - def london2 = Location.findByName("London") - - then: - 1 == City.count() - 1 == Country.count() - 3 == Location.count() - - city != null - city instanceof City - london instanceof City - london2 instanceof City - "London" == london2.name - 49.1 == london2.longitude - "LON" == london2.code - - country instanceof Country - "UK" == country.code - 10000000 == country.population - } - - def clearSession() { - City.withSession { session -> session.flush() } - } -} - -@Entity -class Location implements Serializable { - Long id - Long version - String name - String code = "DEFAULT" - - def namedAndCode() { - "$name - $code" - } - - static mapping = { - name index:true - code index:true - } -} - -@Entity -class City extends Location { - BigDecimal latitude - BigDecimal longitude -} - -@Entity -class Country extends Location { - Integer population - - static hasMany = [residents:Person] - Set residents -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ListOrderBySpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ListOrderBySpec.groovy deleted file mode 100644 index 6f5a4ec95..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ListOrderBySpec.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package grails.gorm.tests - -/** - * @author graemerocher - */ -class ListOrderBySpec extends GormDatastoreSpec { - - void "Test listOrderBy property name method"() { - given: - def child = new ChildEntity(name: "Child") - new TestEntity(age:30, name:"Bob", child:child).save() - new TestEntity(age:55, name:"Fred", child:child).save() - new TestEntity(age:17, name:"Jack", child:child).save() - - when: - def results = TestEntity.listOrderByAge() - - then: - results.size() == 3 - results[0].name == "Jack" - results[1].name == "Bob" - results[2].name == "Fred" - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/NamedQuerySpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/NamedQuerySpec.groovy deleted file mode 100644 index cb4231b86..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/NamedQuerySpec.groovy +++ /dev/null @@ -1,1133 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -import spock.lang.Ignore - -/** - * @author graemerocher - */ -class NamedQuerySpec extends GormDatastoreSpec { - - void "Test named query with disjunction"() { - given: - def now = new Date() - def oldDate = now - 2000 - - Publication.newInstance(title: 'New Paperback', datePublished: now, paperback: true).save(failOnError: true) - Publication.newInstance(title: 'Old Paperback', datePublished: oldDate, paperback: true).save(failOnError: true) - Publication.newInstance(title: 'New Hardback', datePublished: now, paperback: false).save(failOnError: true) - Publication.newInstance(title: 'Old Hardback', datePublished: oldDate, paperback: false).save(failOnError: true) - session.flush() - session.clear() - - when: - def publications = Publication.paperbackOrRecent.list() - - then: - 3 == publications?.size() - } - - void "Test max and offset parameter"() { - given: - (1..25).each {num -> - Publication.newInstance(title: "Book Number ${num}", - datePublished: new Date()).save() - } - - when: - def pubs = Publication.recentPublications.list(max: 10, offset: 5) - - then: - 10 == pubs?.size() - - when: - pubs = Publication.recentPublications.list(max: '10', offset: '5') - - then: - 10 == pubs?.size() - } - - void "Test that parameter to get is converted"() { - - given: - def now = new Date() - def newPublication = Publication.newInstance(title: "Some New Book", datePublished: now - 10).save(failOnError: true) - def oldPublication = Publication.newInstance(title: "Some Old Book", - datePublished: now - 900).save(flush:true, failOnError: true) - session.clear() - - when: - def publication = Publication.recentPublications.get(newPublication.id.toString()) - - then: - publication != null - 'Some New Book'== publication.title - } - - void "Test named query with additional criteria closure"() { - - given: - def now = new Date() - 6.times { - Publication.newInstance(title: "Some Book", - datePublished: now - 10).save(failOnError: true) - Publication.newInstance(title: "Some Other Book", - datePublished: now - 10).save(failOnError: true) - Publication.newInstance(title: "Some Book", - datePublished: now - 900).save(failOnError: true) - } - session.flush() - session.clear() - - when: - def publications = Publication.recentPublications { - eq 'title', 'Some Book' - } - - then: - 6 == publications?.size() - - when: - publications = Publication.recentPublications { - like 'title', 'Some%' - } - - then: - 12 == publications?.size() - - when: - def cnt = Publication.recentPublications.count { - eq 'title', 'Some Book' - } - - then: - 6 == cnt - - when: - publications = Publication.recentPublications(max: 3) { - like 'title', 'Some%' - } - - then: - 3 == publications?.size() - } - - void "Test passing parameters to additional criteria"() { - given: - def now = new Date() - - 6.times { cnt -> - new Publication(title: "Some Old Book #${cnt}", - datePublished: now - 1000, paperback: true).save(failOnError: true).id - new Publication(title: "Some New Book #${cnt}", - datePublished: now, paperback: true).save(failOnError: true).id - } - - session?.flush() - - when: - def results = Publication.publishedAfter(now - 5) { - eq 'paperback', true - } - - then: - 6 == results?.size() - - when: - results = Publication.publishedAfter(now - 5, [max: 2, offset: 1]) { - eq 'paperback', true - } - - then: - 2 == results?.size() - - when: - results = Publication.publishedBetween(now - 5, now + 1) { - eq 'paperback', true - } - - then: - 6 == results?.size() - - when: - results = Publication.publishedBetween(now - 5, now + 1, [max: 2, offset: 1]) { - eq 'paperback', true - } - - then: - 2 == results?.size() - - when: - results = Publication.publishedAfter(now - 1005) { - eq 'paperback', true - } - - then: - 12 == results?.size() - - when: - results = Publication.publishedAfter(now - 5) { - eq 'paperback', false - } - - then: - 0 == results?.size() - - when: - results = Publication.publishedAfter(now - 5, [max: 2, offset: 1]) { - eq 'paperback', false - } - - then: - 0 == results?.size() - - when: - results = Publication.publishedBetween(now - 5, now + 1) { - eq 'paperback', false - } - - then: - 0 == results?.size() - - when: - results = Publication.publishedBetween(now - 5, now + 1, [max: 2, offset: 1]) { - eq 'paperback', false - } - - then: - 0 == results?.size() - - when: - results = Publication.publishedAfter(now - 1005) { - eq 'paperback', false - } - - then: - 0 == results?.size() - } - - void "Test get method followed named query chaining"() { - given: - def now = new Date() - - def oldPaperBackWithBookInTitleId = new Publication( - title: "Book 1", - datePublished: now - 1000, paperback: true).save().id - def newPaperBackWithBookInTitleId = new Publication( - title: "Book 2", - datePublished: now, paperback: true).save().id - - session.flush() - session.clear() - - when: - def publication = Publication.publicationsWithBookInTitle().publishedAfter(now - 5).get(oldPaperBackWithBookInTitleId) - - then: - publication == null - - when: - publication = Publication.publishedAfter(now - 5).publicationsWithBookInTitle().get(oldPaperBackWithBookInTitleId) - - then: - publication == null - - when: - publication = Publication.publishedAfter(now - 5).publicationsWithBookInTitle().get(newPaperBackWithBookInTitleId) - - then: - publication != null - - when: - publication = Publication.publishedAfter(now - 5).publicationsWithBookInTitle().get(newPaperBackWithBookInTitleId) - - then: - publication != null - } - - void "Test named query with findBy*() dynamic finder"() { - - given: - def now = new Date() - Publication.newInstance(title: "Book 1", datePublished: now - 900).save(failOnError: true) - def recentBookId = Publication.newInstance( - title: "Book 1", - datePublished: now - 10).save(flush:true).id - session.clear() - - when: - def publication = Publication.recentPublications.findByTitle('Book 1') - - then: - publication != null - recentBookId == publication.id - } - - void "Test named query with findAllBy*() dyamic finder"() { - given: - def now = new Date() - 3.times { - new Publication(title: "Some Recent Book", - datePublished: now - 10).save(failOnError: true) - new Publication(title: "Some Other Book", - datePublished: now - 10).save(failOnError: true) - new Publication(title: "Some Book", - datePublished: now - 900).save(flush:true, failOnError: true) - } - session.clear() - - when: - def publications = Publication.recentPublications.findAllByTitle('Some Recent Book') - - then: - 3 == publications?.size() - 'Some Recent Book' == publications[0].title - 'Some Recent Book' == publications[1].title - 'Some Recent Book' == publications[2].title - } - - @Ignore // queries on associations not yet supported - void "Test named query with relationships in criteria"() { - - given: - - new PlantCategory(name:"leafy") - .addToPlants(goesInPatch:true, name:"Lettuce") - .save(flush:true) - - new PlantCategory(name:"groovy") - .addToPlants(goesInPatch: true, name: 'Gplant') - .save(flush:true) - - new PlantCategory(name:"grapes") - .addToPlants(goesInPatch:false, name:"Gray") - .save(flush:true) - - session.clear() - - when: - def results = PlantCategory.withPlantsInPatch.list() - - then: - 2 == results.size() - true == 'leafy' in results*.name - true == 'groovy' in results*.name - - when: - results = PlantCategory.withPlantsThatStartWithG.list() - - then: - 2 == results.size() - true == 'groovy' in results*.name - true == 'grapes' in results*.name - - when: - results = PlantCategory.withPlantsInPatchThatStartWithG.list() - - then: - 1 == results.size() - 'groovy' == results[0].name - } - - @Ignore // queries on associations not yet supported - void "Test list distinct entities"() { - - given: - new PlantCategory(name:"leafy") - .addToPlants(goesInPatch:true, name:"lettuce") - .addToPlants(goesInPatch:true, name:"cabbage") - .save(flush:true) - - new PlantCategory(name:"orange") - .addToPlants(goesInPatch:true, name:"carrots") - .addToPlants(goesInPatch:true, name:"pumpkin") - .save(flush:true) - - new PlantCategory(name:"grapes") - .addToPlants(goesInPatch:false, name:"red") - .addToPlants(goesInPatch:false, name:"white") - .save(flush:true) - - session.clear() - - when: - def categories = plantCategoryClass.withPlantsInPatch().listDistinct() - def names = categories*.name - - then: - 2 == categories.size() - 2 == names.size() - true == 'leafy' in names - true == 'orange' in names - } - - @Ignore // queries on associations not yet supported - void "Another test on listing distinct entities"() { - given: - new PlantCategory(name:"leafy") - .addToPlants(goesInPatch:true, name:"lettuce") - .addToPlants(goesInPatch:true, name:"cabbage") - .save(flush:true) - - new PlantCategory(name:"orange") - .addToPlants(goesInPatch:true, name:"carrots") - .addToPlants(goesInPatch:true, name:"pumpkin") - .save(flush:true) - - new PlantCategory(name:"grapes") - .addToPlants(goesInPatch:false, name:"red") - .addToPlants(goesInPatch:false, name:"white") - .save(flush:true) - - session.clear() - - when: - def categories = plantCategoryClass.withPlantsInPatch.listDistinct() - def names = categories*.name - - then: - 3 == categories.size() - 3 == names.size() - true == 'leafy' in names - true == 'orange' in names - true == 'grapes' in names - } - - void 'Test uniqueResult'() { - given: - def now = new Date() - - new Publication(title: "Ten Day Old Paperback", - datePublished: now - 10, - paperback: true).save(flush: true) - new Publication(title: "One Hundred Day Old Paperback", - datePublished: now - 100, - paperback: true).save(flush: true) - session.clear() - - when: - def result = Publication.lastPublishedBefore(now - 200).list() - - then: - !result - - when: - result = Publication.lastPublishedBefore(now - 50).list() - - then: - 'One Hundred Day Old Paperback' == result?.title - } - - void "Test findWhere method after chaining named queries"() { - given: - def now = new Date() - - new Publication(title: "Book 1", - datePublished: now - 10, paperback: false).save() - new Publication(title: "Book 2", - datePublished: now - 1000, paperback: true).save() - new Publication(title: "Book 3", - datePublished: now - 10, paperback: true).save() - - new Publication(title: "Some Title", - datePublished: now - 10, paperback: false).save() - new Publication(title: "Some Title", - datePublished: now - 1000, paperback: false).save() - new Publication(title: "Some Title", - datePublished: now - 10, paperback: true).save(flush:true) - session.clear() - - when: - def results = Publication.recentPublications().publicationsWithBookInTitle().findAllWhere(paperback: true) - - then: - 1 == results?.size() - } - - void "Test named query passing multiple parameters to a nested query"() { - given: - def now = new Date() - - new Publication(title: "Some Book", - datePublished: now - 10, paperback: false).save() - new Publication(title: "Some Book", - datePublished: now - 1000, paperback: true).save() - new Publication(title: "Some Book", - datePublished: now - 2, paperback: true).save() - - new Publication(title: "Some Title", - datePublished: now - 2, paperback: false).save() - new Publication(title: "Some Title", - datePublished: now - 1000, paperback: false).save() - new Publication(title: "Some Title", - datePublished: now - 2, paperback: true).save(flush:true) - session.clear() - - when: - def results = Publication.thisWeeksPaperbacks().list() - - then: - 2 == results?.size() - } - - void "Test chaining named queries"() { - - given: - def now = new Date() - [true, false].each { isPaperback -> - 4.times { - Publication.newInstance( - title: "Book Some", - datePublished: now - 10, paperback: isPaperback).save() - Publication.newInstance( - title: "Book Some Other", - datePublished: now - 10, paperback: isPaperback).save() - Publication.newInstance( - title: "Some Other Title", - datePublished: now - 10, paperback: isPaperback).save() - Publication.newInstance( - title: "Book Some", - datePublished: now - 1000, paperback: isPaperback).save() - Publication.newInstance( - title: "Book Some Other", - datePublished: now - 1000, paperback: isPaperback).save() - Publication.newInstance( - title: "Some Other Title", - datePublished: now - 1000, paperback: isPaperback).save() - } - } - session.flush() - session.clear() - - when: - def results = Publication.recentPublications().publicationsWithBookInTitle().list() - - then: "The result size should be 16 when returned from chained queries" - 16 == results?.size() - - when: - results = Publication.recentPublications().publicationsWithBookInTitle().count() - then: - 16 == results - - when: - results = Publication.recentPublications.publicationsWithBookInTitle.list() - then:"The result size should be 16 when returned from chained queries" - 16 == results?.size() - - when: - results = Publication.recentPublications.publicationsWithBookInTitle.count() - then: - 16 == results - - when: - results = Publication.paperbacks().recentPublications().publicationsWithBookInTitle().list() - then: "The result size should be 8 when returned from chained queries" - 8 == results?.size() - - when: - results = Publication.paperbacks().recentPublications().publicationsWithBookInTitle().count() - then: - 8 == results - - when: - results = Publication.recentPublications().publicationsWithBookInTitle().findAllByPaperback(true) - then: "The result size should be 8" - 8 == results?.size() - - when: - results = Publication.paperbacks.recentPublications.publicationsWithBookInTitle.list() - then:"The result size should be 8 when returned from chained queries" - 8 == results?.size() - - when: - results = Publication.paperbacks.recentPublications.publicationsWithBookInTitle.count() - then: - 8 == results - } - - void testChainingQueriesWithParams() { - def Publication = ga.getDomainClass("Publication").clazz - - def now = new Date() - def lastWeek = now - 7 - def longAgo = now - 1000 - 2.times { - Publication.newInstance(title: 'Some Book', - datePublished: now).save(failOnError: true) - Publication.newInstance(title: 'Some Title', - datePublished: now).save(failOnError: true) - } - 3.times { - Publication.newInstance(title: 'Some Book', - datePublished: lastWeek).save(failOnError: true) - Publication.newInstance(title: 'Some Title', - datePublished: lastWeek).save(failOnError: true) - } - 4.times { - Publication.newInstance(title: 'Some Book', - datePublished: longAgo).save(failOnError: true) - Publication.newInstance(title: 'Some Title', - datePublished: longAgo).save(failOnError: true) - } - session.clear() - - def results = Publication.recentPublicationsByTitle('Some Book').publishedAfter(now - 2).list() - assertEquals 'wrong number of books were returned from chained queries', 2, results?.size() - - results = Publication.recentPublicationsByTitle('Some Book').publishedAfter(now - 2).count() - assertEquals 2, results - - results = Publication.recentPublicationsByTitle('Some Book').publishedAfter(lastWeek - 2).list() - assertEquals 'wrong number of books were returned from chained queries', 5, results?.size() - - results = Publication.recentPublicationsByTitle('Some Book').publishedAfter(lastWeek - 2).count() - assertEquals 5, results - } - - void "Test referencing named query before any dynamic methods"() { - - /* - * currently this will work: - * Publication.recentPublications().list() - * but this will not: - * Publication.recentPublications.list() - * - * the static property isn't being added to the class until - * the first dynamic method (recentPublications(), save(), list() etc...) is - * invoked - */ - given: - when: - def publications = Publication.recentPublications.list() - then: - 0 == publications.size() - } - - void "Test named query with conjunction"() { - given: - def now = new Date() - def oldDate = now - 2000 - - Publication.newInstance(title: 'New Paperback', datePublished: now, paperback: true).save(failOnError: true) - Publication.newInstance(title: 'Old Paperback', datePublished: oldDate, paperback: true).save(failOnError: true) - Publication.newInstance(title: 'New Hardback', datePublished: now, paperback: false).save(failOnError: true) - Publication.newInstance(title: 'Old Hardback', datePublished: oldDate, paperback: false).save(failOnError: true) - session.flush() - session.clear() - - when: - def publications = Publication.paperbackAndRecent.list() - - then: - 1 == publications?.size() - } - - void "Test named query with list() method"() { - - given: - def now = new Date() - Publication.newInstance(title: "Some New Book", - datePublished: now - 10).save(failOnError: true) - Publication.newInstance(title: "Some Old Book", - datePublished: now - 900).save(flush:true, failOnError: true) - - session.clear() - - when: - def publications = Publication.recentPublications.list() - - then: - 1 == publications?.size() - 'Some New Book' == publications[0].title - } - - // findby boolean queries not yet supported - @Ignore - void "Test named query with findAll by boolean property"() { - given: - def Publication = ga.getDomainClass("Publication").clazz - def now = new Date() - - Publication.newInstance(title: 'Some Book', datePublished: now - 900, paperback: false).save(failOnError: true) - Publication.newInstance(title: 'Some Book', datePublished: now - 900, paperback: false).save(failOnError: true) - Publication.newInstance(title: 'Some Book', datePublished: now - 10, paperback: true).save(failOnError: true) - Publication.newInstance(title: 'Some Book', datePublished: now - 10, paperback: true).save(failOnError: true) - - when: - def publications = Publication.recentPublications.findAllPaperbackByTitle('Some Book') - - then: - 2 == publications?.size() - publications[0].title == 'Some Book' - publications[1].title == 'Some Book' - } - - // findby boolean queries not yet supported - @Ignore - void "Test named query with find by boolean property"() { - - given: - def now = new Date() - - Publication.newInstance(title: 'Some Book', datePublished: now - 900, paperback: false).save(failOnError: true) - Publication.newInstance(title: 'Some Book', datePublished: now - 900, paperback: false).save(failOnError: true) - Publication.newInstance(title: 'Some Book', datePublished: now - 10, paperback: true).save(failOnError: true) - Publication.newInstance(title: 'Some Book', datePublished: now - 10, paperback: true).save(failOnError: true) - - when: - def publication = Publication.recentPublications.findPaperbackByTitle('Some Book') - - then: - publication.title == 'Some Book' - } - - void "Test named query with countBy*() dynamic finder"() { - given: - def now = new Date() - 3.times { - Publication.newInstance(title: "Some Book", - datePublished: now - 10).save(failOnError: true) - Publication.newInstance(title: "Some Other Book", - datePublished: now - 10).save(failOnError: true) - Publication.newInstance(title: "Some Book", - datePublished: now - 900).save(flush:true, failOnError: true) - } - session.clear() - - when: - def numberOfNewBooksNamedSomeBook = Publication.recentPublications.countByTitle('Some Book') - - then: - 3 == numberOfNewBooksNamedSomeBook - } - - @Ignore // list order by not yet supported - void "Test named query with listOrderBy*() dynamic finder"() { - - given: - def now = new Date() - - Publication.newInstance(title: "Book 1", datePublished: now).save(failOnError: true) - Publication.newInstance(title: "Book 5", datePublished: now).save(failOnError: true) - Publication.newInstance(title: "Book 3", datePublished: now - 900).save(failOnError: true) - Publication.newInstance(title: "Book 2", datePublished: now - 900).save(failOnError: true) - Publication.newInstance(title: "Book 4", datePublished: now).save(flush:true, failOnError: true) - session.clear() - - when: - def publications = Publication.recentPublications.listOrderByTitle() - - then: - 3 == publications?.size() - 'Book 1' == publications[0].title - 'Book 4' == publications[1].title - 'Book 5'== publications[2].title - } - - void "Test get with id of object which does not match criteria"() { - - given: - def now = new Date() - def hasBookInTitle = Publication.newInstance( - title: "Book 1", - datePublished: now - 10).save(failOnError: true) - def doesNotHaveBookInTitle = Publication.newInstance( - title: "Some Publication", - datePublished: now - 900).save(flush:true, failOnError: true) - - session.clear() - - when: - def result = Publication.publicationsWithBookInTitle.get(doesNotHaveBookInTitle.id) - - then: - result == null - } - - void "Test get method returns correct object"() { - - given: - def now = new Date() - def newPublication = Publication.newInstance( - title: "Some New Book", - datePublished: now - 10).save(failOnError: true) - def oldPublication = Publication.newInstance( - title: "Some Old Book", - datePublished: now - 900).save(flush:true, failOnError: true) - - session.clear() - - when: - def publication = Publication.recentPublications.get(newPublication.id) - - then: - publication != null - 'Some New Book' == publication.title - } - - void "Test get method returns null"() { - - given: - def now = new Date() - def newPublication = Publication.newInstance( - title: "Some New Book", - datePublished: now - 10).save(failOnError: true) - def oldPublication = Publication.newInstance( - title: "Some Old Book", - datePublished: now - 900).save(flush:true, failOnError: true) - - session.clear() - - when: - def publication = Publication.recentPublications.get(42 + oldPublication.id) - - then: - publication == null - } - - void "Test count method following named criteria"() { - - given: - def now = new Date() - def newPublication = Publication.newInstance( - title: "Book Some New ", - datePublished: now - 10).save(failOnError: true) - def oldPublication = Publication.newInstance( - title: "Book Some Old ", - datePublished: now - 900).save(flush:true, failOnError: true) - - session.clear() - - when: - def publicationsWithBookInTitleCount = Publication.publicationsWithBookInTitle.count() - def recentPublicationsCount = Publication.recentPublications.count() - - then: - 2 == publicationsWithBookInTitleCount - 1 == recentPublicationsCount - } - - void "Test count with parameterized named query"() { - - given: - def now = new Date() - Publication.newInstance(title: "Book", - datePublished: now - 10).save(failOnError: true) - Publication.newInstance(title: "Book", - datePublished: now - 10).save(failOnError: true) - Publication.newInstance(title: "Book", - datePublished: now - 900).save(flush:true, failOnError: true) - - session.clear() - - when: - def recentPublicationsCount = Publication.recentPublicationsByTitle('Book').count() - - then: - 2 == recentPublicationsCount - } - - void "Test max parameter"() { - given: - (1..25).each {num -> - Publication.newInstance(title: "Book Number ${num}", - datePublished: new Date()).save() - } - - when: - def pubs = Publication.recentPublications.list(max: 10) - then: - 10 == pubs?.size() - } - - void "Test max results"() { - given: - (1..25).each {num -> - Publication.newInstance(title: 'Book Title', - datePublished: new Date() + num).save() - } - - when: - def pubs = Publication.latestBooks.list() - - then: - 10 == pubs?.size() - } - - void "Test findAllWhere method combined with named query"() { - given: - def now = new Date() - (1..5).each {num -> - 3.times { - Publication.newInstance(title: "Book Number ${num}", - datePublished: now).save(failOnError: true) - } - } - - when: - def pubs = Publication.recentPublications.findAllWhere(title: 'Book Number 2') - - then: - 3 == pubs?.size() - } - - void "Test findAllWhere method with named query and disjunction"() { - - given: - def now = new Date() - def oldDate = now - 2000 - - Publication.newInstance(title: 'New Paperback', datePublished: now, paperback: true).save(failOnError: true) - Publication.newInstance(title: 'New Paperback', datePublished: now, paperback: true).save(failOnError: true) - Publication.newInstance(title: 'Old Paperback', datePublished: oldDate, paperback: true).save(failOnError: true) - Publication.newInstance(title: 'New Hardback', datePublished: now, paperback: false).save(failOnError: true) - Publication.newInstance(title: 'Old Hardback', datePublished: oldDate, paperback: false).save(flush:true, failOnError: true) - session.clear() - - when: - def publications = Publication.paperbackOrRecent.findAllWhere(title: 'Old Paperback') - - then: - 1 == publications?.size() - - when: - publications = Publication.paperbackOrRecent.findAllWhere(title: 'Old Hardback') - - then: - 0 == publications?.size() - - when: - publications = Publication.paperbackOrRecent.findAllWhere(title: 'New Paperback') - - then: - 2 == publications?.size() - } - - void "Test get with parameterized named query"() { - - given: - def now = new Date() - def recentPub = Publication.newInstance(title: "Some Title", - datePublished: now).save() - def oldPub = Publication.newInstance(title: "Some Title", - datePublished: now - 900).save() - - when: - def pub = Publication.recentPublicationsByTitle('Some Title').get(oldPub.id) - - then: - pub == null - - when: - pub = Publication.recentPublicationsByTitle('Some Title').get(recentPub.id) - - then: - recentPub.id == pub?.id - } - - void "Test named query with one parameter"() { - - given: - def now = new Date() - (1..5).each {num -> - 3.times { - Publication.newInstance( - title: "Book Number ${num}", - datePublished: now).save(failOnError: true) - } - } - - when: - def pubs = Publication.recentPublicationsByTitle('Book Number 2').list() - - then: - 3 == pubs?.size() - } - - void "Test named query with multiple parameters"() { - - given: - def now = new Date() - (1..5).each {num -> - Publication.newInstance( - title: "Book Number ${num}", - datePublished: ++now).save(failOnError: true) - } - - when: - def pubs = Publication.publishedBetween(now-2, now).list() - - then: - 3 == pubs?.size() - } - - void "Test named query with multiple parameters and dynamic finder"() { - given: - def now = new Date() - (1..5).each {num -> - Publication.newInstance( - title: "Book Number ${num}", - datePublished: now + num).save(failOnError: true) - Publication.newInstance( - title: "Another Book Number ${num}", - datePublished: now + num).save(failOnError: true) - } - - when: - def pubs = Publication.publishedBetween(now, now + 2).findAllByTitleLike('Book%') - - then: - 2 == pubs?.size() - } - - void "Test named query with multiple parameters and map"() { - - given: - def now = new Date() - (1..10).each {num -> - Publication.newInstance( - title: "Book Number ${num}", - datePublished: ++now).save(failOnError: true) - } - - when: - def pubs = Publication.publishedBetween(now-8, now-2).list(offset:2, max: 4) - - then: - 4 == pubs?.size() - } - - void "Test findWhere with named query"() { - - given: - def now = new Date() - (1..5).each {num -> - 3.times { - Publication.newInstance( - title: "Book Number ${num}", - datePublished: now).save(failOnError: true) - } - } - - when: - def pub = Publication.recentPublications.findWhere(title: 'Book Number 2') - then: - 'Book Number 2' == pub.title - } -} - -@Entity -class PlantCategory implements Serializable { - Long id - Long version - Set plants - String name - - static hasMany = [plants:Plant] - - static namedQueries = { -// withPlantsInPatch { -// plants { -// eq 'goesInPatch', true -// } -// } -// withPlantsThatStartWithG { -// plants { -// like 'name', 'G%' -// } -// } -// withPlantsInPatchThatStartWithG { -// withPlantsInPatch() -// withPlantsThatStartWithG() -// } - } -} - -@Entity -class Plant implements Serializable { - Long id - Long version - boolean goesInPatch - String name - - static mapping = { - name index:true - goesInPatch index:true - } -} - -@Entity -class Publication implements Serializable { - Long id - Long version - String title - Date datePublished - Boolean paperback = true - - static mapping = { - title index:true - paperback index:true - datePublished index:true - } - - static namedQueries = { - - lastPublishedBefore { date -> - uniqueResult = true - le 'datePublished', date - order 'datePublished', 'desc' - } - - recentPublications { - def now = new Date() - gt 'datePublished', now - 365 - } - - publicationsWithBookInTitle { - like 'title', 'Book%' - } - - recentPublicationsByTitle { title -> - recentPublications() - eq 'title', title - } - - latestBooks { - maxResults(10) - order("datePublished", "desc") - } - - publishedBetween { start, end -> - between 'datePublished', start, end - } - - publishedAfter { date -> - gt 'datePublished', date - } - - paperbackOrRecent { - or { - def now = new Date() - gt 'datePublished', now - 365 - paperbacks() - } - } - - paperbacks { - eq 'paperback', true - } - - paperbackAndRecent { - paperbacks() - recentPublications() - } - - thisWeeksPaperbacks() { - paperbacks() - def today = new Date() - publishedBetween(today - 7, today) - } - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/NegationSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/NegationSpec.groovy deleted file mode 100644 index f10681634..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/NegationSpec.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package grails.gorm.tests - -/** - * @author graemerocher - */ -class NegationSpec extends GormDatastoreSpec { - - void "Test negation in dynamic finder"() { - given: - new Book(title:"The Stand", author:"Stephen King").save() - new Book(title:"The Shining", author:"Stephen King").save() - new Book(title:"Along Came a Spider", author:"James Patterson").save() - - when: - def results = Book.findAllByAuthorNotEqual("James Patterson") - def author = Book.findByAuthorNotEqual("Stephen King") - - then: - results.size() == 2 - results[0].author == "Stephen King" - results[1].author == "Stephen King" - - author != null - author.author == "James Patterson" - } - - void "Test simple negation in criteria"() { - given: - new Book(title:"The Stand", author:"Stephen King").save() - new Book(title:"The Shining", author:"Stephen King").save() - new Book(title:"Along Came a Spider", author:"James Patterson").save() - - when: - def results = Book.withCriteria { ne("author", "James Patterson" ) } - def author = Book.createCriteria().get { ne("author", "Stephen King" ) } - - then: - results.size() == 2 - results[0].author == "Stephen King" - results[1].author == "Stephen King" - - author != null - author.author == "James Patterson" - } - - void "Test complex negation in criteria"() { - given: - new Book(title:"The Stand", author:"Stephen King").save() - new Book(title:"The Shining", author:"Stephen King").save() - new Book(title:"Along Came a Spider", author:"James Patterson").save() - new Book(title:"The Girl with the Dragon Tattoo", author:"Stieg Larsson").save() - - when: - def results = Book.withCriteria { - not { - eq 'title', 'The Stand' - eq 'author', 'James Patterson' - } - } - - then: - results.size() == 2 - results.find { it.author == "Stieg Larsson" } != null - results.find { it.author == "Stephen King" && it.title == "The Shining" } != null - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/OneToManySpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/OneToManySpec.groovy deleted file mode 100644 index 5df2c45b5..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/OneToManySpec.groovy +++ /dev/null @@ -1,146 +0,0 @@ -package grails.gorm.tests - -/** - * @author graemerocher - */ -class OneToManySpec extends GormDatastoreSpec { - - void "test save and return unidirectional one to many"() { - given: - Person p = new Person(firstName: "Fred", lastName: "Flinstone") - Country c = new Country(name:"Dinoville") - .addToResidents(p) - .save(flush:true) - - session.clear() - - when: - c = Country.findByName("Dinoville") - - then: - c != null - c.residents != null - c.residents.size() == 1 - c.residents.every { it instanceof Person } == true - - when: - c.addToResidents(new Person(firstName:"Barney", lastName:"Rubble")) - c.save(flush:true) - session.clear() - c = Country.findByName("Dinoville") - - then: - c != null - c.residents != null - c.residents.size() == 2 - c.residents.every { it instanceof Person } == true - } - - void "test save and return bidirectional one to many"() { - given: - Person p = new Person(firstName: "Fred", lastName: "Flinstone") - p.addToPets(new Pet(name: "Dino", type: new PetType(name: "Dinosaur"))) - p.save(flush:true) - - new Person(firstName: "Barney", lastName: "Rubble") - .addToPets(new Pet(name: "T Rex", type: new PetType(name: "Dinosaur"))) - .addToPets(new Pet(name: "Stego", type: new PetType(name: "Dinosaur"))) - .save(flush:true) - - session.clear() - - when: - p = Person.findByFirstName("Fred") - - then: - p != null - p.pets != null - p.pets.size() == 1 - def pet = p.pets.iterator().next() - pet instanceof Pet - pet.name == 'Dino' - pet.type != null - pet.type.name == 'Dinosaur' - - when: - p.addToPets(new Pet(name: "Rex", type: new PetType(name: "Dinosaur"))) - p.save(flush:true) - session.clear() - p = Person.findByFirstName("Fred") - - then: - p != null - p.pets != null - p.pets.size() == 2 - p.pets.every { it instanceof Pet } == true - } - - void "test update inverse side of bidirectional one to many collection"() { - given: - Person p = new Person(firstName: "Fred", lastName: "Flinstone").save() - new Pet(name: "Dino", type: new PetType(name: "Dinosaur"), owner:p).save() - Person p2 = new Person(firstName: "Barney", lastName: "Rubble").save() - new Pet(name: "T Rex", type: new PetType(name: "Dinosaur"), owner:p2).save() - new Pet(name: "Stego", type: new PetType(name: "Dinosaur"), owner:p2).save(flush:true) - - session.clear() - - when: - p = Person.findByFirstName("Fred") - - then: - p != null - p.pets != null - p.pets.size() == 1 - def pet = p.pets.iterator().next() - pet instanceof Pet - pet.name == 'Dino' - pet.type != null - pet.type.name == 'Dinosaur' - } - - void "test update inverse side of bidirectional one to many happens before flushing the session"() { - - if (session.datastore.getClass().name.contains('Hibernate')) { - return - } - - given: - Person person = new Person(firstName: "Fred", lastName: "Flinstone").save() - Pet dino = new Pet(name: "Dino", type: new PetType(name: "Dinosaur"), owner:person).save() - Pet trex = new Pet(name: "Trex", type: new PetType(name: "Dinosaur"), owner:person).save() - - expect: - dino.owner == person - trex.owner == person - person.pets.size() == 2 - - when: - session.flush() - session.clear() - person = Person.findByLastName('Flinstone') - - then: - person - person.pets.size() == 2 - } - - void "Test persist of association with proxy"() { - given: "A domain model with a many-to-one" - def person = new Person(firstName: "Fred", lastName: "Flintstone") - person.save(flush:true) - session.clear() - def pet = new Pet(name: "Dino", owner: Person.load(person.id)) - 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.owner != null - pet.owner.firstName == "Fred" - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/OneToOneSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/OneToOneSpec.groovy deleted file mode 100644 index 452332a3b..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/OneToOneSpec.groovy +++ /dev/null @@ -1,82 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity -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) - - then:"The domain model is valid" - - 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" - } -} - -@Entity -class Face implements Serializable { - Long id - Long version - String name - Nose nose - Person person - static hasOne = [nose: Nose] - static belongsTo = [person:Person] - - static constraints = { - person nullable:true - } -} - -@Entity -class Nose implements Serializable { - Long id - Long version - boolean hasFreckles - Face face - static belongsTo = [face: Face] - - static mapping = { - face index:true - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy deleted file mode 100644 index 53aa20f11..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy +++ /dev/null @@ -1,135 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -import org.grails.datastore.mapping.core.OptimisticLockingException -import org.grails.datastore.mapping.core.Session - -/** - * @author Burt Beckwith - */ -class OptimisticLockingSpec extends GormDatastoreSpec { - - void "Test versioning"() { - - given: - def o = new OptLockVersioned(name: 'locked') - - when: - o.save flush: true - - then: - o.version == 0 - - when: - session.clear() - o = OptLockVersioned.get(o.id) - o.name = 'Fred' - o.save flush: true - - then: - o.version == 1 - - when: - session.clear() - o = OptLockVersioned.get(o.id) - - then: - o.name == 'Fred' - o.version == 1 - } - - void "Test optimistic locking"() { - - given: - def o = new OptLockVersioned(name: 'locked').save(flush: true) - session.clear() - - when: - o = OptLockVersioned.get(o.id) - - Thread.start { - OptLockVersioned.withNewSession { s -> - def reloaded = OptLockVersioned.get(o.id) - assert reloaded - reloaded.name += ' in new session' - reloaded.save(flush: true) - } - }.join() - sleep 2000 // heisenbug - - o.name += ' in main session' - def ex - try { - o.save(flush: true) - } - catch (e) { - ex = e - e.printStackTrace() - } - - session.clear() - o = OptLockVersioned.get(o.id) - - then: - ex instanceof OptimisticLockingException - o.version == 1 - o.name == 'locked in new session' - } - - void "Test optimistic locking disabled with 'version false'"() { - - given: - def o = new OptLockNotVersioned(name: 'locked').save(flush: true) - session.clear() - - when: - o = OptLockNotVersioned.get(o.id) - - Thread.start { - OptLockNotVersioned.withNewSession { s -> - def reloaded = OptLockNotVersioned.get(o.id) - reloaded.name += ' in new session' - reloaded.save(flush: true) - } - }.join() - sleep 2000 // heisenbug - - o.name += ' in main session' - def ex - try { - o.save(flush: true) - } - catch (e) { - ex = e - e.printStackTrace() - } - - session.clear() - o = OptLockNotVersioned.get(o.id) - - then: - ex == null - o.name == 'locked in main session' - } -} - -@Entity -class OptLockVersioned implements Serializable { - Long id - Long version - - String name -} - -@Entity -class OptLockNotVersioned implements Serializable { - Long id - Long version - - String name - - static mapping = { - version false - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/OrderBySpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/OrderBySpec.groovy deleted file mode 100644 index 2b08f7a4c..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/OrderBySpec.groovy +++ /dev/null @@ -1,84 +0,0 @@ -package grails.gorm.tests - -/** - * Abstract base test for order by queries. Subclasses should do the necessary setup to configure GORM - */ -class OrderBySpec extends GormDatastoreSpec { - - void "Test order with criteria"() { - given: - def age = 40 - - ["Bob", "Fred", "Barney", "Frank", "Joe", "Ernie"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - when: - def results = TestEntity.createCriteria().list { - order "age" - } - then: - 40 == results[0].age - 41 == results[1].age - 42 == results[2].age - - when: - results = TestEntity.createCriteria().list { - order "age", "desc" - } - - then: - 45 == results[0].age - 44 == results[1].age - 43 == results[2].age - } - void "Test order by with list() method"() { - given: - def age = 40 - - ["Bob", "Fred", "Barney", "Frank", "Joe", "Ernie"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - when: - def results = TestEntity.list(sort:"age") - - then: - 40 == results[0].age - 41 == results[1].age - 42 == results[2].age - - when: - results = TestEntity.list(sort:"age", order:"desc") - - then: - 45 == results[0].age - 44 == results[1].age - 43 == results[2].age - } - - void "Test order by property name with dynamic finder"() { - given: - def age = 40 - - ["Bob", "Fred", "Barney", "Frank", "Joe", "Ernie"].each { - new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() - } - - when: - def results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort:"age"]) - - then: - 40 == results[0].age - 41 == results[1].age - 42 == results[2].age - - when: - results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort:"age", order:"desc"]) - - then: - 45 == results[0].age - 44 == results[1].age - 43 == results[2].age - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/PagedResultSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/PagedResultSpec.groovy deleted file mode 100644 index 775b3a40c..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/PagedResultSpec.groovy +++ /dev/null @@ -1,45 +0,0 @@ -package grails.gorm.tests - -class PagedResultSpec extends GormDatastoreSpec { - - void "Test that a paged result list is returned from the list() method with pagination params"() { - given:"Some people" - createPeople() - - when:"The list method is used with pagination params" - def results = Person.list(offset:2, max:2) - - then:"You get a paged result list back" - results.getClass().simpleName == 'PagedResultList' // Grails/Hibernate has a custom class in different package - results.size() == 2 - results[0].firstName == "Bart" - results[1].firstName == "Lisa" - results.totalCount == 6 - } - - void "Test that a paged result list is returned from the critera with pagination params"() { - given:"Some people" - createPeople() - - when:"The list method is used with pagination params" - def results = Person.createCriteria().list(offset:1, max:2) { - eq 'lastName', 'Simpson' - } - - then:"You get a paged result list back" - results.getClass().simpleName == 'PagedResultList' // Grails/Hibernate has a custom class in different package - results.size() == 2 - results[0].firstName == "Marge" - results[1].firstName == "Bart" - results.totalCount == 4 - } - - protected void createPeople() { - new Person(firstName: "Homer", lastName: "Simpson", age:45).save() - new Person(firstName: "Marge", lastName: "Simpson", age:40).save() - new Person(firstName: "Bart", lastName: "Simpson", age:9).save() - new Person(firstName: "Lisa", lastName: "Simpson", age:7).save() - new Person(firstName: "Barney", lastName: "Rubble", age:35).save() - new Person(firstName: "Fred", lastName: "Flinstone", age:41).save() - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/PersistenceEventListenerSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/PersistenceEventListenerSpec.groovy deleted file mode 100644 index f20fe820b..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/PersistenceEventListenerSpec.groovy +++ /dev/null @@ -1,253 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.DetachedCriteria -import grails.persistence.Entity - -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener -import org.grails.datastore.mapping.engine.event.EventType -import org.grails.datastore.mapping.engine.event.PostDeleteEvent -import org.grails.datastore.mapping.engine.event.PreDeleteEvent -import org.grails.datastore.mapping.engine.event.ValidationEvent -import org.springframework.context.ApplicationEvent - -/** - * @author Tom Widmer - */ -class PersistenceEventListenerSpec extends GormDatastoreSpec { - SpecPersistenceListener listener - - @Override - List getDomainClasses() { - [Simples] - } - - def setup() { - listener = new SpecPersistenceListener(session.datastore) - session.datastore.applicationContext.addApplicationListener(listener) - } - - void "Test delete events"() { - given: - def p = new Simples() - p.name = "Fred" - p.save(flush: true) - session.clear() - - when: - p = Simples.get(p.id) - - then: - 0 == listener.PreDeleteCount - 0 == listener.PostDeleteCount - - when: - p.delete(flush: true) - - then: - 1 == listener.PreDeleteCount - 1 == listener.PostDeleteCount - 0 < listener.events.size() - p == listener.events[-1].entityObject - listener.events[-1].eventType == EventType.PostDelete - listener.events[-1] instanceof PostDeleteEvent - listener.events[-2].eventType == EventType.PreDelete - listener.events[-2] instanceof PreDeleteEvent - } - - void "Test multi-delete events"() { - given: - def freds = (1..3).collect { - new Simples(name: "Fred$it").save(flush: true) - } - session.clear() - - when: - freds = Simples.findAllByIdInList(freds*.id) - - then: - 3 == freds.size() - 0 == listener.PreDeleteCount - 0 == listener.PostDeleteCount - - when: - new DetachedCriteria(Simples).build { - 'in'('id', freds*.id) - }.deleteAll() - session.flush() - - then: - 0 == Simples.count() - 0 == Simples.list().size() - - // conditional assertions because in the case of batch DML statements neither Hibernate nor JPA triggers delete events for individual entities - if (!session.getClass().simpleName in ['JpaSession', 'HibernateSession']) { - 3 == listener.PreDeleteCount - 3 == listener.PostDeleteCount - } - } - - void "Test update events"() { - given: - def p = new Simples() - - p.name = "Fred" - p.save(flush: true) - session.clear() - - when: - p = Simples.get(p.id) - - then: - "Fred" == p.name - 0 == listener.PreUpdateCount - 0 == listener.PostUpdateCount - - when: - p.name = "Bob" - p.save(flush: true) - session.clear() - p = Simples.get(p.id) - - then: - "Bob" == p.name - 1 == listener.PreUpdateCount - 1 == listener.PostUpdateCount - } - - void "Test insert events"() { - given: - def p = new Simples() - - p.name = "Fred" - p.save(flush: true) - session.clear() - - when: - p = Simples.get(p.id) - - then: - "Fred" == p.name - 0 == listener.PreUpdateCount - 1 == listener.PreInsertCount - 0 == listener.PostUpdateCount - 1 == listener.PostInsertCount - - when: - p.name = "Bob" - p.save(flush: true) - session.clear() - p = Simples.get(p.id) - - then: - "Bob" == p.name - 1 == listener.PreUpdateCount - 1 == listener.PreInsertCount - 1 == listener.PostUpdateCount - 1 == listener.PostInsertCount - } - - void "Test load events"() { - given: - def p = new Simples() - - p.name = "Fred" - p.save(flush: true) - session.clear() - - when: - p = Simples.get(p.id) - - then: - "Fred" == p.name - if (!'JpaSession'.equals(session.getClass().simpleName)) { - // JPA doesn't seem to support a pre-load event - 1 == listener.PreLoadCount - } - 1 == listener.PostLoadCount - } - - void "Test multi-load events"() { - given: - def freds = (1..3).collect { - new Simples(name: "Fred$it").save(flush: true) - } - session.clear() - - when: - freds = Simples.findAllByIdInList(freds*.id) - for(f in freds) {} // just to trigger load - - then: - 3 == freds.size() - if (!'JpaSession'.equals(session.getClass().simpleName)) { - // JPA doesn't seem to support a pre-load event - 3 == listener.PreLoadCount - } - 3 == listener.PostLoadCount - } - - void "Test validation events"() { - given: - def p = new Simples() - - p.name = "Fred" - - when: - p.validate() - - then: - 1 == listener.ValidationCount - listener.events.size() == 1 - p == listener.events[0].entityObject - listener.events[0] instanceof ValidationEvent - null == listener.events[0].validatedFields - - when: - p.name = null - p.validate(['name']) - - then: - 2 == listener.ValidationCount - listener.events.size() == 2 - p == listener.events[1].entityObject - listener.events[1] instanceof ValidationEvent - ['name'] == listener.events[1].validatedFields - } -} - -class SpecPersistenceListener extends AbstractPersistenceEventListener { - - SpecPersistenceListener(Datastore datastore) { - super(datastore) - } - - List events = [] - - int PreDeleteCount, - PreInsertCount, - PreUpdateCount, - PostUpdateCount, - PostDeleteCount, - PostInsertCount, - PreLoadCount, - PostLoadCount, - SaveOrUpdateCount, - ValidationCount - - @Override - protected void onPersistenceEvent(AbstractPersistenceEvent event) { - String typeName = event.eventType.name() - this."${typeName}Count"++ - events << event - } - - boolean supportsEventType(Class eventType) { true } -} - -@Entity -class Simples implements Serializable { - Long id - String name -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy deleted file mode 100644 index 7ed0cbabe..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/PropertyComparisonQuerySpec.groovy +++ /dev/null @@ -1,141 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * Tests for criteria queries that compare two properties - */ -class PropertyComparisonQuerySpec extends GormDatastoreSpec { - - void "Test geProperty query"() { - given:"Some dead and alive dogs" - new Dog(name:"Barney", age:7, deathAge:14).save() - new Dog(name:"Fred", age:13, deathAge:13).save() - new Dog(name:"Jack", age:14, deathAge:13).save() - new Dog(name:"Joe", age:4, deathAge:14).save(flush:true) - - when:"We query for dogs that are alive" - def results = Dog.withCriteria { - geProperty 'age', 'deathAge' - order 'name' - } - - then:"3 dogs are found" - Dog.count() == 4 - results.size() == 2 - results[0].name == "Fred" - results[1].name == "Jack" - } - void "Test leProperty query"() { - given:"Some dead and alive dogs" - new Dog(name:"Barney", age:7, deathAge:14).save() - new Dog(name:"Fred", age:13, deathAge:13).save() - new Dog(name:"Jack", age:14, deathAge:13).save() - new Dog(name:"Joe", age:4, deathAge:14).save(flush:true) - - when:"We query for dogs that are alive" - def results = Dog.withCriteria { - leProperty 'age', 'deathAge' - order 'name' - } - - then:"3 dogs are found" - Dog.count() == 4 - results.size() == 3 - results[0].name == "Barney" - results[1].name == "Fred" - results[2].name == "Joe" - } - - void "Test ltProperty query"() { - given:"Some dead and alive dogs" - new Dog(name:"Barney", age:7, deathAge:14).save() - new Dog(name:"Fred", age:13, deathAge:13).save() - new Dog(name:"Joe", age:4, deathAge:14).save(flush:true) - - when:"We query for dogs that are alive" - def results = Dog.withCriteria { - ltProperty 'age', 'deathAge' - order 'name' - } - - then:"2 dogs are found" - Dog.count() == 3 - results.size() == 2 - results[0].name == "Barney" - results[1].name == "Joe" - } - - void "Test gtProperty query"() { - given:"Some dead and alive dogs" - new Dog(name:"Barney", age:7, deathAge:14).save() - new Dog(name:"Fred", age:13, deathAge:13).save() - new Dog(name:"Joe", age:4, deathAge:14).save(flush:true) - - when:"We query for dogs that are alive" - def results = Dog.withCriteria { - gtProperty 'deathAge', 'age' - order 'name' - } - - then:"2 dogs are found" - Dog.count() == 3 - results.size() == 2 - results[0].name == "Barney" - results[1].name == "Joe" - } - - void "Test neProperty query"() { - given:"Some dead and alive dogs" - new Dog(name:"Barney", age:7, deathAge:14).save() - new Dog(name:"Fred", age:13, deathAge:13).save() - new Dog(name:"Joe", age:4, deathAge:14).save(flush:true) - - when:"We query for dogs that are alive" - def results = Dog.withCriteria { - neProperty 'age', 'deathAge' - order 'name' - } - - then:"2 dogs are found" - Dog.count() == 3 - results.size() == 2 - results[0].name == "Barney" - results[1].name == "Joe" - } - - void "Test eqProperty query"() { - given:"Some dead and alive dogs" - new Dog(name:"Barney", age:7, deathAge:14).save() - new Dog(name:"Fred", age:13, deathAge:13).save() - new Dog(name:"Joe", age:4, deathAge:14).save(flush:true) - - when:"We query for dogs that died" - def results = Dog.withCriteria { - eqProperty 'age', 'deathAge' - } - - then:"1 dog is found" - Dog.count() == 3 - results.size() == 1 - results[0].name == "Fred" - } - - @Override - List getDomainClasses() { - [Dog] - } -} - -@Entity -class Dog implements Serializable{ - Long id - int age - int deathAge - String name - - static mapping = { - age index:true - name index:true - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ProxyLoadingSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ProxyLoadingSpec.groovy deleted file mode 100644 index d3d32e828..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ProxyLoadingSpec.groovy +++ /dev/null @@ -1,34 +0,0 @@ -package grails.gorm.tests - -/** - * Abstract base test for loading proxies. Subclasses should do the necessary setup to configure GORM - */ -class ProxyLoadingSpec extends GormDatastoreSpec { - - void "Test load proxied instance directly"() { - - given: - def t = new TestEntity(name:"Bob", age: 45, child:new ChildEntity(name:"Test Child")).save(flush:true) - - when: - def proxy = TestEntity.load(t.id) - - then: - proxy != null - t.id == proxy.id - "Bob" == proxy.name - } - - void "Test query using proxied association"() { - given: - def child = new ChildEntity(name: "Test Child") - def t = new TestEntity(name:"Bob", age: 45, child:child).save() - - when: - def proxy = ChildEntity.load(child.id) - t = TestEntity.findByChild(proxy) - - then: - t != null - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/QueryAfterPropertyChangeSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/QueryAfterPropertyChangeSpec.groovy deleted file mode 100644 index 9e630b835..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/QueryAfterPropertyChangeSpec.groovy +++ /dev/null @@ -1,29 +0,0 @@ -package grails.gorm.tests - -/** - * @author graemerocher - */ -class QueryAfterPropertyChangeSpec extends GormDatastoreSpec { - - void "Test that an entity is de-indexed after a change to an indexed property"() { - given: - def person = new Person(firstName:"Homer", lastName:"Simpson").save(flush:true) - - when: - session.clear() - person = Person.findByFirstName("Homer") - - then: - person != null - - when: - person.firstName = "Marge" - person.save(flush:true) - session.clear() - person = Person.findByFirstName("Homer") - - then: - Person.findByFirstName("Marge") != null - person == null - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/QueryByAssociationSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/QueryByAssociationSpec.groovy deleted file mode 100644 index c1eae2787..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/QueryByAssociationSpec.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package grails.gorm.tests - -/** - * Abstract base test for query associations. Subclasses should do the necessary setup to configure GORM - */ -class QueryByAssociationSpec extends GormDatastoreSpec { - - void "Test query entity by single-ended association"() { - given: - def age = 40 - ["Bob", "Fred", "Barney", "Frank"].each { new TestEntity(name:it, age: age++, child:new ChildEntity(name:"$it Child")).save() } - - when: - def child = ChildEntity.findByName("Barney Child") - - then: - child != null - child.id != null - - when: - def t = TestEntity.findByChild(child) - - then: - t != null - "Barney" == t.name - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/QueryByNullSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/QueryByNullSpec.groovy deleted file mode 100644 index ac3318b61..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/QueryByNullSpec.groovy +++ /dev/null @@ -1,19 +0,0 @@ -package grails.gorm.tests - -class QueryByNullSpec extends GormDatastoreSpec { - - void 'Test passing null as the sole argument to a dynamic finder multiple times'() { - // see GRAILS-3463 - when: - def people = Person.findAllByLastName(null) - - then: - !people - - when: - people - Person.findAllByLastName(null) - - then: - !people - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/QueryEventsSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/QueryEventsSpec.groovy deleted file mode 100644 index a0d1d88a1..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/QueryEventsSpec.groovy +++ /dev/null @@ -1,107 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.DetachedCriteria -import org.grails.datastore.mapping.query.event.AbstractQueryEvent -import org.grails.datastore.mapping.query.event.PostQueryEvent -import org.grails.datastore.mapping.query.event.PreQueryEvent -import org.springframework.context.ApplicationEvent -import org.springframework.context.event.SmartApplicationListener -import spock.lang.Ignore - -/** - * Tests for query events. - */ -@Ignore -class QueryEventsSpec extends GormDatastoreSpec { - SpecQueryEventListener listener - - @Override - List getDomainClasses() { - [Simples] - } - - def setup() { - listener = new SpecQueryEventListener() - session.datastore.applicationContext.addApplicationListener(listener) - } - - void "pre-events are fired before queries are run"() { - when: - TestEntity.findByName 'bob' - then: - listener.events.size() >= 1 - listener.events[0] instanceof PreQueryEvent - listener.events[0].query != null - listener.PreExecution == 1 - - when: - TestEntity.where {name == 'bob'}.list() - then: - listener.PreExecution == 2 - - when: - new DetachedCriteria(TestEntity).build({name == 'bob'}).list() - then: - listener.PreExecution == 3 - } - - void "post-events are fired after queries are run"() { - given: - def entity = new TestEntity(name: 'bob').save(flush: true) - new TestEntity(name: 'mark').save(flush: true) - - when: - TestEntity.findByName 'bob' - then: - listener.events.size() >= 1 - listener.events[1] instanceof PostQueryEvent - listener.events[1].query != null - listener.events[1].query == listener.events[0].query - listener.events[1].results instanceof List - listener.events[1].results.size() == 1 - listener.events[1].results[0] == entity - listener.PostExecution == 1 - - when: - TestEntity.where {name == 'bob'}.list() - then: - listener.PostExecution == 2 - - when: - new DetachedCriteria(TestEntity).build({name == 'bob'}).list() - then: - listener.PostExecution == 3 - } - - static class SpecQueryEventListener implements SmartApplicationListener { - - List events = [] - - int PreExecution, - PostExecution - - @Override - void onApplicationEvent(ApplicationEvent event) { - AbstractQueryEvent e = event as AbstractQueryEvent - def typeName = e.eventType.name() - this."$typeName"++ - events << event - } - - @Override - boolean supportsSourceType(Class sourceType) { - return true - } - - @Override - int getOrder() { - Integer.MAX_VALUE / 2 - } - - @Override - boolean supportsEventType(Class eventType) { - return eventType in [PreQueryEvent, PostQueryEvent] - } - } -} - diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/RangeQuerySpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/RangeQuerySpec.groovy deleted file mode 100644 index 30e87e8ec..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/RangeQuerySpec.groovy +++ /dev/null @@ -1,120 +0,0 @@ -package grails.gorm.tests - -import groovy.time.TimeCategory - -/** - * Abstract base test for querying ranges. Subclasses should do the necessary setup to configure GORM - */ -class RangeQuerySpec extends GormDatastoreSpec { - - void "Test between query with dates"() { - given: - def now = new Date() - use(TimeCategory) { - new Publication(title:"The Guardian", datePublished: now - 5.minutes).save() - new Publication(title:"The Times", datePublished: now - 5.days).save() - new Publication(title:"The Observer", datePublished: now - 10.days).save() - } - - when: - def results = use(TimeCategory) { - Publication.findAllByDatePublishedBetween(now-6.days, now) - } - - then: - results != null - results.size() == 2 - } - - void "Test between query"() { - given: - int age = 40 - ["Bob", "Fred", "Barney", "Frank", "Joe", "Ernie"].each { new TestEntity(name:it, age: age--, child:new ChildEntity(name:"$it Child")).save() } - - when: - def results = TestEntity.findAllByAgeBetween(38, 40) - - then: - 3 == results.size() - - when: - results = TestEntity.findAllByAgeBetween(38, 40) - - then: - 3 == results.size() - - results.find { it.name == "Bob" } != null - results.find { it.name == "Fred" } != null - results.find { it.name == "Barney" } != null - - when: - results = TestEntity.findAllByAgeBetweenOrName(38, 40, "Ernie") - - then: - 4 == results.size() - } - - void "Test greater than or equal to and less than or equal to queries"() { - given: - - int age = 40 - ["Bob", "Fred", "Barney", "Frank", "Joe", "Ernie"].each { new TestEntity(name:it, age: age--, child:new ChildEntity(name:"$it Child")).save() } - - when: - def results = TestEntity.findAllByAgeGreaterThanEquals(38) - - then: - 3 == results.size() - results.find { it.age == 38 } != null - results.find { it.age == 39 } != null - results.find { it.age == 40 } != null - - when: - results = TestEntity.findAllByAgeLessThanEquals(38) - - then: - 4 == results.size() - results.find { it.age == 38 } != null - results.find { it.age == 37 } != null - results.find { it.age == 36 } != null - results.find { it.age == 35 } != null - } - - void 'Test InRange Dynamic Finder'() { - given: - new Person(firstName: 'Jake', lastName: 'Brown', age: 11).save() - new Person(firstName: 'Zack', lastName: 'Brown', age: 14).save() - new Person(firstName: 'Jeff', lastName: 'Brown', age: 41).save() - new Person(firstName: 'Zack', lastName: 'Galifianakis', age: 41).save() - - when: - int count = Person.countByAgeInRange(14..41) - - then: - 3 == count - - when: - count = Person.countByAgeInRange(41..14) - - then: - 3 == count - - when: - count = Person.countByAgeInRange(14..<30) - - then: - 1 == count - - when: - count = Person.countByAgeInRange(14..<42) - - then: - 3 == count - - when: - count = Person.countByAgeInRange(15..40) - - then: - 0 == count - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/SaveAllSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/SaveAllSpec.groovy deleted file mode 100644 index 09f69fc45..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/SaveAllSpec.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package grails.gorm.tests - -class SaveAllSpec extends GormDatastoreSpec { - - def "Test that many objects can be saved at once using multiple arguments"() { - given: - def bob = new Person(firstName:"Bob", lastName:"Builder") - def fred = new Person(firstName:"Fred", lastName:"Flintstone") - def joe = new Person(firstName:"Joe", lastName:"Doe") - - Person.saveAll(bob, fred, joe) - - when: - def total = Person.count() - def results = Person.list() - then: - total == 3 - results.every { it.id != null } == true - } - - def "Test that many objects can be saved at once using a list"() { - given: - def bob = new Person(firstName:"Bob", lastName:"Builder") - def fred = new Person(firstName:"Fred", lastName:"Flintstone") - def joe = new Person(firstName:"Joe", lastName:"Doe") - - Person.saveAll([bob, fred, joe]) - - when: - def total = Person.count() - def results = Person.list() - then: - total == 3 - results.every { it.id != null } == true - } - - def "Test that many objects can be saved at once using an iterable"() { - given: - def bob = new Person(firstName:"Bob", lastName:"Builder") - def fred = new Person(firstName:"Fred", lastName:"Flintstone") - def joe = new Person(firstName:"Joe", lastName:"Doe") - - Vector personVector = new Vector() - personVector.add(bob) - personVector.add(fred) - personVector.add(joe) - - Person.saveAll(personVector) - - when: - def total = Person.count() - def results = Person.list() - then: - total == 3 - results.every { it.id != null } == true - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/SessionCreationEventSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/SessionCreationEventSpec.groovy deleted file mode 100644 index 5cb50c64d..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/SessionCreationEventSpec.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package grails.gorm.tests - -import org.springframework.context.event.SmartApplicationListener -import org.springframework.context.ApplicationEvent -import org.grails.datastore.mapping.core.SessionCreationEvent -import org.grails.datastore.mapping.core.Session -import spock.lang.Ignore - -/** - * Test case that session creation events are fired. - */ -@Ignore -class SessionCreationEventSpec extends GormDatastoreSpec { - - Listener listener - - def setup() { - listener = new Listener() - session.datastore.applicationContext.addApplicationListener(listener) - } - - void "test event for new session"() { - when:"Using existing session" - TestEntity.withSession { s -> - s.flush() - } - then: - listener.events.empty - - when:"Creating new session" - def newSession = null - def isDatastoreSession = false - TestEntity.withNewSession { s -> - newSession = s - isDatastoreSession = s instanceof Session - } - then: - !isDatastoreSession || listener.events.size() == 1 - !isDatastoreSession || listener.events[0].session == newSession - } - - - static class Listener implements SmartApplicationListener { - List events = [] - - @Override - int getOrder() { - Integer.MAX_VALUE / 2 - } - - @Override - void onApplicationEvent(ApplicationEvent event) { - events << event - } - - @Override - boolean supportsSourceType(Class sourceType) { - return true - } - - @Override - boolean supportsEventType(Class eventType) { - return eventType == SessionCreationEvent - } - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/SessionPropertiesSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/SessionPropertiesSpec.groovy deleted file mode 100644 index f21e2243c..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/SessionPropertiesSpec.groovy +++ /dev/null @@ -1,41 +0,0 @@ -package grails.gorm.tests - -/** - * Test session properties - */ -class SessionPropertiesSpec extends GormDatastoreSpec { - - void "test session properties"() { - when: - session.setSessionProperty('Hello', 'World') - then: - session.getSessionProperty('Hello') == 'World' - session.getSessionProperty('World') == null - - when: - session.setSessionProperty('One', 'Two') - then: - session.getSessionProperty('Hello') == 'World' - session.getSessionProperty('One') == 'Two' - - when: - def old = session.setSessionProperty('One', 'Three') - then: - session.getSessionProperty('Hello') == 'World' - session.getSessionProperty('One') == 'Three' - old == 'Two' - - when:"Clearing the session doesn't clear the properties" - session.clear() - then: - session.getSessionProperty('Hello') == 'World' - session.getSessionProperty('One') == 'Three' - - when: - old = session.clearSessionProperty('Hello') - then: - session.getSessionProperty('Hello') == null - session.getSessionProperty('One') == 'Three' - old == 'World' - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/SizeQuerySpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/SizeQuerySpec.groovy deleted file mode 100644 index 4d5d62693..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/SizeQuerySpec.groovy +++ /dev/null @@ -1,309 +0,0 @@ -package grails.gorm.tests - -import spock.lang.Specification - -/** - * Tests for querying the size of collections etc. - */ -class SizeQuerySpec extends GormDatastoreSpec { - - void "Test sizeLe criterion"() { - given: "A country with only 1 resident" - Person p = new Person(firstName: "Fred", lastName: "Flinstone") - Country c = new Country(name:"Dinoville") - .addToResidents(p) - .save(flush:true) - - new Country(name:"Springfield") - .addToResidents(firstName:"Homer", lastName:"Simpson") - .addToResidents(firstName:"Bart", lastName:"Simpson") - .addToResidents(firstName:"Marge", lastName:"Simpson") - .save(flush:true) - - new Country(name:"Miami") - .addToResidents(firstName:"Dexter", lastName:"Morgan") - .addToResidents(firstName:"Debra", lastName:"Morgan") - .save(flush:true) - - session.clear() - - when:"We query for countries with 1 resident" - def results = Country.withCriteria { - sizeLe "residents", 3 - order "name" - } - - then:"We get the correct result back" - results != null - results.size() == 3 - results[0].name == 'Dinoville' - results[1].name == 'Miami' - results[2].name == 'Springfield' - - when:"We query for countries with 2 resident" - results = Country.withCriteria { - sizeLe "residents", 2 - } - - then:"We get the correct result back" - results != null - results.size() == 2 - results[0].name == 'Dinoville' - results[1].name == 'Miami' - - when:"We query for countries with 2 residents" - results = Country.withCriteria { - sizeLe "residents", 1 - } - - then:"we get 1 result back" - results.size() == 1 - } - - void "Test sizeLt criterion"() { - given: "A country with only 1 resident" - Person p = new Person(firstName: "Fred", lastName: "Flinstone") - Country c = new Country(name:"Dinoville") - .addToResidents(p) - .save(flush:true) - - new Country(name:"Springfield") - .addToResidents(firstName:"Homer", lastName:"Simpson") - .addToResidents(firstName:"Bart", lastName:"Simpson") - .addToResidents(firstName:"Marge", lastName:"Simpson") - .save(flush:true) - - new Country(name:"Miami") - .addToResidents(firstName:"Dexter", lastName:"Morgan") - .addToResidents(firstName:"Debra", lastName:"Morgan") - .save(flush:true) - - session.clear() - - when:"We query for countries with 1 resident" - def results = Country.withCriteria { - sizeLt "residents", 3 - order "name" - } - - then:"We get the correct result back" - results != null - results.size() == 2 - results[0].name == 'Dinoville' - results[1].name == 'Miami' - - when:"We query for countries with 2 resident" - results = Country.withCriteria { - sizeLt "residents", 2 - } - - then:"We get the correct result back" - results != null - results.size() == 1 - results[0].name == 'Dinoville' - - when:"We query for countries with 2 residents" - results = Country.withCriteria { - sizeLt "residents", 1 - } - - then:"we get no results back" - results.size() == 0 - } - - void "Test sizeGt criterion"() { - given: "A country with only 1 resident" - Person p = new Person(firstName: "Fred", lastName: "Flinstone") - Country c = new Country(name:"Dinoville") - .addToResidents(p) - .save(flush:true) - - new Country(name:"Springfield") - .addToResidents(firstName:"Homer", lastName:"Simpson") - .addToResidents(firstName:"Bart", lastName:"Simpson") - .addToResidents(firstName:"Marge", lastName:"Simpson") - .save(flush:true) - - new Country(name:"Miami") - .addToResidents(firstName:"Dexter", lastName:"Morgan") - .addToResidents(firstName:"Debra", lastName:"Morgan") - .save(flush:true) - - session.clear() - - when:"We query for countries with 1 resident" - def results = Country.withCriteria { - sizeGt "residents", 1 - order "name" - } - - then:"We get the correct result back" - results != null - results.size() == 2 - results[0].name == 'Miami' - results[1].name == 'Springfield' - - when:"We query for countries with 2 resident" - results = Country.withCriteria { - sizeGt "residents", 2 - } - - then:"We get the correct result back" - results != null - results.size() == 1 - results[0].name == 'Springfield' - - when:"We query for countries with 2 residents" - results = Country.withCriteria { - sizeGt "residents", 5 - } - - then:"we get no results back" - results.size() == 0 - } - - void "Test sizeGe criterion"() { - given: "A country with only 1 resident" - Person p = new Person(firstName: "Fred", lastName: "Flinstone") - Country c = new Country(name:"Dinoville") - .addToResidents(p) - .save(flush:true) - - new Country(name:"Springfield") - .addToResidents(firstName:"Homer", lastName:"Simpson") - .addToResidents(firstName:"Bart", lastName:"Simpson") - .addToResidents(firstName:"Marge", lastName:"Simpson") - .save(flush:true) - - new Country(name:"Miami") - .addToResidents(firstName:"Dexter", lastName:"Morgan") - .addToResidents(firstName:"Debra", lastName:"Morgan") - .save(flush:true) - - session.clear() - - when:"We query for countries with 1 resident" - def results = Country.withCriteria { - sizeGe "residents", 1 - order "name" - } - - then:"We get the correct result back" - results != null - results.size() == 3 - results[0].name == 'Dinoville' - results[1].name == 'Miami' - results[2].name == 'Springfield' - - when:"We query for countries with 2 resident" - results = Country.withCriteria { - sizeGe "residents", 2 - order "name" - } - - then:"We get the correct result back" - results != null - results.size() == 2 - results[0].name == 'Miami' - results[1].name == 'Springfield' - - when:"We query for countries with 2 residents" - results = Country.withCriteria { - sizeGe "residents", 5 - } - - then:"we get no results back" - results.size() == 0 - } - - void "Test sizeEq criterion"() { - given: "A country with only 1 resident" - Person p = new Person(firstName: "Fred", lastName: "Flinstone") - Country c = new Country(name:"Dinoville") - .addToResidents(p) - .save(flush:true) - - new Country(name:"Springfield") - .addToResidents(firstName:"Homer", lastName:"Simpson") - .addToResidents(firstName:"Bart", lastName:"Simpson") - .addToResidents(firstName:"Marge", lastName:"Simpson") - .save(flush:true) - - session.clear() - - when:"We query for countries with 1 resident" - def results = Country.withCriteria { - sizeEq "residents", 1 - } - - then:"We get the correct result back" - results != null - results.size() == 1 - results[0].name == 'Dinoville' - - when:"We query for countries with 3 resident" - results = Country.withCriteria { - sizeEq "residents", 3 - } - - then:"We get the correct result back" - results != null - results.size() == 1 - results[0].name == 'Springfield' - - when:"We query for countries with 2 residents" - results = Country.withCriteria { - sizeEq "residents", 2 - } - - then:"we get no results back" - results.size() == 0 - } - - void "Test sizeNe criterion"() { - given: "A country with only 1 resident" - Person p = new Person(firstName: "Fred", lastName: "Flinstone") - Country c = new Country(name:"Dinoville") - .addToResidents(p) - .save(flush:true) - - new Country(name:"Springfield") - .addToResidents(firstName:"Homer", lastName:"Simpson") - .addToResidents(firstName:"Bart", lastName:"Simpson") - .addToResidents(firstName:"Marge", lastName:"Simpson") - .save(flush:true) - - session.clear() - - when:"We query for countries that don't have 1 resident" - def results = Country.withCriteria { - sizeNe "residents", 1 - } - - then:"We get the correct result back" - results != null - results.size() == 1 - results[0].name == 'Springfield' - - when:"We query for countries who don't have 3 resident" - results = Country.withCriteria { - sizeNe "residents", 3 - } - - then:"We get the correct result back" - results != null - results.size() == 1 - results[0].name == 'Dinoville' - - when:"We query for countries with 2 residents" - results = Country.withCriteria { - and { - sizeNe "residents", 1 - sizeNe "residents", 3 - } - } - - then:"we get no results back" - results.size() == 0 - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/TestEntity.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/TestEntity.groovy deleted file mode 100644 index 646f91a60..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/TestEntity.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -/** - * @author graemerocher - */ -@Entity -class TestEntity implements Serializable { - Long id - Long version - String name - Integer age = 30 - - ChildEntity child - - static mapping = { - name index:true - age index:true, nullable:true - child index:true, nullable:true - } - - static constraints = { - name blank:false - child nullable:true - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/TestEnum.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/TestEnum.groovy deleted file mode 100644 index f7195559e..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/TestEnum.groovy +++ /dev/null @@ -1,8 +0,0 @@ -package grails.gorm.tests - -enum TestEnum { - V1, - V2, - V3 - -} 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 deleted file mode 100644 index 27c9b6566..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/UniqueConstraintSpec.groovy +++ /dev/null @@ -1,118 +0,0 @@ -package grails.gorm.tests - -import grails.persistence.Entity - -import org.codehaus.groovy.grails.commons.GrailsDomainConfigurationUtil -import org.codehaus.groovy.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 -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -import javax.persistence.FlushModeType - -/** - * Tests the unique constraint - */ -class UniqueConstraintSpec extends GormDatastoreSpec { - - void "Test simple unique constraint"() { - given:"A validator that uses the unique constraint" - setupValidator() - - when:"Two domain classes with the same name are saved" - def one = new UniqueGroup(name:"foo").save(flush:true) - def two = new UniqueGroup(name:"foo") - two.save(flush:true) - - then:"The second has errors" - one != null - two.hasErrors() - UniqueGroup.count() == 1 - - when:"The first is saved again" - one = one.save(flush:true) - - then:"The are no errors" - one != null - - when:"Three domain classes are saved within different uniqueness groups" - one = new GroupWithin(name:"foo", org:"mycompany").save(flush:true) - two = new GroupWithin(name:"foo", org:"othercompany").save(flush:true) - def three = new GroupWithin(name:"foo", org:"mycompany") - three.save(flush:true) - - then:"Only the third has errors" - one != null - two != null - three.hasErrors() - GroupWithin.count() == 2 - } - - void "withManualFlushMode should use flushmode commit"() { - - setup: - def constraint = new UniqueConstraint(session.datastore) - constraint.owningClass = UniqueGroup - def origFlushMode = session.flushMode - - when: "check if session flushmode has really switched to COMMIT" - constraint.withManualFlushMode { s-> - assert s.flushMode == FlushModeType.COMMIT - } - - then: - session.flushMode == origFlushMode - } - - protected void setupValidator() { - - def groupValidator = [supports: {Class cls -> true}, - validate: {Object target, Errors errors -> - def constrainedProperties = GrailsDomainConfigurationUtil.evaluateConstraints(UniqueGroup) - for (ConstrainedProperty cp in constrainedProperties.values()) { - cp.validate(target, target[cp.propertyName], errors) - } - }] as Validator - - def groupWithinValidator = [supports: {Class cls -> true}, - validate: {Object target, Errors errors -> - def constrainedProperties = GrailsDomainConfigurationUtil.evaluateConstraints(GroupWithin) - for (ConstrainedProperty cp in constrainedProperties.values()) { - cp.validate(target, target[cp.propertyName], errors) - } - }] as Validator - - final MappingContext context = session.datastore.mappingContext - final PersistentEntity entity = context.getPersistentEntity(UniqueGroup.name) - context.addEntityValidator(entity, groupValidator) - entity = context.getPersistentEntity(GroupWithin.name) - context.addEntityValidator(entity, groupWithinValidator) - } - - @Override - List getDomainClasses() { - [UniqueGroup, GroupWithin] - } -} - -@Entity -class UniqueGroup implements Serializable { - Long id - String name - static constraints = { - name unique:true, index:true - } -} - -@Entity -class GroupWithin implements Serializable { - Long id - String name - String org - static constraints = { - name unique:"org", index:true - org index:true - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/UpdateWithProxyPresentSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/UpdateWithProxyPresentSpec.groovy deleted file mode 100644 index de7191ff6..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/UpdateWithProxyPresentSpec.groovy +++ /dev/null @@ -1,167 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.dirty.checking.DirtyCheck -import grails.persistence.Entity - -import org.grails.datastore.gorm.proxy.GroovyProxyFactory -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -/** - * @author graemerocher - */ -class UpdateWithProxyPresentSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [Pet, Person, PetType, Parent, Child] - } - - void "Test update entity with association proxies"() { - given: - session.mappingContext.setProxyFactory(new GroovyProxyFactory()) - def person = new Person(firstName:"Bob", lastName:"Builder") - def petType = new PetType(name:"snake") - def pet = new Pet(name:"Fred", type:petType, owner:person) - person.addToPets(pet) - person.save(flush:true) - session.clear() - - when: - person = Person.get(person.id) - person.firstName = "changed" - person.save(flush:true) - session.clear() - person = Person.get(person.id) - def personPet = person.pets.iterator().next() - - then: - person.firstName == "changed" - personPet.name == "Fred" - personPet.id == pet.id - personPet.owner.id == person.id - personPet.type.name == 'snake' - personPet.type.id == petType.id - } - - void "Test update unidirectional oneToMany with proxy"() { - given: - session.mappingContext.setProxyFactory(new GroovyProxyFactory()) - def parent = new Parent(name: "Bob").save(flush: true) - def child = new Child(name: "Bill").save(flush: true) - session.clear() - - when: - parent = Parent.get(parent.id) - child = Child.load(child.id) // make sure we've got a proxy. - parent.addToChildren(child) - parent.save(flush: true) - session.clear() - parent = Parent.get(parent.id) - - then: - parent.name == 'Bob' - parent.children.size() == 1 - - when: - child = parent.children.first() - - then: - child.name == "Bill" - } -} - -@Entity -class Pet implements Serializable { - Long id - Long version - String name - Date birthDate = new Date() - PetType type = new PetType(name:"Unknown") - Person owner - Integer age - Face face - - static mapping = { - name index:true - } - - static constraints = { - owner nullable:true - age nullable: true - face nullable:true - } -} - -@DirtyCheck -@Entity -@ApplyDetachedCriteriaTransform -class Person implements Serializable, Comparable { - static simpsons = where { - lastName == "Simpson" - } - - Long id - Long version - String firstName - String lastName - Integer age = 0 - Set pets = [] as Set - static hasMany = [pets:Pet] - Face face - -// static peopleWithOlderPets = where { -// pets { -// age > 9 -// } -// } -// static peopleWithOlderPets2 = where { -// pets.age > 9 -// } - - static Person getByFirstNameAndLastNameAndAge(String firstName, String lastName, int age) { - find( new Person(firstName: firstName, lastName: lastName, age: age) ) - } - - static mapping = { - firstName index:true - lastName index:true - age index:true - } - - static constraints = { - face nullable:true - } - - @Override - int compareTo(Person t) { - age <=> t.age - } -} - -@Entity -class PetType implements Serializable { - private static final long serialVersionUID = 1 - Long id - Long version - String name - - static belongsTo = Pet -} - -@Entity -class Parent implements Serializable { - private static final long serialVersionUID = 1 - Long id - String name - Set children = [] - static hasMany = [children: Child] -} - -@Entity -class Child implements Serializable { - private static final long serialVersionUID = 1 - Long id - String name -} - - diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ValidationSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ValidationSpec.groovy deleted file mode 100644 index 3d028dc00..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/ValidationSpec.groovy +++ /dev/null @@ -1,234 +0,0 @@ -package grails.gorm.tests - -import org.grails.datastore.gorm.validation.CascadingValidator -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.validation.ValidatingEventListener -import org.springframework.validation.Validator - -import spock.lang.Unroll - -/** - * Tests validation semantics. - */ -class ValidationSpec extends GormDatastoreSpec { - - void 'Test validating an object that has had values rejected with an ObjectError'() { - given: - def t = new TestEntity(name: 'someName') - - when: - t.errors.reject 'foo' - boolean isValid = t.validate() - int errorCount = t.errors.errorCount - - then: - !isValid - 1 == errorCount - } - - void "Test disable validation"() { - session.datastore.applicationContext.addApplicationListener( - new ValidatingEventListener(session.datastore)) - - // test assumes name cannot be blank - given: - def t - - when: - t = new TestEntity(name:"", child:new ChildEntity(name:"child")) - boolean validationResult = t.validate() - def errors = t.errors - - then: - !validationResult - t.hasErrors() - errors != null - errors.hasErrors() - - when: - t.save(validate:false, flush:true) - - then: - t.id != null - !t.hasErrors() - } - - void "Test validate() method"() { - // test assumes name cannot be blank - given: - def t - - when: - t = new TestEntity(name:"") - boolean validationResult = t.validate() - def errors = t.errors - - then: - !validationResult - t.hasErrors() - errors != null - errors.hasErrors() - - when: - t.clearErrors() - - then: - !t.hasErrors() - } - - void "Test that validate is called on save()"() { - - given: - def t - - when: - t = new TestEntity(name:"") - - then: - t.save() == null - t.hasErrors() == true - 0 == TestEntity.count() - - when: - t.clearErrors() - t.name = "Bob" - t.age = 45 - t.child = new ChildEntity(name:"Fred") - t = t.save() - - then: - t != null - 1 == TestEntity.count() - } - - void "Test beforeValidate gets called on save()"() { - given: - def entityWithNoArgBeforeValidateMethod - def entityWithListArgBeforeValidateMethod - def entityWithOverloadedBeforeValidateMethod - - when: - entityWithNoArgBeforeValidateMethod = new ClassWithNoArgBeforeValidate() - entityWithListArgBeforeValidateMethod = new ClassWithListArgBeforeValidate() - entityWithOverloadedBeforeValidateMethod = new ClassWithOverloadedBeforeValidate() - entityWithNoArgBeforeValidateMethod.save() - entityWithListArgBeforeValidateMethod.save() - entityWithOverloadedBeforeValidateMethod.save() - - then: - 1 == entityWithNoArgBeforeValidateMethod.noArgCounter - 1 == entityWithListArgBeforeValidateMethod.listArgCounter - 1 == entityWithOverloadedBeforeValidateMethod.noArgCounter - 0 == entityWithOverloadedBeforeValidateMethod.listArgCounter - } - - void "Test beforeValidate gets called on validate()"() { - given: - def entityWithNoArgBeforeValidateMethod - def entityWithListArgBeforeValidateMethod - def entityWithOverloadedBeforeValidateMethod - - when: - entityWithNoArgBeforeValidateMethod = new ClassWithNoArgBeforeValidate() - entityWithListArgBeforeValidateMethod = new ClassWithListArgBeforeValidate() - entityWithOverloadedBeforeValidateMethod = new ClassWithOverloadedBeforeValidate() - entityWithNoArgBeforeValidateMethod.validate() - entityWithListArgBeforeValidateMethod.validate() - entityWithOverloadedBeforeValidateMethod.validate() - - then: - 1 == entityWithNoArgBeforeValidateMethod.noArgCounter - 1 == entityWithListArgBeforeValidateMethod.listArgCounter - 1 == entityWithOverloadedBeforeValidateMethod.noArgCounter - 0 == entityWithOverloadedBeforeValidateMethod.listArgCounter - } - - void "Test beforeValidate gets called on validate() and passing a list of field names to validate"() { - given: - def entityWithNoArgBeforeValidateMethod - def entityWithListArgBeforeValidateMethod - def entityWithOverloadedBeforeValidateMethod - - when: - entityWithNoArgBeforeValidateMethod = new ClassWithNoArgBeforeValidate() - entityWithListArgBeforeValidateMethod = new ClassWithListArgBeforeValidate() - entityWithOverloadedBeforeValidateMethod = new ClassWithOverloadedBeforeValidate() - entityWithNoArgBeforeValidateMethod.validate(['name']) - entityWithListArgBeforeValidateMethod.validate(['name']) - entityWithOverloadedBeforeValidateMethod.validate(['name']) - - then: - 1 == entityWithNoArgBeforeValidateMethod.noArgCounter - 1 == entityWithListArgBeforeValidateMethod.listArgCounter - 0 == entityWithOverloadedBeforeValidateMethod.noArgCounter - 1 == entityWithOverloadedBeforeValidateMethod.listArgCounter - ['name'] == entityWithOverloadedBeforeValidateMethod.propertiesPassedToBeforeValidate - } - - void "Test that validate works without a bound Session"() { - - given: - def t - - when: - session.disconnect() - t = new TestEntity(name:"") - - then: - !session.datastore.hasCurrentSession() - t.save() == null - t.hasErrors() == true - 1 == t.errors.allErrors.size() - TestEntity.getValidationErrorsMap().get(System.identityHashCode(t)).is(t.errors) - 0 == TestEntity.count() - - when: - t.clearErrors() - t.name = "Bob" - t.age = 45 - t.child = new ChildEntity(name:"Fred") - t = t.save(flush: true) - - then: - !session.datastore.hasCurrentSession() - t != null - 1 == TestEntity.count() - } - - void "Two parameter validate is called on entity validator if it implements Validator interface"() { - given: - def mockValidator = Mock(Validator) - session.mappingContext.addEntityValidator(persistentEntityFor(Task), mockValidator) - def task = new Task() - - when: - task.validate() - - then: - 1 * mockValidator.validate(task, _) - } - - @Unroll - void "deepValidate parameter is honoured if entity validator implements CascadingValidator"() { - given: - def mockValidator = Mock(CascadingValidator) - session.mappingContext.addEntityValidator(persistentEntityFor(Task), mockValidator) - def task = new Task() - - when: - task.validate(validateParams) - - then: - 1 * mockValidator.validate(task, _, cascade) - - where: - validateParams | cascade - [:] | true - [deepValidate: true] | true - [deepValidate: false] | false - } - - private PersistentEntity persistentEntityFor(Class c) { - session.mappingContext.persistentEntities.find { it.javaClass == c } - } -} diff --git a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/WithTransactionSpec.groovy b/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/WithTransactionSpec.groovy deleted file mode 100644 index aeefee629..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/grails/gorm/tests/WithTransactionSpec.groovy +++ /dev/null @@ -1,67 +0,0 @@ -package grails.gorm.tests - -/** - * Transaction tests. - */ -class WithTransactionSpec extends GormDatastoreSpec { - - void "Test save() with transaction"() { - given: - TestEntity.withTransaction { - new TestEntity(name:"Bob", age:50, child:new ChildEntity(name:"Bob Child")).save() - new TestEntity(name:"Fred", age:45, child:new ChildEntity(name:"Fred Child")).save() - } - - when: - int count = TestEntity.count() -// def results = TestEntity.list(sort:"name") // TODO this fails but doesn't appear to be tx-related, so manually sorting - def results = TestEntity.list().sort { it.name } - - then: - 2 == count - "Bob" == results[0].name - "Fred" == results[1].name - } - - void "Test rollback transaction"() { - given: - TestEntity.withNewTransaction { status -> - new TestEntity(name:"Bob", age:50, child:new ChildEntity(name:"Bob Child")).save() - status.setRollbackOnly() - new TestEntity(name:"Fred", age:45, child:new ChildEntity(name:"Fred Child")).save() - } - - when: - int count = TestEntity.count() - def results = TestEntity.list() - - then: - count == 0 - results.size() == 0 - } - - void "Test rollback transaction with Exception"() { - given: - def ex - try { - TestEntity.withNewTransaction { status -> - new TestEntity(name:"Bob", age:50, child:new ChildEntity(name:"Bob Child")).save() - throw new RuntimeException("bad") - new TestEntity(name:"Fred", age:45, child:new ChildEntity(name:"Fred Child")).save() - } - } - catch (e) { - ex = e - } - - when: - int count = TestEntity.count() - def results = TestEntity.list() - - then: - count == 0 - results.size() == 0 - ex instanceof RuntimeException - ex.message == 'bad' - } -} 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 725fbaf53..000000000 --- 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-tck/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/BeforeValidateHelper.groovy b/grails-datastore-gorm-tck/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/BeforeValidateHelper.groovy deleted file mode 100644 index 024adef30..000000000 --- a/grails-datastore-gorm-tck/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/metaclass/BeforeValidateHelper.groovy +++ /dev/null @@ -1,9 +0,0 @@ -package org.codehaus.groovy.grails.orm.hibernate.metaclass -/** - * Here as a stub for running older code - * - * @deprecated Use {@link org.grails.datastore.gorm.support.BeforeValidateHelper} - * @author Graeme Rocher - */ -class BeforeValidateHelper extends org.grails.datastore.gorm.support.BeforeValidateHelper{ -} diff --git a/grails-datastore-gorm-test/build.gradle b/grails-datastore-gorm-test/build.gradle deleted file mode 100644 index 91bd3e0e4..000000000 --- a/grails-datastore-gorm-test/build.gradle +++ /dev/null @@ -1,34 +0,0 @@ -dependencies { - def excludes = { - exclude group:"org.grails",module: "grails-plugin-url-mappings" - exclude group:"org.grails",module: "grails-plugin-servlets" - exclude group:"org.grails",module: "grails-plugin-controllers" - exclude group:"org.grails",module: "grails-plugin-domain-class" - exclude group:"org.grails",module: "grails-plugin-gsp" - exclude group:"org.grails",module: "grails-plugin-filters" - exclude group:"org.grails",module: "grails-plugin-mimetypes" - exclude group:"org.grails",module: "grails-plugin-converters" - exclude group:"org.grails",module: "grails-logging" - exclude group:"org.grails",module: "grails-test" - exclude group:"org.grails",module: "grails-datastore-gorm" - exclude group:"org.grails",module: "grails-datastore-core" - exclude group:"org.grails",module: "grails-datastore-simple" - exclude group:"org.grails",module: "grails-datastore-gorm" - } - - compile "org.grails:grails-test:$grailsVersion", excludes - compile "org.grails:grails-plugin-testing:$grailsVersion", excludes - - compile project(":grails-datastore-gorm"), - project(":grails-datastore-simple"), - project(":grails-datastore-core") - - compile "org.grails:grails-test:$grailsVersion",excludes - compile "org.grails:grails-core:$grailsVersion",excludes - compile("org.grails:grails-bootstrap:$grailsVersion",excludes) - - testCompile project(":grails-datastore-gorm-tck") - testRuntime "javax.servlet:servlet-api:2.5" - testRuntime "org.grails:grails-web:$grailsVersion",excludes - testRuntime "log4j:log4j:1.2.16" -} 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 deleted file mode 100644 index 8d1e8a1d0..000000000 --- a/grails-datastore-gorm-test/src/main/groovy/grails/datastore/test/DatastoreUnitTestMixin.groovy +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright (C) 2010 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 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 org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.mapping.core.DatastoreUtils -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.simple.SimpleMapDatastore -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager -import org.grails.datastore.mapping.transactions.SessionHolder -import org.springframework.context.ConfigurableApplicationContext -import org.springframework.context.support.GenericApplicationContext -import org.springframework.transaction.PlatformTransactionManager -import org.springframework.transaction.support.TransactionSynchronizationManager -import org.springframework.util.ClassUtils - -/** - *

    A Groovy mixin used for testing datastore interactions. Test cases should include the mixin using - * the Groovy @Mixin transformation:

    - * - *
    
    - *  @Mixin(DatastoreUnitTestMixin)
    - *  class MyTests {}
    - * 
    - * - *

    - * The {@link DatastoreUnitTestMixin#connect()} method should be called in the test cases setUp() method - * and the {@link DatastoreUnitTestMixin#disconnect()} method on the tearDown() method. - *

    - * - * @author Graeme Rocher - * @since 1.0 - */ -class DatastoreUnitTestMixin { - - static ConfigurableApplicationContext ctx - static SimpleMapDatastore datastore - static { - ctx = new GenericApplicationContext() - ctx.refresh() - datastore = new SimpleMapDatastore(ctx) - ctx.addApplicationListener(new DomainEventListener(datastore)) - ctx.addApplicationListener(new AutoTimestampEventListener(datastore)) - } - - Session session - PlatformTransactionManager transactionManager = new DatastoreTransactionManager(datastore:datastore) - - private mockPluginManager = [hasGrailsPlugin: { String name -> - if (name == "hibernate") { - return ClassUtils.isPresent("org.hibernate.mapping.Value", getClass().getClassLoader()) - } - return true - }] as GrailsPluginManager - - Session connect() { - session = datastore.connect() - def resource = TransactionSynchronizationManager.getResource(datastore) - if (resource == null) { - DatastoreUtils.bindSession session - } - return session - } - - def mockDomain(Class domainClass, List instances = []) { - if (session == null) { - datastore.clearData() - session = DatastoreUtils.getSession(datastore, true) - if (!hasSessionBound()) { - DatastoreUtils.bindSession(session) - } - } - - if (!(PluginManagerHolder.pluginManager instanceof DefaultGrailsPluginManager)) { - PluginManagerHolder.pluginManager = mockPluginManager - } - - def entity = datastore.mappingContext.addPersistentEntity(domainClass) - def enhancer = new GormEnhancer(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 { - it.metaClass = GroovySystem.metaClassRegistry.getMetaClass(domainClass) - session.persist(it) - } - session.flush() - } - - protected boolean hasSessionBound() { - return TransactionSynchronizationManager.getResource(getDatastore()) != null - } - - def disconnect() { - session?.disconnect() - if (PluginManagerHolder.pluginManager?.is(mockPluginManager)) { - PluginManagerHolder.pluginManager = null - } - - datastore.clearData() - if (!hasSessionBound()) { - return - } - - // single session mode - SessionHolder sessionHolder = TransactionSynchronizationManager.unbindResource(getDatastore()) - DatastoreUtils.closeSession(sessionHolder.getSession()) - - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/grails/gorm/tests/JpaQueryBuilderSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/grails/gorm/tests/JpaQueryBuilderSpec.groovy deleted file mode 100644 index 45a65e116..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/grails/gorm/tests/JpaQueryBuilderSpec.groovy +++ /dev/null @@ -1,162 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.DetachedCriteria - -import org.grails.datastore.mapping.query.jpa.JpaQueryBuilder -import org.springframework.dao.InvalidDataAccessResourceUsageException - -/** - * Test for JPA builder - */ -class JpaQueryBuilderSpec extends GormDatastoreSpec{ - - void "Test update query with ilike criterion"() { - given:"Some criteria" - DetachedCriteria criteria = new DetachedCriteria(Person).build { - eq 'age', 10 - ilike 'firstName', 'Bob' - } - - when:"A jpa query is built" - def builder = new JpaQueryBuilder(session.mappingContext.getPersistentEntity(Person.name),criteria.criteria) - def queryInfo = builder.buildUpdate(firstName:"Fred") - - then:"The query is valid" - queryInfo.query == 'UPDATE grails.gorm.tests.Person person SET person.firstName=?1 WHERE (person.age=?2 AND lower(person.firstName) like lower(?3))' - } - - void "Test exception is thrown in join with delete"() { - given:"Some criteria" - DetachedCriteria criteria = new DetachedCriteria(Person).build { - pets { - eq 'name', 'Ted' - } - eq 'firstName', 'Bob' - } - - when:"A jpa query is built" - def builder = new JpaQueryBuilder(session.mappingContext.getPersistentEntity(Person.name),criteria.criteria) - builder.buildDelete() - - then:"The query throws an exception" - def e = thrown(InvalidDataAccessResourceUsageException) - e.message == 'Joins cannot be used in a DELETE or UPDATE operation' - - } - - void "Test build update property natural ordering and hibernate compatible"() { - given:"Some criteria" - DetachedCriteria criteria = new DetachedCriteria(Person).build { - eq 'firstName', 'Bob' - } - - when:"A jpa query is built" - def builder = new JpaQueryBuilder(session.mappingContext.getPersistentEntity(Person.name),criteria.criteria) - builder.hibernateCompatible = true - def queryInfo = builder.buildUpdate(firstName:'Bob updated', age:30) - - then:"The query is valid" - queryInfo.query != null - queryInfo.query == 'UPDATE grails.gorm.tests.Person person SET person.age=?, person.firstName=? WHERE (person.firstName=?)' - queryInfo.parameters == [30,"Bob updated", "Bob"] - } - - void "Test build update property natural ordering"() { - given:"Some criteria" - DetachedCriteria criteria = new DetachedCriteria(Person).build { - eq 'firstName', 'Bob' - } - - when:"A jpa query is built" - def builder = new JpaQueryBuilder(session.mappingContext.getPersistentEntity(Person.name),criteria.criteria) - def queryInfo = builder.buildUpdate(firstName:'Bob updated', age:30) - - then:"The query is valid" - queryInfo.query != null - queryInfo.query == 'UPDATE grails.gorm.tests.Person person SET person.age=?1, person.firstName=?2 WHERE (person.firstName=?3)' - queryInfo.parameters == [30,"Bob updated", "Bob"] - } - - void "Test build update"() { - given:"Some criteria" - DetachedCriteria criteria = new DetachedCriteria(Person).build { - eq 'firstName', 'Bob' - } - - when:"A jpa query is built" - def builder = new JpaQueryBuilder(session.mappingContext.getPersistentEntity(Person.name),criteria.criteria) - def queryInfo = builder.buildUpdate(age:30) - - then:"The query is valid" - queryInfo.query != null - queryInfo.query == 'UPDATE grails.gorm.tests.Person person SET person.age=?1 WHERE (person.firstName=?2)' - queryInfo.parameters == [30, "Bob"] - } - - void "Test build delete"() { - given:"Some criteria" - DetachedCriteria criteria = new DetachedCriteria(Person).build { - eq 'firstName', 'Bob' - } - - when:"A jpa query is built" - def builder = new JpaQueryBuilder(session.mappingContext.getPersistentEntity(Person.name),criteria.criteria) - def queryInfo = builder.buildDelete() - - then:"The query is valid" - queryInfo.query != null - queryInfo.query == 'DELETE grails.gorm.tests.Person person WHERE (person.firstName=?1)' - queryInfo.parameters == ["Bob"] - } - - void "Test build simple select hibernate compatible"() { - given:"Some criteria" - DetachedCriteria criteria = new DetachedCriteria(Person).build { - eq 'firstName', 'Bob' - } - - when:"A jpa query is built" - def builder = new JpaQueryBuilder(session.mappingContext.getPersistentEntity(Person.name),criteria.criteria) - builder.hibernateCompatible = true - def query = builder.buildSelect().query - - then:"The query is valid" - query != null - query == 'SELECT DISTINCT person FROM grails.gorm.tests.Person AS person WHERE (person.firstName=?)' - } - - void "Test build simple select"() { - given:"Some criteria" - DetachedCriteria criteria = new DetachedCriteria(Person).build { - eq 'firstName', 'Bob' - } - - when:"A jpa query is built" - def builder = new JpaQueryBuilder(session.mappingContext.getPersistentEntity(Person.name),criteria.criteria) - def query = builder.buildSelect().query - - then:"The query is valid" - query != null - query == 'SELECT DISTINCT person FROM grails.gorm.tests.Person AS person WHERE (person.firstName=?1)' - } - - void "Test build select with or"() { - given:"Some criteria" - DetachedCriteria criteria = new DetachedCriteria(Person).build { - or { - eq 'firstName', 'Bob' - eq 'firstName', 'Fred' - } - } - - when:"A jpa query is built" - def builder = new JpaQueryBuilder(session.mappingContext.getPersistentEntity(Person.name),criteria.criteria) - final queryInfo = builder.buildSelect() - - then:"The query is valid" - queryInfo.query!= null - queryInfo.query == 'SELECT DISTINCT person FROM grails.gorm.tests.Person AS person WHERE ((person.firstName=?1 OR person.firstName=?2))' - queryInfo.parameters == ['Bob', 'Fred'] - - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy deleted file mode 100644 index 63b81ff03..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy +++ /dev/null @@ -1,9 +0,0 @@ -package grails.gorm.tests - -/** - * @author Burt Beckwith - */ -class OptimisticLockingSpec { - // TODO implement optimistic locking for simple map and delete this - void testNothing() {} -} diff --git a/grails-datastore-gorm-test/src/test/groovy/grails/gorm/tests/SubquerySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/grails/gorm/tests/SubquerySpec.groovy deleted file mode 100644 index e262de8e0..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/grails/gorm/tests/SubquerySpec.groovy +++ /dev/null @@ -1,111 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.DetachedCriteria - -/** - * Tests for using subqueries in criteria and where method calls - * - */ -class SubquerySpec extends GormDatastoreSpec { - - def "Test subquery with projection and criteria with closure"() { - given:"A bunch of people" - createPeople() - - when:"We query for people above a certain age average" - def results = Person.withCriteria { - gt "age", { - projections { - avg "age" - } - } - - order "firstName" - } - - then:"the correct results are returned" - results.size() == 4 - results[0].firstName == "Barney" - results[1].firstName == "Fred" - results[2].firstName == "Homer" - results[3].firstName == "Marge" - } - - def "Test subquery with projection and criteria"() { - given:"A bunch of people" - createPeople() - - when:"We query for people above a certain age average" - def results = Person.withCriteria { - gt "age", new DetachedCriteria(Person).build { - projections { - avg "age" - } - } - - order "firstName" - } - - then:"the correct results are returned" - results.size() == 4 - results[0].firstName == "Barney" - results[1].firstName == "Fred" - results[2].firstName == "Homer" - results[3].firstName == "Marge" - } - - def "Test subquery that returned multiple results and criteria"() { - given:"A bunch of people" - createPeople() - - when:"We query for people above a certain age average" - def results = Person.withCriteria { - gtAll "age", new DetachedCriteria(Person).build { - projections { - property "age" - } - between 'age', 5, 39 - } - - order "firstName" - } - - then:"the correct results are returned" - results.size() == 3 - results[0].firstName == "Fred" - results[1].firstName == "Homer" - results[2].firstName == "Marge" - } - - def "Test subquery that returned multiple results and criteria using a closure" () { - given:"A bunch of people" - createPeople() - - when:"We query for people above a certain age average" - def results = Person.withCriteria { - gtAll "age", { - projections { - property "age" - } - between 'age', 5, 39 - } - - order "firstName" - } - - then:"the correct results are returned" - results.size() == 3 - results[0].firstName == "Fred" - results[1].firstName == "Homer" - results[2].firstName == "Marge" - } - - protected def createPeople() { - new Person(firstName: "Homer", lastName: "Simpson", age:45).save() - new Person(firstName: "Marge", lastName: "Simpson", age:40).save() - new Person(firstName: "Bart", lastName: "Simpson", age:9).save() - new Person(firstName: "Lisa", lastName: "Simpson", age:7).save() - new Person(firstName: "Barney", lastName: "Rubble", age:35).save() - new Person(firstName: "Fred", lastName: "Flinstone", age:41).save() - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/grails/gorm/tests/WhereMethodSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/grails/gorm/tests/WhereMethodSpec.groovy deleted file mode 100644 index 7891010b8..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/grails/gorm/tests/WhereMethodSpec.groovy +++ /dev/null @@ -1,1784 +0,0 @@ -package grails.gorm.tests - -import grails.gorm.DetachedCriteria -import grails.persistence.Entity -import groovy.transform.CompileStatic; - -import org.codehaus.groovy.control.MultipleCompilationErrorsException -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -import spock.lang.Ignore -import spock.lang.Issue - -/** - * Tests for the new where method used to define detached criteria using the new DSL - */ -@ApplyDetachedCriteriaTransform -@Ignore -class WhereMethodSpec extends GormDatastoreSpec { - - def gcl - - @Override - List getDomainClasses() { - def list = [Continent, Group, Proposal, Advisor] - - gcl= new GroovyClassLoader() - list << gcl.parseClass(''' -import grails.gorm.tests.* -import grails.gorm.* -import grails.persistence.* -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -@ApplyDetachedCriteriaTransform -@Entity -class Todo { - Long id - String title - static doStuff() { - where { title == 'blah' } - } -} -''') - - list << gcl.parseClass(''' -import grails.gorm.tests.* -import grails.gorm.* -import grails.persistence.* -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -@ApplyDetachedCriteriaTransform -@Entity -class Project { - Long id - String name - static hasMany =[todos:Todo] - Set todos - - static todosThatStartWithA = where { - todos.title ==~ "A%" - } -} -''') - return list - } - -// TODO: Fix RHS function calls -// @Ignore -// def "Test year function with to-one association"() { -// given:"people and pets" -// createPeopleWithPets() -// -// when:"We use a function with an association query" -// def results = Pet.where { -// owner.age < year(birthDate) -// }.list() -// -// then:"The correct results are returned" -// results.size() > 0 -// } - - def closureProperty = { - Person.where { lastName == "Simpson" }.list() - } - - @Issue('GRAILS-9696') - def "Test that a call to a static find method from within the class resolves correctly"() { - given:"Some people" - createPeople() - - when:"A method is called that calls the find method from within the class" - def bart = Person.getByFirstNameAndLastNameAndAge("Bart", "Simpson", 9) - - then:"The data returned is correct" - bart != null - bart.firstName == "Bart" - } - @Issue('GRAILS-8256') - def "Test query with 3 level deep domain association"() { - given:"create people and faces" - createPeopleWithFaces() - - when:"A query that uses criteria 2 levels deep is executed" - def results = Nose.withCriteria { - face { person { eq 'lastName', 'Simpson' } } - } - - then:"The results are correct" - results.size() == 4 - - when:"A query that queries an association 2 levels deep is executed" - def query = Nose.where { - face.person.lastName == "Simpson" - } - - then:"The correct results are returned" - query.count() == 4 - - when:"A query that queries an association 2 levels deep is executed via nesting" - query = Nose.where { - face { person { lastName == "Simpson" } } - } - - then:"The correct results are returned" - query.count() == 4 - } - - private createPeopleWithFaces() { - final h = new Person(firstName: "Homer", lastName: "Simpson", age: 45) - h.face = new Face(name: "Homer", nose: new Nose(), person: h ) - h.save() - final m = new Person(firstName: "Marge", lastName: "Simpson", age: 40) - m.face = new Face(name: "Marge", nose: new Nose(), person: m) - m.save() - - final b = new Person(firstName: "Bart", lastName: "Simpson", age: 9) - b.face = new Face(name: "Bart", nose: new Nose(hasFreckles: true), person: b) - b.save() - - final l = new Person(firstName: "Lisa", lastName: "Simpson", age: 7) - l.face = new Face(name: "Lisa", nose: new Nose(hasFreckles: true), person: l) - l.save() - - final ba = new Person(firstName: "Barney", lastName: "Rubble", age: 35) - ba.face = new Face(name: "Barney", nose: new Nose()) - ba.save() - - assert Person.count() == 5 - assert Face.count() == 5 - - } - - @Issue('GRAILS-8256') - def "Test query with 3 level deep collection association"() { - given:"some people with pets in groups" - createPeopleInGroupsWithPets() - - when:"A query that uses criteria 2 levels deep is executed" - def results = Group.withCriteria { - people { pets { eq 'name', 'Jack' } } - } - - then:"The results are correct" - results.size() == 1 - when:"A query that queries an association 2 levels deep is executed" - def query = Group.where { - people.pets.name == "Jack" - } - - then:"The correct results are returned" - query.count() == 1 - - when:"A query that queries an association 2 levels deep is executed via nesting" - query = Group.where { - people { pets { name == "Jack" } } - } - - then:"The correct results are returned" - query.count() == 1 - } - - @Issue('GRAILS-8366') - def "Test calling method on RHS of collection size() query"() { - given:"some people and pets" - createPeopleWithPets() - - when:"A query that inspects the size() of a collection and calls a method on the RHS is called" - def query = Person.where { - pets.size() == processPetSize(3) - } - - then:"The query returns the correct results" - query.count() == 1 - } - - private processPetSize(int size) { size } - - def "Test error when using incorrect property of a to-one association"() { - when:"A an unknown domain class property is referenced" - queryUsingUnknownToOneAssociationProperty() - then: - MultipleCompilationErrorsException e = thrown() - e.message.contains 'Cannot query property "firstN" - no such property on class grails.gorm.tests.Person exists.' - } - - @Issue('GRAILS-9425') - def "Test that static definition of where query works with associations"() { - given:"given a project and some todos" - def Todo = this.gcl.loadClass("Todo") - def Project = this.gcl.loadClass("Project") - - Project.newInstance(name: "Foo").save() - Project.newInstance(name: "Bar") - .addToTodos(title:"A todo") - .addToTodos(title:"Another") - .save(flush: true) - - session.clear() - - when:"a statically defined where query is used" - def results = Project.todosThatStartWithA.list() - - then:"The correct results are returned" - results.size() == 1 - } - - @Issue('GRAILS-8526') - def "Test association query with referenced arguments"() { - given:"some people and pets" - createPeopleWithPets() - - when:"A query is built from arguments to a method" - def q = getSomePets(name: "Ed") - def results = q.list() - - then:"The results are correct" - results.size() == 3 - } - - def "Test a static method that calls where"() { - - when:"a static method call, calls into where" - def Todo = this.gcl.loadClass("Todo") - Todo.newInstance(title:"blah").save() - Todo.newInstance(title:"two").save(flush:true) - def query = Todo.doStuff() - - then:"The query is valid" - query != null - Todo.count() == 2 - query.count() == 1 - query.find().title == 'blah' - } - - private getSomePets(args) { - Pet.where { - owner.firstName == args.name - } - } - - @Issue('GRAILS-9471') - def "Test chaining where queries directly"() { - given:"Some people" - createPeople() - - when:"2 where queries are combined in a sequence" - def results = Person.where { lastName == 'Simpson' }.where { firstName == 'Bart'}.list() - - then:"The correct results are returned" - results.size() == 1 - results[0].firstName == 'Bart' - } - - @Issue('GRAILS-9447') - def "Test where query integer type conversion"() { - given:"some people" - createPeopleWithPets() - - when:"A where query is used with an integer value and a long property type" - def results = Pet.where { owner.id == 2 }.list() - - then:"The correct results are returned and type conversion happens as expected" - results.size() == 3 - results[0].id == 3 - } - - def "Test where query inside closure property declaration"() { - given:"some people" - createPeople() - - when:"A query is created in a closure property" - def results = closureProperty.call() - - then:"The correct results are returned" - results.size() == 4 - results.every { it.lastName == "Simpson" } - } - - def "Test captured detached criteria instance" () { - given:"people and pets" - createPeopleWithPets() - - when:"Another detached criteria variable is captured" - def pets = Pet.where { - name ==~ "J%" - } - - def owners = Person.where { - pets.size() == 2 - } - - then:"The results are valid" - owners.count() == 2 - } - - def "Test whereAny method"() { - given:"some people" - createPeople() - - when:"An or is used in a where query" - def people = Person.whereAny { - firstName == "Homer" - firstName == "Bart" - }.list(sort:"firstName") - - then:"The right results are returned" - people.size() == 2 - people[0].firstName == "Bart" - people[1].firstName == "Homer" - } - - def "Test where query that uses a captured variable inside an association query"() { - given:"people and pets" - createPeopleWithPets() - - when:"A where query that queries an association from a captured variable is used" - def fn = "Joe" - def pets = Pet.where { - owner { firstName == fn } - }.list() - - then:"The correct result is returned" - pets.size() == 2 - } - - def "Test where with multiple property projections using chaining"() { - given:"A bunch of people" - createPeople() - - when:"Multiple property projections are used" - def people = Person.where { lastName == "Simpson" } - def results = people.property("lastName").property('firstName').list() - - then:"The correct results are returned" - results == [["Simpson", "Homer"], ["Simpson", "Marge"], ["Simpson", "Bart"], ["Simpson", "Lisa"]] - } - - def "Test where with multiple property projections"() { - given:"A bunch of people" - createPeople() - - when:"Multiple property projections are used" - def people = Person.where { lastName == "Simpson" } - def results = people.projections { - property "lastName" - property "firstName" - }.list() - - then:"The correct results are returned" - results == [["Simpson", "Homer"], ["Simpson", "Marge"], ["Simpson", "Bart"], ["Simpson", "Lisa"]] - } - - def "Test parameterized where query"() { - given:"A bunch of people" - createPeople() - - when:"parameters are used instead of literals" - def fn = "Bart" - def ln = "Simpson" - - def query = Person.where { firstName != fn && lastName == ln }.sort("firstName", "desc") - def people = query.list() - - then:"The correct results are returned" - people.size() == 3 - } - - def "Test is null query"() { - given:"A bunch of people" - createPeople() - - when:"We query for a property to be null" - def query = Person.where { - firstName == null - } - - then:"the right results are returned" - query.count() == 0 - } - - def "Test subquery defined as closure"() { - given:"A bunch of people" - createPeople() - - when:"use a subquery with additional criterion " - def query = Person.where { - age > avg(age).of { lastName == "Simpson" } && firstName == "Homer" - } - - def results = query.list(sort:"firstName") - - then:"The expected result is returned" - results.size() == 1 - results[0].firstName == "Homer" - } - - def "Test function execution"() { - given:"A bunch of people with pets" - createPeopleWithPets() - def p = new Person(firstName: "Old", lastName: "Person").save() - new Pet(owner:p, birthDate: new GregorianCalendar(2009,1, 1).time, name:"Old Dog").save() - - when:"A function is used on the property" - def query = Pet.where { - year(birthDate) == 2011 - } - def results = query.list() - - then:"check that the results are correct" - results.size() == 7 - - when:"A function is used on the property" - query = Pet.where { - year(birthDate) == 2009 - } - results = query.list() - - then:"check that the results are correct" - results.size() == 1 - results[0].name == "Old Dog" - - when:"A function is used on an association" - query = Person.where { - year(pets.birthDate) == 2009 - } - results = query.list() - - then:"The correct results are returned" - results.size() == 1 - results[0].firstName == "Old" - } - - def "Test in range query"() { - given:"A bunch of people" - createPeople() - - when:"a query is composed" - def query = Person.where { - age in 1..15 - } - - def results = query.list(sort:"firstName") - - then:"The expected result is returned" - results.size() == 2 - results[0].firstName == "Bart" - results[1].firstName == "Lisa" - } - def "Test compose query"() { - given:"A bunch of people" - createPeople() - - when:"a query is composed" - def query = Person.where { - lastName == "Simpson" - } - def bartQuery = query.where { - firstName == "Bart" - } - Person p = bartQuery.find() - - then:"The expected result is returned" - p != null - p.firstName == "Bart" - } - def "Test static scoped where calls"() { - given:"A bunch of people" - createPeople() - - when:"We use the static simpsons property " - def simpsons = Person.simpsons - - then:"We get the right results back" - simpsons.count() == 4 - - when:"We apply further where criteria to static scoped where call" - def query = Person.simpsons.where { - firstName == "Bart" - } - Person p = query.find() - - then:"The correct results are returned" - p != null - p.firstName == "Bart" - } - def "Test findAll with pagination params"() { - given:"A bunch of people" - createPeople() - - when:"We use findAll with pagination params" - def results = Person.findAll(sort:"firstName") { - lastName == "Simpson" - } - - then:"The correct results are returned" - results != null - results.size() == 4 - results[0].firstName == "Bart" - } - - @Issue('GRAILS-9658') - def "Test findAll with assocation query"() { - - when:"We use findAll is called with an association" - def results = getClassThatCallsWhere().doQuery() -// def session = [user: [username:"Fred"]] -// def results = Proposal.findAll { advisor.username == session.user.username && approvalDate != null } - - then:"The correct results are returned" - results != null - } - - def "Test try catch finally"() { - given:"A bunch of people" - createPeople() - - when:"We use a try catch finally block in a where query" - def query = Person.where { - def personAge = "nine" - try { - age == personAge.toInteger() - } - catch(e) { - age == 7 - } - finally { - lastName == "Simpson" - } - } - Person result = query.find() - - then:"The correct results are returned" - result != null - result.firstName == "Lisa" - } - def "Test while loop"() { - given:"A bunch of people" - createPeople() - - when:"We use a while loop in a where query" - def query = Person.where { - def list = ["Bart", "Simpson"] - int total = 0 - while(total < list.size()) { - def name = list[total++] - if (name == "Bart") - firstName == name - else - lastName == "Simpson" - } - } - Person result = query.find() - - then:"The correct results are returned" - result != null - result.firstName == "Bart" - } - def "Test for loop"() { - given:"A bunch of people" - createPeople() - - when:"We use a for loop in a query" - def query = Person.where { - for (name in ["Bart", "Simpson"]) { - if (name == "Bart") - firstName == name - else - lastName == "Simpson" - } - } - Person result = query.find() - - then:"The correct results are returned" - result != null - result.firstName == "Bart" - } - def "Test criteria on single ended association"() { - given:"people and pets" - createPeopleWithPets() - - when:"We query the single-ended association owner of pet" - def query = Pet.where { - owner.firstName == "Joe" || owner.firstName == "Fred" - } - - then:"the correct results are returned" - query.count() == 4 - } - -// def "Test comparing property with single ended association"() { -// given:"people and pets" -// createPeopleWithPets() -// -// when:"We query a property against the property of a single-ended association" -// def query = Pet.where { -// name == owner.firstName -// } -// -// then:"the correct results are returned" -// query.count() == 0 -// } - - def "Test ilike operator"() { - given:"A bunch of people" - createPeople() - - when:"We query for people whose first names start with the letter B in lower case" - def query = Person.where { - firstName =~ "b%" - } - def results = query.list(sort:'firstName') - - then:"The correct results are returned" - results.size() == 2 - results[0].firstName == "Barney" - results[1].firstName == "Bart" - - } - def "Test switch statement"() { - given: "A bunch of people" - createPeople() - - when: "A where query is used with a switch statement" - int count = 2 - def query = Person.where { - switch (count) { - case 1: - firstName == "Bart" - break - case 2: - firstName == "Lisa" - break - case 3: - firstName == "Marge" - - } - } - def result = query.find() - - then: "The correct result is returned" - result != null - result.firstName == "Lisa" - } - def "Test where blocks on detached criteria"() { - given:"A bunch of people" - createPeople() - - when:"A where block is used on a detached criteria instance" - DetachedCriteria dc = new DetachedCriteria(Person) - dc = dc.where { - firstName == "Bart" - } - def result = dc.find() - - then:"The correct results are returned" - result != null - result.firstName == "Bart" - } - def "Test local declaration inside where method"() { - given:"A bunch of people" - createPeople() - - when: "A where query is used with if statement" - - def query = Person.where { - def useBart = true - firstName == (useBart ? "Bart" : "Homer") - } - def result = query.find() - - then:"The correct result is returned" - - result != null - result.firstName == "Bart" - } - - def "Test where method with ternary operator"() { - given:"A bunch of people" - createPeople() - - when: "A where query is used with if statement" - def useBart = true - def query = Person.where { - firstName == (useBart ? "Bart" : "Homer") - } - def result = query.find() - - then:"The correct result is returned" - - result != null - result.firstName == "Bart" - } - def "Test where method with if else block"() { - given:"A bunch of people" - createPeople() - - when: "A where query is used with if statement" - def useBart = true - def query = Person.where { - if (useBart) - firstName == "Bart" - else - firstName == "Homer" - } - def result = query.find() - - then:"The correct result is returned" - - result != null - result.firstName == "Bart" - - when: "A where query is used with else statement" - useBart = false - query = Person.where { - if (useBart) - firstName == "Bart" - else - firstName == "Marge" - } - result = query.find() - - then:"The correct result is returned" - - result != null - result.firstName == "Marge" - - when: "A where query is used with else statement" - useBart = false - int count = 1 - query = Person.where { - if (useBart) - firstName == "Bart" - else if (count == 1) { - firstName == "Lisa" - } - else - firstName == "Marge" - } - result = query.find() - - then:"The correct result is returned" - - result != null - result.firstName == "Lisa" - } - - def "Test collection operations"() { - given:"People with pets" - createPeopleWithPets() - - when:"We query for people with 2 pets" - def query = Person.where { - pets.size() == 2 - } - def results = query.list(sort:"firstName") - - then:"The correct results are returned" - results.size() == 2 - results[0].firstName == "Fred" - results[1].firstName == "Joe" - - when:"We query for people with greater than 2 pets" - query = Person.where { - pets.size() > 2 - } - results = query.list(sort:"firstName") - then:"The correct results are returned" - results.size() == 1 - results[0].firstName == "Ed" - - when:"We query for people with greater than 2 pets" - query = Person.where { - pets.size() > 1 && firstName != "Joe" - } - results = query.list(sort:"firstName") - then:"The correct results are returned" - results.size() == 2 - results[0].firstName == "Ed" - results[1].firstName == "Fred" - } - - def "Test subquery usage combined with property"() { - given:"a bunch of people" - createPeople() - - when:"We query for people greater that all defined ages" - final query = Person.where { - age > property(age) - } - def results = query.list(sort:"firstName") - - then:"The correct results are returned" - results.size() == 0 - } - - def "Test subquery usage combined with logical query"() { - given:"a bunch of people" - createPeople() - - when:"We query for people greater than an average age" - final query = Person.where { - age > avg(age) && firstName != "Marge" - } - def results = query.list(sort:"firstName") - - then:"The correct results are returned" - results.size() == 3 - results[0].firstName == "Barney" - results[1].firstName == "Fred" - results[2].firstName == "Homer" - } - - def "Test subquery usage"() { - given:"a bunch of people" - createPeople() - - when:"We query for people greater than an average age" - final query = Person.where { - age > avg(age) - } - def results = query.list(sort:"firstName") - - then:"The correct results are returned" - results.size() == 4 - results[0].firstName == "Barney" - results[1].firstName == "Fred" - results[2].firstName == "Homer" - results[3].firstName == "Marge" - } - - def "Test error when using negating a non-binary expression"() { - when:"A an unknown domain class property is referenced" - queryUsingInvalidNegation() - then: - MultipleCompilationErrorsException e = thrown() - e.message.contains 'You can only negate a binary expressions in queries.' - } - - def "Test error when using unsupported operator in size() query"() { - when:"A an unknown domain class property is referenced" - queryUsingUnsupportedOperatorInSize() - then: - MultipleCompilationErrorsException e = thrown() - e.message.contains 'Unsupported operator [<<] used in size() query' - } - - def "Test error when using unknown property in size() query"() { - when:"A an unknown domain class property is referenced" - queryUsingUnknownPropertyWithSize() - then: - MultipleCompilationErrorsException e = thrown() - e.message.contains 'Cannot query size of property "blah" - no such property on class grails.gorm.tests.Person exists' - } - - def "Test error when using unsupported operator"() { - when:"A an unsupported query operator is used" - queryUsingUnsupportedOperator() - then: - MultipleCompilationErrorsException e = thrown() - e.message.contains 'Unsupported operator [<<] used in query' - } - - def "Test error when using unknown domain property of an association"() { - when:"A an unknown domain class property of an association is referenced" - queryReferencingNonExistentPropertyOfAssociation() - then: - MultipleCompilationErrorsException e = thrown() - e.message.contains 'Cannot query on property "doesntExist" - no such property on class grails.gorm.tests.Pet exists.' - } - - def "Test error when using unknown domain property"() { - when:"A an unknown domain class property is referenced" - queryReferencingNonExistentProperty() - then: - MultipleCompilationErrorsException e = thrown() - e.message.contains 'Cannot query on property "doesntExist" - no such property on class grails.gorm.tests.Person exists.' - } - - def "Test error when using function on property of a to-one association"() { - when:"A function is used on a property expression" - queryUsingFunctionOnToOneAssociationProperty() - then: - MultipleCompilationErrorsException e = thrown() - e.message.contains 'Cannot use aggregate function avg on expressions "owner.age"' - } - - String nameBart() { "Bart" } - def "Test where method with value obtained via method call"() { - given:"A bunch of people" - createPeople() - - when:"We find a person where first name is obtained via method call" - Person p = Person.find { firstName == nameBart() } - - then:"The expected result is returned" - p != null - p.firstName == "Bart" - } - - def "Test second where declaration on detached criteria instance"() { - given:"A bunch of people" - createPeople() - - when:"We create a 2 where queries, one derived from the other" - def q1 = Person.where { - lastName == "Simpson" - } - - def q2 = q1.where { - firstName == "Bart" - } - - then:"The first query is not modified, and the second works as expected" - q1.count() == 4 - q2.count() == 1 - } - - def "Test query association"() { - given:"People with a few pets" - createPeopleWithPets() - - when:"We query for people by Pet using a simple equals query" - - def query = Person.where { - pets.name == "Butch" - } - def count = query.count() - def result = query.find() - - then:"The expected result is returned" - count == 1 - result != null - result.firstName == "Joe" - - when:"We query for people by Pet with multiple results" - query = Person.where { - pets.name ==~ "B%" - } - count = query.count() - def results = query.list(sort:"firstName") - - then:"The expected results are returned" - count == 2 - results[0].firstName == "Ed" - results[1].firstName == "Joe" - } - - def "Test query association with or"() { - given:"People with a few pets" - createPeopleWithPets() - - when:"We use a logical or to query people by pets" - def query = Person.where { - pets { name == "Jack" || name == "Joe" } - } - def count = query.count() - def results = query.list(sort:"firstName") - - then:"The expected results are returned" - count == 2 - results[0].firstName == "Fred" - results[1].firstName == "Joe" - - when:"We use a logical or to query pets combined with another top-level logical expression" - query = Person.where { - pets { name == "Jack" } || firstName == "Ed" - } - count = query.count() - results = query.list(sort:"firstName") - - then:"The correct results are returned" - count == 2 - results[0].firstName == "Ed" - results[1].firstName == "Joe" - } - - def "Test findAll method for inline query"() { - given:"A bunch of people" - createPeople() - - when:"We find a person where first name is Bart" - List people = Person.findAll { lastName == "Simpson" } - - then:"The expected result is returned" - people.size() == 4 - } - - def "Test find method for inline query"() { - given:"A bunch of people" - createPeople() - - when:"We find a person where first name is Bart" - Person p = Person.find { firstName == "Bart" } - - then:"The expected result is returned" - p != null - p.firstName == "Bart" - } - - def "Test use property declared as detached criteria"() { - given:"A bunch of people" - createPeople() - - when:"A closure is declared as detached criteria and then passed to where" - - def query = getClassThatCallsWhere().declaredQuery() - Person p = query.find() - - then:"The right result is returned" - p != null - p.firstName == "Bart" - } - - def "Test declare closure as detached criteria"() { - given:"A bunch of people" - createPeople() - - when:"A closure is declared as detached criteria and then passed to where" - def callable = { firstName == "Bart" } as DetachedCriteria - def query = Person.where(callable) - Person p = query.find() - - then:"The right result is returned" - p != null - p.firstName == "Bart" - - } - - def "Test query using captured variables"() { - given:"A bunch of people" - createPeople() - - when:"We query with variable captured from outside the closures scope" - def params = [firstName:"Bart"] - def query = Person.where { - firstName == params.firstName - } - def count = query.count() - Person p = query.find() - - then:"The correct results are returned" - count == 1 - p != null - p.firstName == "Bart" - } - def "Test negation query"() { - given:"A bunch of people" - createPeople() - - when:"A single criterion is negated" - def query = Person.where { - !(lastName == "Simpson") - } - def results = query.list(sort:"firstName") - - then:"The right results are returned" - results.size() == 2 - - when:"Multiple criterion are negated" - - query = Person.where { - !(firstName == "Fred" || firstName == "Barney") - } - results = query.list(sort:"firstName") - - then:"The right results are returned" - results.every { it.lastName == "Simpson" } - - when:"Negation is combined with non-negation" - - query = Person.where { - firstName == "Fred" && !(lastName == 'Simpson') - } - Person result = query.find() - - then:"The correct results are returned" - result != null - result.firstName == "Fred" - - when:"Negation is combined with non-negation" - - query = Person.where { - !(firstName == "Homer") && lastName == 'Simpson' - } - results = query.list(sort:"firstName") - - then:"The correct results are returned" - results.size() == 3 - results[0].firstName == "Bart" - results[1].firstName == "Lisa" - results[2].firstName == "Marge" - } - - def "Test query association with logical or"() { - given:"People with a few pets" - createPeopleWithPets() - - when:"We use a logical or to query people by pets" - def query = Person.where { - pets.name == "Jack" || pets.name == "Joe" - } - - def count = query.count() - def results = query.list(sort:"firstName") - - then:"The expected results are returned" - count == 2 - results[0].firstName == "Fred" - results[1].firstName == "Joe" - } - - def "Test eqProperty query"() { - given:"A bunch of people" - createPeople() - new Person(firstName: "Frank", lastName: "Frank").save() - - when:"We query for a person with the same first name and last name" - def query = Person.where { - firstName == lastName - } - Person result = query.get() - int count = query.count() - - then:"The correct result is returned" - result != null - count == 1 - result.firstName == "Frank" - - } - - @Ignore // rlike not suppported by all datastores yet - def "Test rlike query"() { - given:"A bunch of people" - createPeople() - - when:"We query for people whose first names start with the letter B" - def query = Person.where { - firstName ==~ ~/B.+/ - } - def results = query.list(sort:'firstName') - - then:"The correct results are returned" - results.size() == 2 - results[0].firstName == "Barney" - results[1].firstName == "Bart" - } - - def "Test like query"() { - given:"A bunch of people" - createPeople() - - when:"We query for people whose first names start with the letter B" - def query = Person.where { - firstName ==~ "B%" - } - def results = query.list(sort:'firstName') - - then:"The correct results are returned" - results.size() == 2 - results[0].firstName == "Barney" - results[1].firstName == "Bart" - } - - def "Test in list query"() { - given:"A bunch of people" - createPeople() - - when:"We query for people in a list" - def query = Person.where { - firstName in ["Bart", "Homer"] - } - def results = query.list(sort:'firstName') - - then:"The correct results are returned" - results.size() == 2 - results[0].firstName == "Bart" - results[1].firstName == "Homer" - } - - def "Test less than or equal to query"() { - given:"A bunch of people" - createPeople() - - when:"We query for people older than 30" - def query = Person.where { - age <= 35 - } - def results = query.list(sort:'firstName') - - then:"The correct results are returned" - results.size() == 3 - results[0].firstName == "Barney" - results[1].firstName == "Bart" - results[2].firstName == "Lisa" - - when:"A greater than query is combined with an equals query" - query = Person.where { - age <= 35 && lastName == 'Simpson' - } - results = query.list(sort:'firstName') - - then:"The correct results are returned" - - results.size() == 2 - results[0].firstName == "Bart" - results[1].firstName == "Lisa" - } - - def "Test greater than or equal to query"() { - given:"A bunch of people" - createPeople() - - when:"We query for people older than 30" - def query = Person.where { - age >= 35 - } - def results = query.list(sort:'firstName') - - then:"The correct results are returned" - results.size() == 4 - results[0].firstName == "Barney" - results[1].firstName == "Fred" - results[2].firstName == "Homer" - results[3].firstName == "Marge" - - when:"A greater than query is combined with an equals query" - query = Person.where { - age >= 35 && lastName == 'Simpson' - } - results = query.list(sort:'firstName') - - then:"The correct results are returned" - - results.size() == 2 - results[0].firstName == "Homer" - results[1].firstName == "Marge" - } - - def "Test less than query"() { - given:"A bunch of people" - createPeople() - - when:"We query for people younger than 30" - def query = Person.where { - age < 30 - } - def results = query.list(sort:'firstName') - - then:"The correct results are returned" - results.size() == 2 - results[0].firstName == "Bart" - results[1].firstName == "Lisa" - - when:"A greater than query is combined with an equals query" - query = Person.where { - age < 30 && firstName == 'Bart' - } - results = query.list(sort:'firstName') - - then:"The correct results are returned" - - results.size() == 1 - results[0].firstName == "Bart" - } - - def "Test greater than query"() { - given:"A bunch of people" - createPeople() - - when:"We query for people older than 30" - def query = Person.where { - age > 35 - } - def results = query.list(sort:'firstName') - - then:"The correct results are returned" - results.size() == 3 - results[0].firstName == "Fred" - results[1].firstName == "Homer" - results[2].firstName == "Marge" - - when:"A greater than query is combined with an equals query" - query = Person.where { - age > 35 && lastName == 'Simpson' - } - results = query.list(sort:'firstName') - - then:"The correct results are returned" - - results.size() == 2 - results[0].firstName == "Homer" - results[1].firstName == "Marge" - } - - def "Test nested and or query"() { - given:"A bunch of people" - createPeople() - - when: "A where query is used" - def query = Person.where { - (lastName != "Simpson" && firstName != "Fred") || firstName == "Bart" - } - def results = query.list(sort:"firstName") - - then:"The correct result is returned" - results.size() == 2 - results[0].firstName == "Barney" - results[1].firstName == "Bart" - } - - def "Test not equal query"() { - given:"A bunch of people" - createPeople() - - when: "A where query is used" - def query = Person.where { - lastName != "Simpson" - } - def results = query.list(sort:"firstName") - - then:"The correct result is returned" - results.size() == 2 - results[0].firstName == "Barney" - results[1].firstName == "Fred" - } - - def "Test basic binary criterion where call"() { - given:"A bunch of people" - createPeople() - - when: "A where query is used" - def query = Person.where { - firstName == "Bart" && lastName == "Simpson" - } - def result = query.get() - - then:"The correct result is returned" - result != null - result.firstName == "Bart" - } - - def "Test basic single criterion where call"() { - given:"A bunch of people" - createPeople() - - when: "A where query is used" - def query = Person.where { - firstName == "Bart" - } - def result = query.get() - - then:"The correct result is returned" - - result != null - result.firstName == "Bart" - - } - - def "Test query association on inherited property"() { - given:"People in countries" - createContinentWithCountries() - - when:"A where query is used" - def query = Continent.where { - countries { name == 'SA'} - } - - then:"The correct resulted are returned" - query.count() == 1 - - } - - def "Test where query with overlapping parameter and property names with association query"() { - given:"some people" - createPeopleWithPets() - - when:"A variable is declared that overlaps with a property of the class" - def age = 10 - def pets = [] - def query = Person.where { - pets.age == age - } - def results = query.list() - - then:"The variable takes precedence" - query.count() == 2 - results.find { it.firstName == 'Joe'} - results.find { it.firstName == 'Ed'} - } - - def "Test where query with overlapping parameter and property names"() { - given:"some people" - createPeopleWithPets() - - when:"A variable is declared that overlaps with a property of the class" - def age = 5 - def pets = [] - def query = Person.where { - age > age && pets { age > age} - } - def results = query.list() - - then:"The variable takes precedence" - query.count() == 2 - results.find { it.firstName == 'Ed'} - results.find { it.firstName == 'Fred'} - } - - def "Test where query on sorted set"() { - given:"Some people and groups" - createPeopleAndGroups() - - when:"A where query is executed on a sorted set" - def query = Group.where { - people.lastName == "Simpson" - } - def results = query.list(sort:"name", order:"desc") - - then:"The results are correct" - results.size() == 1 - } - - @Issue('GRAILS-9996') - void "test static where queries and CompileStatic"() { - given:"A bunch of people" - createPeople() - when: - Person person = findHomerWithStaticWhereAndCompileStatic() - then: - person.firstName == "Homer" - } - - @Issue('GRAILS-9996') - void "test where queries and CompileStatic"() { - given:"A bunch of people" - createPeople() - when: - Person person = DetachedCriteriaInnerClass.findHomerWithWhereAndCompileStatic() - then: - person.firstName == "Homer" - - } - - @CompileStatic - static Person findHomerWithStaticWhereAndCompileStatic() { - List results = Person.simpsons.list(max: 2) - results[0] - } - - // TODO: Issue GRAILS-9996 hasn't been solved yet, this breaks with @CompileStatic - //@CompileStatic - @ApplyDetachedCriteriaTransform - static class DetachedCriteriaInnerClass { - static Person findHomerWithWhereAndCompileStatic() { - List results = Person.where { lastName == 'Simpson' }.list(max: 2) - results[0] - } - } - - protected createContinentWithCountries() { - final continent = new Continent(name: "Africa") - continent.countries << new Country(name:"SA", population:304830) << new Country(name:"Zim", population:304830) - assert continent.save(flush:true) != null - } - protected def createPeople() { - new Person(firstName: "Homer", lastName: "Simpson", age:45).save() - new Person(firstName: "Marge", lastName: "Simpson", age:40).save() - new Person(firstName: "Bart", lastName: "Simpson", age:9).save() - new Person(firstName: "Lisa", lastName: "Simpson", age:7).save() - new Person(firstName: "Barney", lastName: "Rubble", age:35).save() - new Person(firstName: "Fred", lastName: "Flinstone", age:41).save() - } - - protected def createPeopleAndGroups() { - createPeople() - def simpsons = Person.findAllByLastName("Simpson") - assert simpsons.size() == 4 - def s = new Group(name: "Simpsons") - s.people.addAll(simpsons) - s.save flush: true - session.clear() - - assert Group.findByName("Simpsons").people.size() == 4 - } - - protected def createPeopleInGroupsWithPets() { - createPeopleWithPets() - def peopleWith2Pets = Person.findAllByLastNameOrLastName("Bloggs", "Cloggs") - assert peopleWith2Pets.size() == 2 - def s = new Group(name: "2 Pets") - s.people.addAll(peopleWith2Pets) - s.save flush: true - - def peopleWith3Pets = Person.findAllByLastName("Floggs") - assert peopleWith3Pets.size() == 1 - s = new Group(name: "3 Pets") - s.people.addAll(peopleWith3Pets) - s.save flush: true - - session.clear() - - assert Group.findByName("2 Pets").people.size() == 2 - assert Group.findByName("3 Pets").people.size() == 1 - } - - protected def createPeopleWithPets() { - new Person(firstName: "Joe", lastName: "Bloggs", age:4) - .addToPets(name: "Jack", age: 5, birthDate: new GregorianCalendar(2011,1, 1).time) - .addToPets(name: "Butch", age: 10, birthDate: new GregorianCalendar(2011,1, 1).time) - .save() - - new Person(firstName: "Ed", lastName: "Floggs", age: 6) - .addToPets(name: "Mini", age: 10, birthDate: new GregorianCalendar(2011,1, 1).time) - .addToPets(name: "Barbie", age: 4, birthDate: new GregorianCalendar(2011,1, 1).time) - .addToPets(name:"Ken", birthDate: new GregorianCalendar(2011,1, 1).time) - .save() - - new Person(firstName: "Fred", lastName: "Cloggs", age: 12) - .addToPets(name: "Jim", age: 2, birthDate: new GregorianCalendar(2011,1, 1).time) - .addToPets(name: "Joe", age: 9, birthDate: new GregorianCalendar(2011,1, 1).time) - .save() - } - - def queryUsingFunctionOnToOneAssociationProperty() { - def gcl = new GroovyClassLoader(getClass().classLoader) - gcl.parseClass(''' -import grails.gorm.tests.* -import grails.gorm.* -import grails.persistence.* -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -@ApplyDetachedCriteriaTransform -@Entity -class CallMe { - def badQuery() { - Pet.where { - owner.age > avg(owner.age) - } - } -} -''') - } - - def queryUsingUnknownToOneAssociationProperty() { - def gcl = new GroovyClassLoader(getClass().classLoader) - gcl.parseClass(''' -import grails.gorm.tests.* -import grails.gorm.* -import grails.persistence.* -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -@ApplyDetachedCriteriaTransform -@Entity -class CallMe { - def badQuery() { - Pet.where { - owner.firstN == "Joe" - } - } -} -''') - } - - def queryUsingUnsupportedOperatorInSize() { - def gcl = new GroovyClassLoader(getClass().classLoader) - gcl.parseClass(''' -import grails.gorm.tests.* -import grails.gorm.* -import grails.persistence.* -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -@ApplyDetachedCriteriaTransform -@Entity -class CallMe { - def badQuery() { - Person.where { - pets.size() << 1 - } - } -} -''') - } - def queryUsingUnsupportedOperator() { - def gcl = new GroovyClassLoader(getClass().classLoader) - gcl.parseClass(''' -import grails.gorm.tests.* -import grails.gorm.* -import grails.persistence.* -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -@ApplyDetachedCriteriaTransform -@Entity -class CallMe { - def badQuery() { - Person.where { - firstName << "Blah" - } - } -} -''') - } - - def queryUsingInvalidNegation() { - def gcl = new GroovyClassLoader(getClass().classLoader) - gcl.parseClass(''' -import grails.gorm.tests.* -import grails.gorm.* -import grails.persistence.* -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -@ApplyDetachedCriteriaTransform -@Entity -class CallMe { - def badQuery() { - Person.where { - !(firstName) - } - } -} -''') - } - - def queryUsingUnknownPropertyWithSize() { - def gcl = new GroovyClassLoader(getClass().classLoader) - gcl.parseClass(''' -import grails.gorm.tests.* -import grails.gorm.* -import grails.persistence.* -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -@ApplyDetachedCriteriaTransform -@Entity -class CallMe { - def badQuery() { - Person.where { - blah.size() == 10 - } - } -} -''') - } - - def queryReferencingNonExistentProperty() { - def gcl = new GroovyClassLoader(getClass().classLoader) - gcl.parseClass(''' -import grails.gorm.tests.* -import grails.gorm.* -import grails.persistence.* -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -@ApplyDetachedCriteriaTransform -@Entity -class CallMe { - def badQuery() { - Person.where { - doesntExist == "Blah" - } - } -} -''') - } - - def queryReferencingNonExistentPropertyOfAssociation() { - def gcl = new GroovyClassLoader(getClass().classLoader) - gcl.parseClass(''' -import grails.gorm.tests.* -import grails.gorm.* -import grails.persistence.* -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -@ApplyDetachedCriteriaTransform -@Entity -class CallMe { - - Set pets - static hasMany = [pets:Pet] - def badQuery() { - Person.where { - pets { doesntExist == "Blah" } - } - } -} - -@ApplyDetachedCriteriaTransform -@Entity -class Pet { - String name -} -''') - } - - def getClassThatCallsWhere() { - def gcl = new GroovyClassLoader(getClass().classLoader) - gcl.parseClass(''' -import grails.gorm.tests.* -import grails.gorm.* -import grails.persistence.* -import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform - -@ApplyDetachedCriteriaTransform -@Entity -class CallMe { - String name - def myDetachedCriteria = { firstName == "Bart" } as DetachedCriteria - def declaredQuery() { - Person.where(myDetachedCriteria) - } - - static doStuff() { - Person.where {} - } - - def doQuery() { - def session = [user: [username:"Fred"]] - def results = Proposal.findAll { advisor.username == session.user.username && approvalDate != null } - } -} -''', "Test").newInstance() - } -} - -@Entity -class Continent { - Long id - Long version - - String name - Set countries = [] - static hasMany = [countries:Country] -} - -@Entity -class Group { - Long id - String name - SortedSet people = [] as SortedSet - static hasMany = [people:Person] -} - -@Entity -class Proposal { - Long id - String name - Advisor advisor - Date approvalDate - - static constraints = { - advisor nullable:false - name nullable:false - approvalDate nullable:true - } -} - -@Entity -class Advisor { - Long id - String username - - static constraints = { - username nullable:false - proposals nullable:true - } - - static hasMany = [proposals: Proposal] -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AddToAndInjectedServiceSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AddToAndInjectedServiceSpec.groovy deleted file mode 100644 index 1f6ed7a54..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AddToAndInjectedServiceSpec.groovy +++ /dev/null @@ -1,40 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Issue - -class AddToAndInjectedServiceSpec extends GormDatastoreSpec { - - @Issue('GRAILS-9119') - void "Test add to method with injected service present"() { - given:"A domain with an addTo relationship" - def pirate = new Pirate(name: 'Billy') - def ship = new Ship() - when:"The addTo method is called" - ship.addToPirates(pirate) - - then:"It adds an associated entity correctly" - assert 1 == ship.pirates.size() - } - - @Override - List getDomainClasses() { - [Pirate, Ship] - } -} - -@Entity -class Pirate { - Long id - String name - def pirateShipService -} - -@Entity -class Ship { - Long id - Set pirates - static hasMany = [pirates: Pirate] -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AddToMethodWithBasicCollectionSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AddToMethodWithBasicCollectionSpec.groovy deleted file mode 100644 index 634ac7ff9..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AddToMethodWithBasicCollectionSpec.groovy +++ /dev/null @@ -1,42 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Issue - -class AddToMethodWithBasicCollectionSpec extends GormDatastoreSpec{ - - @Issue('GRAILS-8779') - void "Test that the addTo* method works with basic collections"() { - when:"A book is saved with a basic collection" - def book = new BasicBook(title: "DGG") - book.addToAuthors("Graeme") - .addToAuthors("Jeff") - .save(flush:true) - - session.clear() - - book = BasicBook.get(book.id) - then:"The model is saved correctly" - book.title == "DGG" - book.authors.size() == 2 - book.authors.contains "Graeme" - book.authors.contains "Jeff" - } - - @Override - List getDomainClasses() { - [BasicBook] - } -} - -@Entity -class BasicBook { - - Long id - static hasMany = [authors:String] - - Set authors - String title -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AddToMethodWithEmbeddedCollectionSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AddToMethodWithEmbeddedCollectionSpec.groovy deleted file mode 100644 index 76d533e6c..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AddToMethodWithEmbeddedCollectionSpec.groovy +++ /dev/null @@ -1,64 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class AddToMethodWithEmbeddedCollectionSpec extends GormDatastoreSpec { - - private service = new LibraryService() - - void testAddBooks() { - when: - LibraryBook book = new LibraryBook(title:"title", author:"me") - def library = service.addBook(book) - - then: - library - library.books.size()==1 - } - - void testAddBooksInTest() { - when: - LibraryBook book = new LibraryBook(title:"title", author:"me") - def library = new Library() - library.addToBooks(book) - - then: - library - library.books.size()==1 - } - - @Override - List getDomainClasses() { - [Library, LibraryBook] - } -} - -@Entity -class Library { - - static embedded = [ - 'books' - ] - - Set books - Long id - static hasMany = [books:LibraryBook] -} - -@Entity -class LibraryBook { - Long id - String title - String author -} - -class LibraryService { - - Library addBook(LibraryBook book) { - def library = new Library() - library.addToBooks(book) - library.save(failOnError:true) - return library - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AssignedIdentifierSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AssignedIdentifierSpec.groovy deleted file mode 100644 index 26800f0f5..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AssignedIdentifierSpec.groovy +++ /dev/null @@ -1,55 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -/** - * Tests for usage of assigned identifiers - */ -class AssignedIdentifierSpec extends GormDatastoreSpec{ - - void "Test that entities can be saved, retrieved and updated with assigned ids"() { - when:"An entity is saved with an assigned id" - def r = new River(name:"Amazon", country: "Brazil") - r.save flush:true - session.clear() - r = River.get("Amazon") - - then:"The entity can be retrieved" - r != null - r.name == "Amazon" - r.country == "Brazil" - - when:"The entity is updated" - r.country = "Argentina" - r.save flush:true - session.clear() - r = River.get("Amazon") - - then:"The update is applied" - r != null - r.name == "Amazon" - r.country == "Argentina" - - when:"The entity is deleted" - r.delete(flush:true) - - then:"It is gone" - River.count() == 0 - River.get("Amazon") == null - } - - @Override - List getDomainClasses() { - [River] - } -} - -@Entity -class River { - String name - String country - static mapping = { - id name:'name', generator:'assigned' - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AsyncReadMethodsSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AsyncReadMethodsSpec.groovy deleted file mode 100644 index b3932bcc6..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AsyncReadMethodsSpec.groovy +++ /dev/null @@ -1,100 +0,0 @@ -package org.grails.datastore.gorm - -import grails.async.Promise -import grails.async.Promises -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person - -/** - */ -class AsyncReadMethodsSpec extends GormDatastoreSpec{ - - def "Test that normal GORM methods can be used within the doAsync method"() { - given:"Some people" - final p1 = new Person(firstName: "Homer", lastName: "Simpson").save() - final p2 = new Person(firstName: "Bart", lastName: "Simpson").save() - final p3 = new Person(firstName: "Barney", lastName: "Rubble").save(flush: true) - session.clear() - - when:"We obtain a promise via the exec method" - def promise = Person.async.task { - list() - } - - def results = promise.get() - then:"The results are correct" - results.size() == 3 - results[0].firstName == "Homer" - results[1].firstName == "Bart" - results[2].firstName == "Barney" - } - def "Test that the list method works async"() { - given:"Some people" - new Person(firstName: "Homer", lastName: "Simpson").save() - new Person(firstName: "Bart", lastName: "Simpson").save() - new Person(firstName: "Barney", lastName: "Rubble").save(flush:true) - session.clear() - - when:"We list all entities async" - def promise = Person.async.list() - - then:"A promise is returned" - promise instanceof Promise - - when:"The promise value is returned" - def results = promise.get() - - then:"They are correct" - results.size() == 3 - - } - - def "Test multiples GORM promises using get method"() { - given:"Some people" - final p1 = new Person(firstName: "Homer", lastName: "Simpson").save() - final p2 = new Person(firstName: "Bart", lastName: "Simpson").save() - final p3 = new Person(firstName: "Barney", lastName: "Rubble").save(flush: true) - session.clear() - - when:"We obtain multiple promises and await the response" - def prom1 = Person.async.get(p1.id) - def prom2 = Person.async.get(p2.id) - def prom3 = Person.async.get(p3.id) - def results = Promises.waitAll(prom1, prom2, prom3) - - then:"The results are correct" - results.size() == 3 - results[0].firstName == "Homer" - results[1].firstName == "Bart" - results[2].firstName == "Barney" - - when:"We obtain the results with the getAll method async" - results = Person.async.getAll(p1.id, p2.id, p3.id).get() - - then:"The results are correct" - results.size() == 3 - results[0].firstName == "Homer" - results[1].firstName == "Bart" - results[2].firstName == "Barney" - } - - def "Test multiples GORM promises using dynamic finder method"() { - given:"Some people" - final p1 = new Person(firstName: "Homer", lastName: "Simpson").save() - final p2 = new Person(firstName: "Bart", lastName: "Simpson").save() - final p3 = new Person(firstName: "Barney", lastName: "Rubble").save(flush: true) - session.clear() - - when:"We obtain multiple promises and await the response" - def prom1 = Person.async.findByFirstName("Homer") - def prom2 = Person.async.findByFirstName("Bart") - def prom3 = Person.async.findByFirstName("Barney") - def results = Promises.waitAll(prom1, prom2, prom3) - - then:"The results are correct" - results.size() == 3 - results[0].firstName == "Homer" - results[1].firstName == "Bart" - results[2].firstName == "Barney" - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AutoLinkOneToManyAssociationSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AutoLinkOneToManyAssociationSpec.groovy deleted file mode 100644 index 0e8024d15..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/AutoLinkOneToManyAssociationSpec.groovy +++ /dev/null @@ -1,60 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Issue - -class AutoLinkOneToManyAssociationSpec extends GormDatastoreSpec{ - - @Issue('GRAILS-8815') - void "Test that associations are linked automatically when saving"() { - given:"A new domain class with a one-to-many association" - def author = new AutoLinkListAuthor(firstName:'foo', lastName: 'bar') - when:"The domain is saved" - author.save() - then:"The association is intially empty" - author.id != null - author.books == null - - when:"An associated object is added" - def book1 = new AutoLinkListBook(title: 'grails', price: 43, published: new Date(), author: author) - - // add the book to the author to complete the other side - author.addToBooks(book1) - then:"The relationship size is correct" - author.books.size() == 1 - - when:"The domain is saved" - author.save() - then:"The relationship size is still correct" - author.books.size() == 1 - } - - @Override - List getDomainClasses() { - [AutoLinkListAuthor,AutoLinkListBook] - } -} - -@Entity -class AutoLinkListAuthor { - Long id - String firstName - String lastName - - // Hi, see here! - List books - - static hasMany = [books: AutoLinkListBook] -} - -@Entity -class AutoLinkListBook { - Long id - String title - Date published - BigDecimal price - - static belongsTo = [author: AutoLinkListAuthor] -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/BasicTypeHasManySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/BasicTypeHasManySpec.groovy deleted file mode 100644 index 52f6e63bc..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/BasicTypeHasManySpec.groovy +++ /dev/null @@ -1,62 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import spock.lang.Issue - -/** - * @author Graeme Rocher - */ -class BasicTypeHasManySpec extends GormDatastoreSpec{ - @Override - List getDomainClasses() { - [Workspace] - } - - @Issue('GRAILS-9876') - void "Test addTo with locales"() { - given:"Some locale instances" - def ws = new Workspace() - def locales = [Locale.GERMANY, Locale.GERMAN, Locale.ENGLISH, Locale.CHINA] // different language and country base locales - - when:"The locales are added to a domain with the addTo method" - for(loc in locales) { - ws.addToLocales(loc) - } - ws.save() - - then:"The locales collection contains said locales" - ws.locales.contains Locale.GERMANY - ws.locales.contains Locale.GERMAN - ws.locales.contains Locale.ENGLISH - ws.locales.contains Locale.CHINA - } - - @Issue('GRAILS-9876') - void "Test addTo with dates"() { - given:"Some date instances" - def ws = new Workspace() - def d1 = new Date()+1 - def d2 = new Date()+10 - - def dates = [d1, d2] // different dates - when:"The dates are added to a domain with addTo" - for(date in dates) { - ws.addToDates(date) - } - ws.save() - - then:"The dates are added correctly to the association" - ws.dates.contains d1 - ws.dates.contains d2 - } -} - -@Entity -class Workspace { - - Long id - Set locales - Set dates - static hasMany = [locales: Locale, dates: Date] -} \ No newline at end of file diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/BeforeUpdateEventSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/BeforeUpdateEventSpec.groovy deleted file mode 100644 index a8db4e2e9..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/BeforeUpdateEventSpec.groovy +++ /dev/null @@ -1,69 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Issue - -class BeforeUpdateEventSpec extends GormDatastoreSpec { - - @Issue('GRAILS-8916') - void "Test beforeUpdate event doesn't cause test failure"() { - when:"An entity is saved that has a beforeUpdate event" - BeforeUpdateBook b = new BeforeUpdateBook() - b.save(failOnError:true) - BeforeUpdateAuthor a = new BeforeUpdateAuthor() - a.save(failOnError:true) - - a.book = b - a.save(failOnError:true) - - then:"The association index is persisted correctly" - a.id == BeforeUpdateAuthor.findByBook(b).id - } - - @Issue('GRAILS-8977') - void "Test beforeUpdate event doesn't cause test failure when setting association to null"() { - when:"A domain model is created" - BeforeUpdateBook b = new BeforeUpdateBook() - b.save(failOnError:true) - - BeforeUpdateAuthor a = new BeforeUpdateAuthor() - a.save(failOnError:true) - - a.book = b - a.save(failOnError:true) - then:"The domain model is valid" - assert a.id == BeforeUpdateAuthor.findByBook(b).id - - when:"An association is set to null" - a.book = null - a.save(failOnError:true) - - then:"It can be queried" - assert a.id == BeforeUpdateAuthor.findByBookIsNull().id - } - - @Override - List getDomainClasses() { - [BeforeUpdateAuthor, BeforeUpdateBook] - } -} - -@Entity -class BeforeUpdateBook { - Long id - static hasMany = [authors:BeforeUpdateAuthor] -} - -@Entity -class BeforeUpdateAuthor { - Long id - BeforeUpdateBook book - - def beforeUpdate() {} - - static constraints = { - book(nullable:true) - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/BidirectionalOneToManyWithInheritanceSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/BidirectionalOneToManyWithInheritanceSpec.groovy deleted file mode 100644 index 500d19886..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/BidirectionalOneToManyWithInheritanceSpec.groovy +++ /dev/null @@ -1,54 +0,0 @@ -import grails.gorm.tests.GormDatastoreSpec - -/** - * @author graemerocher - */ -class BidirectionalOneToManyWithInheritanceSpec extends GormDatastoreSpec { - - void "Test a bidirectional one-to-many association with inheritance"() { - - given: - def doc = new Documentation() - - doc.addToConfigurationItems(new ChangeRequest()) - .addToConfigurationItems(new Documentation()) - - when: - doc.save(flush:true) - session.clear() - doc = Documentation.get(1) - - then: - 2 == doc.configurationItems.size() - } - - @Override - List getDomainClasses() { - [ConfigurationItem, Documentation, ChangeRequest] - } -} - -class ConfigurationItem { - Long id - Long version - ConfigurationItem parent - - Set configurationItems - - static hasMany = [configurationItems: ConfigurationItem] - static mappedBy = [configurationItems: 'parent'] - static belongsTo = [ConfigurationItem] - static constraints = { - parent(nullable: true) - } -} - -class Documentation extends ConfigurationItem { - Long id - Long version -} - -class ChangeRequest extends ConfigurationItem { - Long id - Long version -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CacheAndJoinSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CacheAndJoinSpec.groovy deleted file mode 100644 index 6b3871ace..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CacheAndJoinSpec.groovy +++ /dev/null @@ -1,43 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Issue - -class CacheAndJoinSpec extends GormDatastoreSpec{ - - @Issue('GRAILS-8758') - void "Test that the cache and join methods can be used in a test"() { - given:"Some test data" - new Author(name: "Bob").save flush:true - session.clear() - when:"The cache and join methods are used in criteria" - def a = Author.createCriteria().get { - eq 'name', "Bob" - join 'books' - maxResults 1 - cache true - } - - then:"Results are returned" - a != null - } - - @Override - List getDomainClasses() { - [Author, Book] - } -} - -@Entity -class Author { - Long id - String name - - static hasMany = [books: Book] - - static constraints = { - name blank: false - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CircularManyToManySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CircularManyToManySpec.groovy deleted file mode 100644 index cc20c4345..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CircularManyToManySpec.groovy +++ /dev/null @@ -1,63 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class CircularManyToManySpec extends GormDatastoreSpec { - - void "Test that a circular one-to-many persists correctly"() { - when:"A domain model with circular one-to-manys is created and queried" - def p1 = new CircularPerson(name: "Fred").save() - def p2 = new CircularPerson(name: "Bob").save() - def p3 = new CircularPerson(name: "Joe").save() - def p4 = new CircularPerson(name: "Homer").save() - - p1.addToFriends(p2) - p1.addToFriends(p3) - - p1.addToEnemies(p4) - - p1.save(flush: true) - - p2.addToEnemies(p1) - - p2.save(flush: true) - session.clear() - - p1 = CircularPerson.findByName("Fred") - p2 = CircularPerson.findByName("Bob") - - then:"The persisted model is correct" - p1.name == "Fred" - p1.friends.size() == 2 - p1.friends.find { it.name == 'Bob' } - p1.friends.find { it.name == 'Joe' } - p1.enemies.size() == 1 - p1.enemies.find { it.name == 'Homer' } - p2.enemies.size() == 1 - p2.enemies.find { it.name == 'Fred' } - } - - @Override - List getDomainClasses() { - [CircularPerson] - } -} - -@Entity -class CircularPerson { - - Long id - String name - List friends = [] - - static hasMany = [ - friends: CircularPerson, - enemies: CircularPerson - ] - - static mapping = { - friends joinTable: "person_friends" - enemies joinTable: "person_enemies" - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CircularManyToOneSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CircularManyToOneSpec.groovy deleted file mode 100644 index cb0792a76..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CircularManyToOneSpec.groovy +++ /dev/null @@ -1,49 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class CircularManyToOneSpec extends GormDatastoreSpec { - - void "Test that a circular many-to-one persists correctly"() { - when:"A self referencing domain model is created" - TreeNode root = new TreeNode(parent: null, name: "root") - root.save() - - TreeNode child = new TreeNode(parent: root, name: "child") - child.save() - - TreeNode grandchild = new TreeNode(parent: child, name:"grandchild") - grandchild.save(flush:true) - - then:"The associations are configured correctly" - root.parent == null - child.parent == root - grandchild.parent == child - - when:"The model is queried" - session.clear() - grandchild = TreeNode.findByName("grandchild") - - then:"It is loaded correctly" - grandchild.name == "grandchild" - grandchild.parent.name == 'child' - grandchild.parent.parent.name == 'root' - grandchild.parent.parent.parent == null - } - - @Override - List getDomainClasses() { - [TreeNode] - } -} - -@Entity -class TreeNode { - Long id - TreeNode parent - String name - static constraints = { - parent nullable:true - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CompositeIdentifierSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CompositeIdentifierSpec.groovy deleted file mode 100644 index 0cfd7d5fb..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CompositeIdentifierSpec.groovy +++ /dev/null @@ -1,56 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Ignore - -/** - * TODO: Support composite ids - */ -@Ignore -class CompositeIdentifierSpec extends GormDatastoreSpec { - - void "Test that a composite identifier is treated as assigned"() { - given:"A domain model with a composite identifier" - def u = new User(name: "Bob").save() - def r = new Role(name: "Admin").save() - def ur = new UserRole(user: u, role: r) - ur.save flush: true - session.clear() - - when:"The entity is queried" - ur = UserRole.get(new UserRole(user: u, role: r)) - - then:"it is found" - ur != null - } - - @Override - List getDomainClasses() { - [User, Role, UserRole] - } -} - -@Entity -class UserRole implements Serializable { - - User user - Role role - - static mapping = { - id composite: ['role', 'user'] - } -} - -@Entity -class User { - Long id - String name -} - -@Entity -class Role { - Long id - String name -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CriteriaProjectedResultsSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CriteriaProjectedResultsSpec.groovy deleted file mode 100644 index 203f4b791..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CriteriaProjectedResultsSpec.groovy +++ /dev/null @@ -1,227 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class CriteriaProjectedResultsSpec extends GormDatastoreSpec { - - void "Test single projection"() { - when:"A instanced is saved" - Check c = new Check(amount: 57).save() - - then:"The count is 1" - 1 == Check.count() - - when:"A sum projection is executed" - def total = Check.withCriteria { - projections { - sum 'amount' - } - } - - then:"A list is returned containing the sum" - [57] == total - } - - void "Test multiple projections"() { - given:"A domain instance" - Check c = new Check(amount: 57).save() - - when:"A projection is used with two projected results" - def model = Check.withCriteria { - projections { - rowCount() - sum 'amount' - } - } - - then:"A list containing another list is returned" - [[1, 57]] == model - } - - void "Test single projection multiple rows"() { - given:"multiple records" - new Check(amount: 57, descr: 'fifty-seven').save() - new Check(amount: 83, descr: 'eighty-three').save() - new Check(amount: 29, descr: 'twenty-nine').save() - - when:"A query is executed" - def model = Check.withCriteria { - projections { - property('amount') - } - order('amount', 'asc') - } - - then:"A list of lists is returned" - [29, 57, 83] == model - } - - void "Test multiple projections with multiple rows"() { - given:"Multiple recordes" - new Check(amount: 57, descr: 'fifty-seven').save() - new Check(amount: 83, descr: 'eighty-three').save() - new Check(amount: 29, descr: 'twenty-nine').save() - - when:"A query with multiple projections is executed" - def model = Check.withCriteria { - projections { - property('descr') - property('amount') - } - order('amount', 'asc') - } - - then:"A list of lists is returned" - [['twenty-nine', 29], ['fifty-seven', 57], ['eighty-three', 83]] == model - } - - void "Test single order"() { - given:"A domain model" - new Check(amount: 57, descr: 'fifty-seven').save() - new Check(amount: 83, descr: 'eighty-three').save() - new Check(amount: 29, descr: 'twenty-nine').save() - new Check(amount: 83, descr: 'seventy').save() - - when:"The model is queried" - def model = Check.withCriteria { - order('amount', 'asc') - } - - then:"The order is correct" - assert model - assert 4 == model.size() - assert 29 == model[0].amount - assert 57 == model[1].amount - assert 83 == model[2].amount - assert 83 == model[3].amount - } - - void "Test multiple orders"() { - given:"A domain model" - new Check(amount: 57, descr: 'fifty-seven').save() - new Check(amount: 83, descr: 'eighty-three').save() - new Check(amount: 29, descr: 'twenty-nine').save() - new Check(amount: 83, descr: 'seventy').save() - - when:"The domain model is queried with multiple order definitions" - def model = Check.withCriteria { - order('amount', 'asc') - order('descr', 'desc') - } - - then:"The order is correct" - assert model - assert 4 == model.size() - assert 29 == model[0].amount - assert 57 == model[1].amount - assert 83 == model[2].amount - assert 'seventy' == model[2].descr - assert 83 == model[3].amount - assert 'eighty-three' == model[3].descr - } - - void "Test multiple orders with projections"() { - given:"A domain model" - new Check(amount: 57, descr: 'fifty-seven').save() - new Check(amount: 83, descr: 'eighty-three').save() - new Check(amount: 29, descr: 'twenty-nine').save() - new Check(amount: 83, descr: 'seventy').save() - - when:"A query is executed with 2 projectsions and 2 orders in different directions" - def model = Check.withCriteria { - projections { - property('descr') - property('amount') - } - order('amount', 'asc') - order('descr', 'desc') - } - then:"The results are correct" - [['twenty-nine', 29], ['fifty-seven', 57], ['seventy', 83], ['eighty-three', 83]] == model - - when:"A query is executed with 2 projections and 2 orders in the same direction" - model = Check.withCriteria { - projections { - property('descr') - property('amount') - } - order('amount', 'asc') - order('descr', 'asc') - } - - then:"The results are correct" - [['twenty-nine', 29], ['fifty-seven', 57], ['eighty-three', 83], ['seventy', 83]] == model - - when:"A query is executed with 2 projects and 2 orders on different properties" - model = Check.withCriteria { - projections { - property('descr') - property('amount') - } - order('amount', 'asc') - order('id', 'desc') - } - - then:"The results are correct" - [['twenty-nine', 29], ['fifty-seven', 57], ['seventy', 83], ['eighty-three', 83]] == model - } - - void testOrderAndOffset() { - given:"A domain model" - new Check(amount: 57, descr: 'fifty-seven').save() - new Check(amount: 83, descr: 'eighty-three').save() - new Check(amount: 29, descr: 'twenty-nine').save() - new Check(amount: 83, descr: 'seventy').save() - - expect:"All items are present" - 4 == Check.count() - - when:"A query is executed with 2 orderings in different directions, offset, and limit" - def model = Check.withCriteria { - projections { - property('descr') - property('amount') - } - order('amount', 'asc') - order('descr', 'desc') - firstResult(1) - maxResults(2) - } - - then:"The results are correct" - [['fifty-seven', 57], ['seventy', 83]] == model - - when:"A query is executed with 2 orderings in same direction, offset, and limit" - model = Check.withCriteria { - projections { - property('descr') - property('amount') - } - order('amount', 'asc') - order('descr', 'asc') - firstResult(2) - maxResults(2) - } - - then:"The results are correct" - [['eighty-three', 83], ['seventy', 83]] == model - } - - @Override - List getDomainClasses() { - [Check] - } -} - -@Entity -class Check { - Long id - BigDecimal amount - String descr - - static constraints = { - amount nullable: false - descr nullable: true - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CustomSequenceIdentifierSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CustomSequenceIdentifierSpec.groovy deleted file mode 100644 index 76950dd16..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CustomSequenceIdentifierSpec.groovy +++ /dev/null @@ -1,31 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec - -class CustomSequenceIdentifierSpec extends GormDatastoreSpec { - - void "Test sequence identifiers"() { - when:"when a book with a sequence id is saved" - new Book(title:"Blah").save(flush:true) - session.clear() - def b = Book.findByTitle("Blah") - then:"It can be retrieved" - b != null - b.id != null - } - - @Override - List getDomainClasses() { - [Book] - } -} - -class Book { - - Long id - String title - - static mapping = { - id generator:'sequence', params:[sequence:'book_seq'] - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CustomStringIdentifierSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CustomStringIdentifierSpec.groovy deleted file mode 100644 index 893025878..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CustomStringIdentifierSpec.groovy +++ /dev/null @@ -1,77 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class CustomStringIdentifierSpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [Product, Description] - } - - void "test basic crud operations with string id"() { - when: "A product is saved with an assigned id" - createProducts() - def p = Product.get("MacBook") - - then:"The product is not null" - p != null - - when:"A product is retrieved by id" - session.clear() - p = Product.get("MacBook") - - then:"The product is not null" - p != null - } - - void "Test dynamic finders with string id"() { - when: "A product with a string id is query via a dynamic finder" - createProducts() - def p = Product.findByName("MacBook") - - then:"The product is not null" - p != null - - } - - void "Test integer based id"() { - when:"An object has an id that is an integer" - def d = new Description(name:"Blah").save(flush:true) - - then:"The object is successfully saved" - d != null - - when:"The object is queried" - session.clear() - d = Description.get(1) - - then:"The object is returned" - d != null - - } - - protected def createProducts() { - new Product(name: "MacBook").save() - new Product(name: "iPhone").save() - new Product(name: "iMac").save(flush: true) - - } -} - -@Entity -class Description { - Integer id - String name -} - -@Entity -class Product { - String name - Date dateCreated - - static mapping = { - id generator:'assigned', name:"name" - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CustomTypeMarshallingSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CustomTypeMarshallingSpec.groovy deleted file mode 100644 index d38ed514a..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/CustomTypeMarshallingSpec.groovy +++ /dev/null @@ -1,145 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec - -import spock.lang.Issue -import spock.lang.Shared - -class CustomTypeMarshallingSpec extends GormDatastoreSpec { - - @Shared Date now = new Date() - - def setup() { - def p = new Person(name:"Fred", birthday: new Birthday(now)) - p.save(flush:true) - session.clear() - } - - def cleanup() { - Person.list()*.delete(flush: true) - session.clear() - } - - void "can retrieve custom values from the datastore"() { - when: "We query the person" - def p = Person.findByName("Fred") - - then: "The birthday is returned" - p != null - p.name == "Fred" - p.birthday != null - } - - void "can query based on custom types"() { - when: "We query with a custom type" - def p = Person.findByBirthday(new Birthday(now)) - - then: - p != null - } - - void "can perform a range query based on custom types"() { - when: "A range query is executed" - def p = Person.findByBirthdayBetween(new Birthday(now-1), new Birthday(now+1)) - def p2 = Person.findByBirthdayBetween(new Birthday(now+1), new Birthday(now+2)) - - then: - p != null - p2 == null - } - - @Issue("http://jira.grails.org/browse/GRAILS-8436") - void "can re-save an existing instance without modifications"() { - given: - def p = Person.findByName("Fred") - - when: "we can re-save an existing instance without modifications" - p.birthday = new Birthday(now) - boolean saveResult = p.save(flush: true) - - then: 'the save is successful' - saveResult - - and: "the version is not incremented" - p.version == old(p.version) - } - - @Issue("http://jira.grails.org/browse/GRAILS-8436") - void "can modify the value of a custom type property"() { - given: - def p = Person.findByName("Fred") - - when: "we modify the value of a custom property" - p.birthday = new Birthday(now + 1) - boolean saveResult = p.save(flush: true) - - then: 'the save is successful' - saveResult - - and: "the version is incremented" - p.version == old(p.version) + 1 - - and: "we can query based on the modified value" - session.clear() - Person.countByBirthdayGreaterThan(new Birthday(now)) == 1 - } - - @Issue("http://jira.grails.org/browse/GRAILS-8436") - void "can nullify the value of a custom type property"() { - given: - def p = Person.findByName("Fred") - - when: "we modify the value of a custom property" - p.birthday = null - boolean saveResult = p.save(flush: true) - - then: 'the save is successful' - saveResult - - and: "the version is incremented" - p.version == old(p.version) + 1 - - and: "we can query based on the modified value" - session.clear() - Person.countByBirthdayIsNull() == 1 - } - - @Override - List getDomainClasses() { - [Person] - } -} - -class Person { - Long id - Integer version - String name - Birthday birthday -} - -class Birthday implements Comparable { - Date date - - Birthday(Date date) { - this.date = date - } - - @Override - int hashCode() { - date.hashCode() - } - - @Override - boolean equals(Object obj) { - obj instanceof Birthday && date == obj.date - } - - int compareTo(t) { - date.compareTo(t.date) - } - - @Override - String toString() { - "Birthday[$date.time]" - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DeindexingSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DeindexingSpec.groovy deleted file mode 100644 index f4f55c4f4..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DeindexingSpec.groovy +++ /dev/null @@ -1,34 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec - -/** - * @author Daniel Wiell - */ -class DeindexingSpec extends GormDatastoreSpec { - - def 'Null is de-indexed'() { - def author = new AuthorWithPseudonym(name: 'Samuel Clemens').save(failOnError: true) - author.pseudonym = 'Mark Twain' - author.save(failOnError: true) - - expect: - !AuthorWithPseudonym.findByPseudonymIsNull() - } - - @Override - List getDomainClasses() { - [AuthorWithPseudonym] - } -} - -class AuthorWithPseudonym { - Long id - Integer version - String name - String pseudonym - - static constraints = { - pseudonym nullable: true - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DetachedCriteriaAsPromiseSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DetachedCriteriaAsPromiseSpec.groovy deleted file mode 100644 index c4ab14be6..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DetachedCriteriaAsPromiseSpec.groovy +++ /dev/null @@ -1,68 +0,0 @@ -package org.grails.datastore.gorm - -import grails.async.Promise -import grails.gorm.DetachedCriteria -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person - -/** - */ -class DetachedCriteriaAsPromiseSpec extends GormDatastoreSpec{ - - def "Test a DetachedCriteria instance can be turned into a Promise"() { - given:"Some people" - new Person(firstName: "Homer", lastName: "Simpson").save() - new Person(firstName: "Bart", lastName: "Simpson").save() - new Person(firstName: "Barney", lastName: "Rubble").save(flush:true) - session.clear() - - when:"We cast a DetachedCriteria to a Promise" - DetachedCriteria query = Person.where( { - lastName == "Simpson" - }) - - def promise = query as Promise - - then:"A promise is returned" - promise instanceof Promise - - when:"The promise value is returned" - def results = promise.get() - - then:"They are correct" - results.size() == 2 - - } - - def "Test a DetachedCriteria instance with the async namespace"() { - given:"Some people" - new Person(firstName: "Homer", lastName: "Simpson").save() - new Person(firstName: "Bart", lastName: "Simpson").save() - new Person(firstName: "Barney", lastName: "Rubble").save(flush:true) - session.clear() - - when:"We cast a DetachedCriteria to a Promise" - DetachedCriteria query = Person.where( { - lastName == "Simpson" - }) - - def promise = query.async.list() - - then:"A promise is returned" - promise instanceof Promise - - when:"The promise value is returned" - def results = promise.get() - - then:"They are correct" - results.size() == 2 - - when:"A dynamic finder is used async" - Person p = query.async.findByFirstName("Homer").get() - - then:"The result is correct" - p != null - p.firstName == "Homer" - - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DirtyCheckingSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DirtyCheckingSpec.groovy deleted file mode 100644 index e2760b992..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DirtyCheckingSpec.groovy +++ /dev/null @@ -1,56 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec - -import grails.gorm.tests.Person -import org.grails.datastore.mapping.dirty.checking.DirtyCheckable - -/** - * @author Graeme Rocher - */ -class DirtyCheckingSpec extends GormDatastoreSpec { - - void "Test that dirty checking methods work when changing entities"() { - when:"A new instance is created" - def p = new Person(firstName: "Homer", lastName: "Simpson") - - then:"The instance is dirty by default" - p instanceof DirtyCheckable - p.isDirty() - p.isDirty("firstName") - - when:"The instance is saved" - p.save(flush:true) - - then:"The instance is no longer dirty" - !p.isDirty() - !p.isDirty("firstName") - - when:"The instance is changed" - p.firstName = "Bart" - - then:"The instance is now dirty" - p.isDirty() - p.isDirty("firstName") - p.dirtyPropertyNames == ['firstName'] - p.getPersistentValue('firstName') == "Homer" - - when:"The instance is loaded from the db" - p.save(flush:true) - session.clear() - p = Person.get(p.id) - - then:"The instance is not dirty" - !p.isDirty() - !p.isDirty('firstName') - - when:"The instance is changed" - p.firstName = "Lisa" - - then:"The instance is dirty" - p.isDirty() - p.isDirty("firstName") - - - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DistinctProjectionSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DistinctProjectionSpec.groovy deleted file mode 100644 index 26939b558..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DistinctProjectionSpec.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Person - -class DistinctProjectionSpec extends GormDatastoreSpec { - - def "Test that using the distinct projection returns distinct results"() { - given:"Some people with the same last names" - new Person(firstName: "Homer", lastName: "Simpson").save() - new Person(firstName: "Bart", lastName: "Simpson").save() - new Person(firstName: "Barney", lastName: "Rubble").save(flush:true) - - when:"We query with criteria for distinct surnames" - def results = Person.withCriteria { - projections { - distinct "lastName" - } - }.sort() - - then:"The correct results are returned" - results == ['Rubble', 'Simpson'] - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DomainWithPrimitiveGetterSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DomainWithPrimitiveGetterSpec.groovy deleted file mode 100644 index b33c6059c..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/DomainWithPrimitiveGetterSpec.groovy +++ /dev/null @@ -1,42 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Issue - -class DomainWithPrimitiveGetterSpec extends GormDatastoreSpec{ - - @Issue('GRAILS-8788') - void "Test that a domain that contains a primitive getter maps correctly"() { - when:"The domain model is saved" - def author = new DomainWithPrimitiveGetterAuthor(name: "Stephen King") - author.save() - def book = new DomainWithPrimitiveGetterBook(title: "The Stand", author: author) - book.save flush:true - then:"The save executes correctly" - DomainWithPrimitiveGetterBook.count() == 1 - DomainWithPrimitiveGetterAuthor.count() == 1 - } - - @Override - List getDomainClasses() { - [DomainWithPrimitiveGetterAuthor, DomainWithPrimitiveGetterBook] - } -} - -@Entity -class DomainWithPrimitiveGetterBook { - Long id - String title - DomainWithPrimitiveGetterAuthor author - int getValue(int param) { - return 0 - } -} -@Entity -class DomainWithPrimitiveGetterAuthor { - Long id - String name - static hasMany = [books: DomainWithPrimitiveGetterBook] -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/EmbeddedAssociationSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/EmbeddedAssociationSpec.groovy deleted file mode 100755 index c8fbca53e..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/EmbeddedAssociationSpec.groovy +++ /dev/null @@ -1,59 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Shared - -class EmbeddedAssociationSpec extends GormDatastoreSpec { - - @Shared Date now = new Date() - - void "Test persistence of embedded entities"() { - given: - def i = new Individual(name:"Bob", address: new Address(postCode:"30483"), bio: new Bio(birthday: new Birthday(now))) - - i.save(flush:true) - session.clear() - - when: - i = Individual.findByName("Bob") - - then: - i != null - i.name == 'Bob' - i.address != null - i.address.postCode == '30483' - i.bio.birthday.date == now - } - - @Override - List getDomainClasses() { - [Individual, Address] - } -} - -@Entity -class Individual { - Long id - String name - Address address - Bio bio - - static embedded = ['address', 'bio'] - - static mapping = { - name index:true - } -} - -@Entity -class Address { - Long id - String postCode -} - -// Test embedded associations with custom types -class Bio { - Birthday birthday -} \ No newline at end of file diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/EmbeddedNonEntityAssociationSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/EmbeddedNonEntityAssociationSpec.groovy deleted file mode 100644 index 176a928f3..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/EmbeddedNonEntityAssociationSpec.groovy +++ /dev/null @@ -1,45 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class EmbeddedNonEntityAssociationSpec extends GormDatastoreSpec { - - void "Test persistence of embedded entities"() { - given: - def i = new Being(name:"Bob", address: new ResidentialAddress(postCode:"30483")) - - i.save(flush:true) - session.clear() - - when: - i = Being.findByName("Bob") - - then: - i != null - i.name == 'Bob' - i.address != null - i.address.postCode == '30483' - } - - @Override - List getDomainClasses() { - [Being] - } -} - -@Entity -class Being { - Long id - String name - ResidentialAddress address - static embedded = ['address'] - - static mapping = { - name index:true - } -} - -class ResidentialAddress { - String postCode -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/EmbeddedPropertyQuerySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/EmbeddedPropertyQuerySpec.groovy deleted file mode 100755 index 6b2e0e499..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/EmbeddedPropertyQuerySpec.groovy +++ /dev/null @@ -1,113 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class EmbeddedPropertyQuerySpec extends GormDatastoreSpec { - - static { - GormDatastoreSpec.TEST_CLASSES << Book2 << Author2 - } - - void "Test eq query of embedded properties"() { - given: - def book = new Book2(name: 'Game of Thrones', publishPeriod: new Period(startDate: new Date(2012, 1, 1), endDate: new Date(2013, 1, 1))) - book.save(flush: true, failOnError: true) - session.clear() - when: - book = Book2.createCriteria().get { eq 'publishPeriod.startDate', new Date(2012, 1, 1) } - then: - book != null - } - - void "Test gt query of embedded properties"() { - given: - def book = new Book2(name: 'Game of Thrones', publishPeriod: new Period(startDate: new Date(2012, 1, 1), endDate: new Date(2013, 1, 1))) - book.save(flush: true, failOnError: true) - session.clear() - when: - book = Book2.createCriteria().get { gt 'publishPeriod.startDate', new Date(2011, 1, 1) } - then: - book != null - } - - void "Test ge query of embedded properties"() { - given: - def book = new Book2(name: 'Game of Thrones', publishPeriod: new Period(startDate: new Date(2012, 1, 1), endDate: new Date(2013, 1, 1))) - book.save(flush: true, failOnError: true) - session.clear() - when: - book = Book2.createCriteria().get { ge 'publishPeriod.startDate', new Date(2012, 1, 1) } - then: - book != null - } - - void "Test lt query of embedded properties"() { - given: - def book = new Book2(name: 'Game of Thrones', publishPeriod: new Period(startDate: new Date(2012, 1, 1), endDate: new Date(2013, 1, 1))) - book.save(flush: true, failOnError: true) - session.clear() - when: - book = Book2.createCriteria().get { lt 'publishPeriod.startDate', new Date(2014, 1, 1) } - then: - book != null - } - - void "Test le query of embedded properties"() { - given: - def book = new Book2(name: 'Game of Thrones', publishPeriod: new Period(startDate: new Date(2012, 1, 1), endDate: new Date(2013, 1, 1))) - book.save(flush: true, failOnError: true) - session.clear() - when: - book = Book2.createCriteria().get { le 'publishPeriod.endDate', new Date(2013, 1, 1) } - then: - book != null - } - - void "Test isNotNull query of embedded properties"() { - given: - def book = new Book2(name: 'Game of Thrones', publishPeriod: new Period(startDate: new Date(2012, 1, 1), endDate: new Date(2013, 1, 1))) - book.save(flush: true, failOnError: true) - session.clear() - when: - book = Book2.createCriteria().get { isNotNull 'publishPeriod.endDate' } - then: - book != null - } - - void "Test associated query of embedded property"() { - given: - def book = new Book2(name: 'Game of Thrones', publishPeriod: new Period(startDate: new Date(2012, 1, 1), endDate: new Date(2013, 1, 1))) - def author = new Author2(name: 'George', books: [book]) - author.save(flush: true, failOnError: true) - session.clear() - when: - author = Author2.createCriteria().get { - books { - eq 'publishPeriod.startDate', new Date(2012, 1, 1) - } - } - then: - author != null - } - -} - -@Entity -class Author2 { - String name - static hasMany = [books: Book2] -} - -@Entity -class Book2 { - String name - Period publishPeriod - - static embedded = ['publishPeriod'] -} - -class Period { - Date startDate - Date endDate -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/EnumHasManySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/EnumHasManySpec.groovy deleted file mode 100644 index 28d6e7c42..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/EnumHasManySpec.groovy +++ /dev/null @@ -1,50 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import spock.lang.Issue -import spock.lang.Specification - -/** - * @author Graeme Rocher - */ -class EnumHasManySpec extends GormDatastoreSpec{ - - - @Override - List getDomainClasses() { - [Animal] - } - - @Issue('GRAILS-9882') - void "Test that a collection of enums can be persisted"() { - when:"A domain class with a collection of enum instance is saved" - Animal zebra = new Animal(name: 'zebra') - zebra.addToTraits(Trait.FOUR_LEGS) - zebra.addToTraits(Trait.TAIL) - zebra.addToTraits(Trait.STRIPES) - zebra.save(flush:true) - session.clear() - - then:"The results are correct" - Animal.findByName('zebra').traits.size() == 3 - } -} - -@Entity -class Animal { - - Long id - Set traits - static hasMany = [traits: Trait] - - String name -} - -enum Trait { - - TAIL, - FOUR_LEGS, - SPOTS, - STRIPES -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/HasManyDefaultMappedBySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/HasManyDefaultMappedBySpec.groovy deleted file mode 100644 index aa35200d0..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/HasManyDefaultMappedBySpec.groovy +++ /dev/null @@ -1,47 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import org.grails.datastore.mapping.model.types.Association - -import spock.lang.Ignore - -class HasManyDefaultMappedBySpec extends GormDatastoreSpec { - - @Ignore - void "Test that has-many with multiple potential matches for the other side matches correctly"() { - - when:"A has many with multiple potential matching sides is retrieved" - def entity = session.datastore.mappingContext.getPersistentEntity(MyDomain.name) - Association p = entity.getPropertyByName("childs") - - then:"The other side is correctly mapped" - p != null - p.inverseSide != null - p.inverseSide.name == 'parent' - } - - @Override - List getDomainClasses() { - [MyDomain, ChildDomain] - } -} - -@Entity -class MyDomain { - Long id - Set childs - static hasMany = [childs:ChildDomain] -} - -@Entity -class ChildDomain { - Long id - static belongsTo = [parent:MyDomain] - - def getSomething() {} - def myService - - MyDomain parent -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/HasOneSetInverseSideSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/HasOneSetInverseSideSpec.groovy deleted file mode 100644 index a3addab13..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/HasOneSetInverseSideSpec.groovy +++ /dev/null @@ -1,51 +0,0 @@ -package org.grails.datastore.gorm - -import grails.persistence.Entity -import spock.lang.Issue -import grails.gorm.tests.GormDatastoreSpec - -class HasOneSetInverseSideSpec extends GormDatastoreSpec{ - - @Issue('GRAILS-8757') - void "Test that saving a one-to-one automatically sets the inverse side"() { - when:"A bidirectional one-to-one is saved" - def address = new HouseAddress(street:"Street 001") - def house = new House(name:"Some house", address: address) - - house.save(flush:true) - - then:"The inverse side is autmotically set" - house.id != null - address.house != null - - when:"The association is queried" - session.clear() - house = House.get(house.id) - - then:"The data model is valid" - house.id != null - house.address != null - house.address.house != null - } - - @Override - List getDomainClasses() { - [House, HouseAddress] - } -} - -@Entity -class House { - Long id - String name - - HouseAddress address - static hasOne = [address: HouseAddress] -} - -@Entity -class HouseAddress { - Long id - String street - House house -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/InheritanceWithOneToManySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/InheritanceWithOneToManySpec.groovy deleted file mode 100644 index 2cad64d45..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/InheritanceWithOneToManySpec.groovy +++ /dev/null @@ -1,48 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import spock.lang.Issue - -class InheritanceWithOneToManySpec extends GormDatastoreSpec{ - - @Issue('GRAILS-9010') - void "Test that a one-to-many cascades to an association featuring inheritance"() { - when:"A domain model with an association featuring inheritance is saved" - def group = new Group(name:"my group") - def subMember = new SubMember(name:"my name",extraName:"extra name",externalId:'blah') - group.addToMembers subMember - group.save(failOnError:true, flush:true) - session.clear() - - then:"The association is correctly saved" - Group.count() == 1 - SubMember.count() == 1 - } - - @Override - List getDomainClasses() { - [Group, Member, SubMember] - } -} - -@Entity -class Group { - Long id - String name - static hasMany = [members:Member] - Collection members -} - -@Entity -class Member { - Long id - String name - String externalId -} - -@Entity -class SubMember extends Member { - String extraName -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/ManyToManySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/ManyToManySpec.groovy deleted file mode 100644 index 2842a7a4e..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/ManyToManySpec.groovy +++ /dev/null @@ -1,45 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class ManyToManySpec extends GormDatastoreSpec { - - void "Test save and load many-to-many association"() { - given:"A many-to-many association" - Account account = new Account().save() - assert account - - account.addToInvoices(new Invoice()) - account.save(flush:true) - session.clear() - - when:"The association is loaded" - account = Account.get(account.id) - - then:"The results are correct" - account != null - account.invoices.size() == 1 - account.invoices.iterator().next().accounts.size() == 1 - } - - @Override - List getDomainClasses() { - [Account, Invoice] - } -} - -@Entity -class Account { - Long id - Set invoices - static hasMany = [invoices: Invoice] -} - -@Entity -class Invoice { - Long id - static belongsTo = [Account] - Set accounts - static hasMany = [accounts: Account] -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/NestedAssociationQuerySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/NestedAssociationQuerySpec.groovy deleted file mode 100644 index ef1192cfc..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/NestedAssociationQuerySpec.groovy +++ /dev/null @@ -1,131 +0,0 @@ -package org.grails.datastore.gorm - -import javax.persistence.Entity -import grails.gorm.tests.GormDatastoreSpec - -class NestedAssociationQuerySpec extends GormDatastoreSpec{ - - void "Test that a join query can be applied to a nested association"() { - given:"A domain multipe with nested asssociations" - def qText = 'What is your gender?' - def genderQuestion = createQuestion(qText) - def femaleAnswer = createAnswer('Female', genderQuestion) - def userOpinion = createUserOpinion(femaleAnswer) - - when:"The association is queried" - def c = UserOpinion.createCriteria() - def femaleCnt = c.count { - answers { - and { - question { - eq('text', qText) - } - eq('text', 'Female') - } - } - } - - then:"The right result is returned" - femaleCnt == 1 - } - - void "test join query for 3-level to-one association"() { - when:"A domain model 3 levels deep is created" - new Release(name:"Grails",milestoneCycle: new MilestoneCycle(name:"1.0",department:new Department(name:"dep A").save()).save()).save(flush:true) - session.clear() - Release r = Release.get(1) - - then:"The domain model is correctly populated" - Release.count() == 1 - MilestoneCycle.count() == 1 - Department.count() == 1 - r != null - r.milestoneCycle != null - r.milestoneCycle.department != null - - when:"The domain model is queried" - - r = Release.createCriteria().get() { - milestoneCycle { - department{ - eq('name', 'dep A') - } - } - } - - then:"The right result is returned" - r != null - r.milestoneCycle != null - r.milestoneCycle.department != null - } - - private Question createQuestion(String qText) { - new Question(text: qText).save(flush: true) - } - - private Answer createAnswer(String aText, Question q) { - new Answer(text: aText, question: q).save(flush: true) - } - - private UserOpinion createUserOpinion(Answer answer) { - def userOpinion = new UserOpinion() - userOpinion.answers << answer - - userOpinion.save(flush: true) - } - - @Override - List getDomainClasses() { - [UserOpinion, Answer, Question, Release, Department, MilestoneCycle] - } -} - -@Entity -class UserOpinion { - Long id - Set answers = [] - static hasMany = [answers: Answer] -} - -@Entity -class Answer { - - Long id - String text - Question question - - static constraints = { - text(blank: false) - } -} - -@Entity -class Question { - - Long id - String text - - static constraints = { - text(blank: false) - } -} - -@Entity -class Release { - Long id - String name - MilestoneCycle milestoneCycle -} - -@Entity -class MilestoneCycle { - Long id - String name - Department department -} - -@Entity -class Department { - Long id - String name -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/NestedCriteriaWithNamedQuerySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/NestedCriteriaWithNamedQuerySpec.groovy deleted file mode 100644 index b007062d9..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/NestedCriteriaWithNamedQuerySpec.groovy +++ /dev/null @@ -1,62 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity -import spock.lang.Issue - -/** - * @author Graeme Rocher - */ -class NestedCriteriaWithNamedQuerySpec extends GormDatastoreSpec{ - - @Issue('GRAILS-9497') - void "Test that nested criteria work with named queries"() { - given:"A domain model with 3 levels of association" - Seller seller = new Seller() - Ticket ticket = new Ticket() - seller.addToTickets(ticket) - seller.save(flush:true) - Purchase purchase = new Purchase() - ticket.addToPurchases(purchase) - purchase.save(flush: true) - ticket.save(flush: true) - session.clear() - when:"The data is queried" - def results = Purchase.myNamedQuery(seller).list() - - then:"Results are returned" - results != null - } - - @Override - List getDomainClasses() { - [Seller, Ticket, Purchase] - } -} -@Entity -class Seller { - Long id - Set tickets - static hasMany = [tickets:Ticket] -} -@Entity -class Ticket { - Long id - Seller seller - Set purchases - static belongsTo = [seller:Seller] - static hasMany = [purchases:Purchase] -} -@Entity -class Purchase { - Long id - Ticket ticket - static belongsTo = [ticket:Ticket] - static namedQueries = { - myNamedQuery { Seller seller -> - ticket{ - eq('seller',seller) - } - } - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/NotNullQuerySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/NotNullQuerySpec.groovy deleted file mode 100644 index 1cdcb7d40..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/NotNullQuerySpec.groovy +++ /dev/null @@ -1,123 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class NotNullQuerySpec extends GormDatastoreSpec { - - void "Test query of null value with dynamic finder"() { - given: - new NullMe(name:"Bob", job:"Builder").save() - new NullMe(name:"Fred").save() - - when: - def results = NullMe.findAllByJobIsNull() - - then: - results.size() == 1 - results[0].name == "Fred" - - when: - results = NullMe.findAllByJobIsNotNull() - - then: - results.size() == 1 - results[0].name == "Bob" - } - - void "Test query of null value with criteria query"() { - given: - new NullMe(name:"Bob", job:"Builder").save() - new NullMe(name:"Fred").save() - - when: - def results = NullMe.withCriteria { isNull "job" } - - then: - results.size() == 1 - results[0].name == "Fred" - - when: - results = NullMe.withCriteria { isNotNull "job" } - - then: - results.size() == 1 - results[0].name == "Bob" - } - - void "Test query of null value with dynamic finder on association"() { - given: - new NullMe(name:"Bob", other: new NullOther(name: 'stuff').save()).save() - new NullMe(name:"Fred").save() - - when: - def results = NullMe.findAllByOtherIsNull() - - then: - results.size() == 1 - results[0].name == "Fred" - - when: - results = NullMe.findAllByOtherIsNotNull() - - then: - results.size() == 1 - results[0].name == "Bob" - } - - void "Test query of null value with criteria query on association"() { - given: - new NullMe(name:"Bob", other: new NullOther(name: 'stuff').save()).save() - new NullMe(name:"Fred").save() - - when: - def results = NullMe.withCriteria { isNull "other" } - - then: - results.size() == 1 - results[0].name == "Fred" - - when: - results = NullMe.withCriteria { isNotNull "other" } - - then: - results.size() == 1 - results[0].name == "Bob" - } - - @Override - List getDomainClasses() { - [NullMe, NullOther] - } -} - -@Entity -class NullMe { - Long id - String name - String job - NullOther other - - static constraints = { - job nullable:true - other nullbale:true - } - - static mapping = { - job index:true - } -} - -@Entity -class NullOther { - Long id - String name - - static constraints = { - job nullable:true - } - - static mapping = { - job index:true - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/OneToOneWithProxiesSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/OneToOneWithProxiesSpec.groovy deleted file mode 100644 index fa3bfd29f..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/OneToOneWithProxiesSpec.groovy +++ /dev/null @@ -1,63 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.Face -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Nose -import grails.gorm.tests.Pet -import org.grails.datastore.mapping.proxy.EntityProxy - -/** - * @author Graeme Rocher - */ -class OneToOneWithProxiesSpec extends GormDatastoreSpec { - - def "Test persist and retrieve unidirectional many-to-one"() { - given:"A domain model with a many-to-one" - def person = new grails.gorm.tests.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.owner instanceof EntityProxy - pet.ownerId == person.id - !pet.owner.isInitialized() - pet.owner.firstName == "Fred" - pet.owner.isInitialized() - } - - 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) - - then:"The domain model is valid" - - 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" - } -} \ No newline at end of file diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/OrderBySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/OrderBySpec.groovy deleted file mode 100644 index 4ce118883..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/OrderBySpec.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.TestEntity -import grails.gorm.tests.ChildEntity - -/** - * @author Daniel Wiell - */ -class OrderBySpec extends GormDatastoreSpec { - def setup() { - def age = 40 - ["Bob", "Fred", "Barney", "Frank", "Joe", "Ernie"].each { - new TestEntity(name: it, age: age++, child: new ChildEntity(name: "$it Child")).save() - } - } - - def 'Test order by property name with dynamic finder returning first result'() { - when: - def result = TestEntity.findByAgeGreaterThanEquals(40, [sort: "age", order: 'desc']) - - then: - 45 == result.age - } - - def 'Test order by property name with dynamic finder using max'() { - when: - def results = TestEntity.findAllByAgeGreaterThanEquals(40, [sort: "age", order: 'desc', max: 1]) - - then: - 45 == results[0].age - } - - def 'Test order by with list() method using max'() { - when: - def results = TestEntity.list(sort: "age", order: 'desc', max: 1) - - then: - 45 == results[0].age - } - - def 'Test order by with criteria using maxResults'() { - when: - def results = TestEntity.withCriteria { - order 'age', 'desc' - maxResults 1 - } - - then: - 45 == results[0].age - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/QueryAssociationSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/QueryAssociationSpec.groovy deleted file mode 100644 index e87fd06df..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/QueryAssociationSpec.groovy +++ /dev/null @@ -1,338 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.ChildEntity -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.PlantCategory -import grails.gorm.tests.TestEntity - -class QueryAssociationSpec extends GormDatastoreSpec { - - void "Test query one-to-one association"() { - given: - new TestEntity(name:"Bob", age: 44, child:new ChildEntity(name:"Nick")).save(flush:true) - new TestEntity(name:"Fred", age: 32, child:new ChildEntity(name:"Jeff")).save(flush:true) - new TestEntity(name:"Charlie", age: 38, child:new ChildEntity(name:"Rosie")).save(flush:true) - new TestEntity(name:"Joe", age: 38, child:new ChildEntity(name:"Jake")).save(flush:true) - - when: "A query on the child association with an equals criterion is executed" - def results = TestEntity.withCriteria { - child { - eq 'name', 'Jeff' - } - } - then: "Check that the entity named Fred is returned" - TestEntity.count() == 4 - results.size() == 1 - results[0].name == "Fred" - - when: "A like criterion is executed on the child association" - results = TestEntity.withCriteria { - child { - like 'name', 'J%' - } - order "name" - } - - then: "Check that we get 2 results back" - results.size() == 2 - results[0].name == "Fred" - results[1].name == "Joe" - - when: "An ilike criterion is executed on the child association" - results = TestEntity.withCriteria { - child { - ilike 'name', 'j%' - } - order "name" - } - - then: "Check that we get 2 results back" - results.size() == 2 - results[0].name == "Fred" - results[1].name == "Joe" - - when: "An ilike criterion is executed on the entity" - results = TestEntity.withCriteria { - ilike 'name', '%e%' - order "name" - } - - then: "Check that we get 2 results back" - results.size() == 3 - results[0].name == "Charlie" - results[1].name == "Fred" - results[2].name == "Joe" - - when: "A not equals criterion is executed in a child association" - results = TestEntity.withCriteria { - child { - ne 'name', 'Rosie' - } - order "name" - } - - then: "Check that we get 3 results back" - results.size() == 3 - results[0].name == "Bob" - results[1].name == "Fred" - results[2].name == "Joe" - - when: "A between query is used" - results = TestEntity.withCriteria { - child { - between 'id', 1L, 2L - } - order "name" - } - - then: "Check we get the correct results" - results.size() == 2 - results[0].name == "Bob" - results[1].name == "Fred" - - when: "A greater than query is used" - results = TestEntity.withCriteria { - child { - gt 'id', 2L - } - order "name" - } - - then: "Check we get the correct results" - results.size() == 2 - results[0].name == "Charlie" - results[1].name == "Joe" - - when: "A less than query is used" - results = TestEntity.withCriteria { - child { - lt 'id', 3L - } - order "name" - } - - then: "Check we get the correct results" - results.size() == 2 - results[0].name == "Bob" - results[1].name == "Fred" - - when: "An in query is used" - results = TestEntity.withCriteria { - child { - inList 'name', ["Nick", "Rosie"] - } - order "name" - } - - then: "We get Bob and Charlie back" - - results.size() == 2 - results[0].name == "Bob" - results[1].name == "Charlie" - - when: "Multiple child criterion are used" - results = TestEntity.withCriteria { - child { - inList 'name', ["Nick", "Rosie"] - gt 'id', 2L - } - order "name" - } - - then: "We get the expected results back" - results.size() == 1 - results[0].name == "Charlie" - - when: "A disjunction is used" - results = TestEntity.withCriteria { - child { - or { - inList 'name', ["Nick", "Rosie"] - gt 'id', 2L - } - } - order "name" - } - - then: "We get the expected results back" - - results.size() == 3 - results[0].name == "Bob" - results[1].name == "Charlie" - results[2].name == "Joe" - - when: "A conjuntion is used" - results = TestEntity.withCriteria { - child { - and { - inList 'name', ["Nick", "Rosie"] - gt 'id', 2L - } - } - order "name" - } - - then: "We get the expected results back" - results.size() == 1 - results[0].name == "Charlie" - } - - void "Test query one-to-many association"() { - given: - new PlantCategory(name:"Tropical") - .addToPlants(name:"Pineapple") - .addToPlants(name:"Mango") - .addToPlants(name:"Lychee") - .save() - new PlantCategory(name:"Veg") - .addToPlants(name:"Cabbage", goesInPatch:true) - .addToPlants(name:"Carrot", goesInPatch:true) - .addToPlants(name:"Pumpkin", goesInPatch:true) - .addToPlants(name:"Tomatoe") - .save(flush:true) - new PlantCategory(name:"Nuts") - .addToPlants(name:"Walnut") - .addToPlants(name:"Coconut") - .save(flush:true) - - when: "The session is cleared" - session.clear() - def categories = PlantCategory.list(sort:"name") - - then: "Check that the state of the data is correct" - - categories.size() == 3 - categories[0] instanceof PlantCategory - categories[0].plants?.size() == 2 - - when: "A query on the child association with an equals criterion is executed" - def results = PlantCategory.withCriteria { - plants { - eq 'name', 'Mango' - } - } - - then: "Check that the Tropical plant is returned" - results.size() == 1 - results[0].name == "Tropical" - - when: "A like criterion is executed on the child association" - results = PlantCategory.withCriteria { - plants { - like 'name', 'P%' - } - order "name" - } - - then: "Check that we get 2 results back" - results.size() == 2 - results[0].name == "Tropical" - results[1].name == "Veg" - - when: "A not equals criterion is executed in a child association" - results = PlantCategory.withCriteria { - plants { - ne 'name', 'Carrot' - } - order "name" - } - - then: "Check that we get 3 results back" - results.size() == 3 - - when: "A between query is used" - results = PlantCategory.withCriteria { - plants { - between 'id', 3L, 5L - } - order "name" - } - - then: "Check we get the correct results" - results.size() == 2 - results[0].name == "Tropical" - results[1].name == "Veg" - - when: "A greater than query is used" - results = PlantCategory.withCriteria { - plants { - gt 'id', 5L - } - order "name" - } - - then: "Check we get the correct results" - results.size() == 2 - results[0].name == "Nuts" - results[1].name == "Veg" - - when: "A less than query is used" - results = PlantCategory.withCriteria { - plants { - lt 'id', 5L - } - order "name" - } - - then: "Check we get the correct results" - results.size() == 2 - results[0].name == "Tropical" - results[1].name == "Veg" - - when: "An in query is used" - results = PlantCategory.withCriteria { - plants { - inList 'name', ['Mango', 'Walnut'] - } - order "name" - } - then: "We get Tropical and Nuts back" - results.size() == 2 - results[0].name == "Nuts" - results[1].name == "Tropical" - - when: "Multiple child criterion are used" - results = PlantCategory.withCriteria { - plants { - like 'name', 'P%' - eq 'goesInPatch', true - } - order "name" - } - - then: "We get the expected results back" - results.size() == 1 - results[0].name == 'Veg' - - when: "A disjunction is used" - results = PlantCategory.withCriteria { - plants { - or { - like 'name', 'P%' - eq 'goesInPatch', true - } - } - order "name" - } - - then: "We get the expected results back" - results.size() == 2 - results[0].name == 'Tropical' - results[1].name == 'Veg' - - when: "A conjuntion is used" - results = PlantCategory.withCriteria { - plants { - and { - like 'name', 'P%' - eq 'goesInPatch', true - } - } - order "name" - } - - then: "We get the expected results back" - results.size() == 1 - results[0].name == 'Veg' - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/QueryNonIndexedPropertySpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/QueryNonIndexedPropertySpec.groovy deleted file mode 100644 index 11f4619b4..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/QueryNonIndexedPropertySpec.groovy +++ /dev/null @@ -1,47 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class QueryNonIndexedPropertySpec extends GormDatastoreSpec { - - @Override - List getDomainClasses() { - [Company, CompanyAddress] - } - - def "Test that we can query a property that has no indices specified"() { - - given:"A valid set of persisted domain instances" - def address = new CompanyAddress(postCode:"30483").save() - def person = new Company(name:"Bob", address: address) - person.save(flush:true) - - when: "An indexed property is queried" - def found = Company.findByName("Bob") - - then: "A result is returned" - found != null - found.name == "Bob" - - when: "A non-indexed property is queried" - found = Company.findByAddress(address) - - then: "A result is returned" - found != null - found.name == "Bob" - } -} - -@Entity -class Company { - Long id - String name - CompanyAddress address -} - -@Entity -class CompanyAddress { - Long id - String postCode -} 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 deleted file mode 100644 index 65ffcd3a5..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/SaveWithFailOnErrorDefaultSpec.groovy +++ /dev/null @@ -1,77 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.validation.ValidationException -import org.codehaus.groovy.grails.commons.GrailsDomainConfigurationUtil -import org.codehaus.groovy.grails.validation.ConstrainedProperty -import org.grails.datastore.mapping.annotation.Entity -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -class SaveWithFailOnErrorDefaultSpec extends GormDatastoreSpec { - @Override - List getDomainClasses() { - [TestProduct] - } - - def setup() { - def validator = [supports: {Class cls -> true}, - validate: {Object target, Errors errors -> - def constrainedProperties = GrailsDomainConfigurationUtil.evaluateConstraints(TestProduct) - for (ConstrainedProperty cp in constrainedProperties.values()) { - cp.validate(target, target[cp.propertyName], errors) - } - }] as Validator - - final context = session.datastore.mappingContext - final entity = context.getPersistentEntity(TestProduct.name) - context.addEntityValidator(entity, validator) - } - - void "test save with fail on error default"() { - when: "A product is saved with fail on error default true" - TestProduct.currentGormInstanceApi().failOnError = true - def p = new TestProduct() - p.save() - - then:"Validation exception thrown" - thrown(ValidationException) - - when: "A product is saved with fail on error default false" - TestProduct.currentGormInstanceApi().failOnError = false - p = new TestProduct() - def result = p.save() - - then:"The save returns false" - !result - } - - void "test override fail on error default"() { - when: "A product is saved with fail on error override to false" - TestProduct.currentGormInstanceApi().failOnError = true - def p = new TestProduct() - def result = p.save(failOnError: false, flush: true) - - then:"The save returns false" - !result - - when: "A product is saved with fail on error override to true" - TestProduct.currentGormInstanceApi().failOnError = false - p = new TestProduct() - p.save(failOnError: true) - - then:"Validation exception thrown" - thrown(ValidationException) - } -} - -@Entity -class TestProduct { - Long id - String name - - static constraints = { - //noinspection GroovyAssignabilityCheck - name(nullable: false) - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/Setup.groovy deleted file mode 100644 index 0a7bfb4b5..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ /dev/null @@ -1,98 +0,0 @@ -package org.grails.datastore.gorm - -import org.grails.datastore.gorm.events.AutoTimestampEventListener -import org.grails.datastore.gorm.events.DomainEventListener -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.engine.types.AbstractMappingAwareCustomTypeMarshaller -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.query.Query.Between -import org.grails.datastore.mapping.query.Query.PropertyCriterion -import org.grails.datastore.mapping.simple.SimpleMapDatastore -import org.grails.datastore.mapping.simple.query.SimpleMapQuery -import org.grails.datastore.mapping.simple.query.SimpleMapResultList -import org.grails.datastore.mapping.transactions.DatastoreTransactionManager -import org.springframework.context.support.GenericApplicationContext -import org.springframework.util.StringUtils -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -/** - * @author graemerocher - */ -class Setup { - - static destroy() { - // noop - } - static Session setup(classes) { - def ctx = new GenericApplicationContext() - ctx.refresh() - def simple = new SimpleMapDatastore(ctx) - - simple.mappingContext.mappingFactory.registerCustomType(new AbstractMappingAwareCustomTypeMarshaller(Birthday) { - @Override - protected Object writeInternal(PersistentProperty property, String key, Birthday value, Map nativeTarget) { - if (value == null) { - nativeTarget.remove(key) - return null - } - - final converted = value.date.time - nativeTarget.put(key, converted) - return converted - } - - @Override - protected void queryInternal(PersistentProperty property, String key, PropertyCriterion criterion, SimpleMapResultList nativeQuery) { - SimpleMapQuery query = nativeQuery.query - def handler = query.handlers[criterion.getClass()] - - if (criterion instanceof Between) { - criterion.from = criterion.from.date.time - criterion.to = criterion.to.date.time - nativeQuery.results << handler?.call(criterion, property) ?: [] - } - else { - criterion.value = criterion.value.date.time - nativeQuery.results << handler?.call(criterion, property) ?: [] - } - } - - @Override - protected Birthday readInternal(PersistentProperty property, String key, Map nativeSource) { - final num = nativeSource.get(key) - if (num instanceof Long) { - return new Birthday(new Date(num)) - } - return null - } - }) - for (cls in classes) { - simple.mappingContext.addPersistentEntity(cls) - } - - PersistentEntity entity = simple.mappingContext.persistentEntities.find { - PersistentEntity e -> e.name.contains("TestEntity")} - - simple.mappingContext.addEntityValidator(entity, [ - supports: { Class c -> true }, - validate: { Object o, Errors errors -> - if (!StringUtils.hasText(o.name)) { - errors.rejectValue("name", "name.is.blank") - } - } - ] as Validator) - - def enhancer = new GormEnhancer(simple, new DatastoreTransactionManager(datastore: simple)) - enhancer.enhance() - - simple.mappingContext.addMappingContextListener({ e -> enhancer.enhance e } as MappingContext.Listener) - - simple.applicationContext.addApplicationListener new DomainEventListener(simple) - simple.applicationContext.addApplicationListener new AutoTimestampEventListener(simple) - - simple.connect() - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/SimpleMapTestSuite.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/SimpleMapTestSuite.groovy deleted file mode 100644 index c09f8974e..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/SimpleMapTestSuite.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package org.grails.datastore.gorm - -import org.junit.runner.RunWith -import org.junit.runners.Suite -import org.junit.runners.Suite.SuiteClasses -import grails.gorm.tests.* - -/** - * @author graemerocher - */ -@RunWith(Suite) -@SuiteClasses([ -// DomainEventsSpec - OneToManySpec -]) -class SimpleMapTestSuite { -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/UUIIdentifierSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/UUIIdentifierSpec.groovy deleted file mode 100644 index ac22aeae4..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/UUIIdentifierSpec.groovy +++ /dev/null @@ -1,56 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -class UUIIdentifierSpec extends GormDatastoreSpec { - - void "Test that a UUID identifier is correctly generated"() { - when:"A domain with a UUID is saved" - def dm = new DocumentModel(name: "My Doc").save() - - then:"The UUID is correctly generated" - dm != null - dm.id != null - DocumentModel.count() == 1 - - when:"Another entity is saved" - new DocumentModel(name: "Another").save() - then:"There are 2" - DocumentModel.count() == 2 - } - - @Override - List getDomainClasses() { - [DocumentModel] - } -} - -@Entity -class DocumentModel { - static final SCORE = 40 - - String id // UUID , for replications / optimization - String name - String description = '' - - Date dateCreated - Date lastUpdated - - long estimatedScore = 0 - long score = 0 - - Map parameters = new HashMap() - - static mapping = { - id generator:'uuid' - name index: 'idx_doc_name' - description size:0..300, nullable:true - } - - static constraints = { - estimatedScore min: 0l - score min: 0l - name blank: false, unique: 'workspace' - } -} 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 deleted file mode 100644 index d2bfef154..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/UniqueConstraintGroupSpec.groovy +++ /dev/null @@ -1,101 +0,0 @@ -package org.grails.datastore.gorm - -import grails.gorm.tests.GormDatastoreSpec -import grails.persistence.Entity - -import org.codehaus.groovy.grails.commons.GrailsDomainConfigurationUtil -import org.codehaus.groovy.grails.validation.ConstrainedProperty -import org.springframework.validation.Errors -import org.springframework.validation.Validator - -import spock.lang.Issue - -class UniqueConstraintGroupSpec extends GormDatastoreSpec{ - - @Issue(['GRAILS-8656', 'GRAILS-10178']) - void "Test null uniqueness handling"() { - - given:"Some test users" - UserClass user1 = createTestUser(1) - UserClass user2 = createTestUser(1) - - user1.save(flush:true) - - when:"another user with same userId" - user2.validate() - def errors = user2.errors.allErrors - - then:"(null) dateDeleted should pass uniqueness test" - errors.size() == 0 - - when: "another user with same userId, and different (not null) dateDeleted is saved" - user2.dateDeleted = new Date() - - then:"validation passes" - user2.validate() - - when: "Now check the same when user1 has not null dateDeleted" - user1.dateDeleted = user2.dateDeleted - then:"The save succeeds" - user1.save(flush:true) - - when: "user1 and user 2 have same userid / dateDeleted" - user2.validate() - errors = user2.errors.allErrors - - then:"should fail uniqueness" - errors.size() == 1 - errors[0].field == "userId" - errors[0].code == "unique" - - when: "user 2 has not date deleted different from user 1" - user2.dateDeleted = (user1.dateDeleted + 1) - then: "passes uniqueness" - user2.validate() - - when: "user 2 has null date deleted" - user2.dateDeleted = null - then: "passes uniqueness" - user2.validate() - } - - @Override - List getDomainClasses() { - [UserClass] - } - - void setup() { - - def groupValidator = [supports: {Class cls -> true}, - validate: {Object target, Errors errors -> - def constrainedProperties = GrailsDomainConfigurationUtil.evaluateConstraints(UserClass) - for (ConstrainedProperty cp in constrainedProperties.values()) { - cp.validate(target, target[cp.propertyName], errors) - } - }] as Validator - - final context = session.datastore.mappingContext - final entity = context.getPersistentEntity(UserClass.name) - context.addEntityValidator(entity, groupValidator) - } - - private createTestUser(Integer suffix) { - def val = new UserClass() - val.dateDeleted = null - val.userId = "UserId${suffix}" - val - } -} - -@Entity -class UserClass { - - Long id - String userId - Date dateDeleted - - static constraints = { - userId blank: false, unique: 'dateDeleted' - dateDeleted nullable: true - } -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/test/DatastoreUnitTestCaseSpec.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/test/DatastoreUnitTestCaseSpec.groovy deleted file mode 100644 index f50b64327..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/test/DatastoreUnitTestCaseSpec.groovy +++ /dev/null @@ -1,73 +0,0 @@ -package org.grails.datastore.test - -import grails.datastore.test.DatastoreUnitTestMixin -import spock.lang.Specification - -/** - * @author graemerocher - */ -class DatastoreUnitTestCaseSpec extends Specification { - - // NOTE: we run the same test twice to ensure setup/teardown is cleaning up properly - void "Test mock domain 1"() { - given: - TestTests tt = new TestTests() - tt.metaClass.mixin DatastoreUnitTestMixin - - when: - tt.setUp() - tt.testCRUD() - tt.tearDown() - - then: - true == true - } - - void "Test mock domain 2"() { - given: - TestTests tt = new TestTests() - - tt.metaClass.mixin DatastoreUnitTestMixin - - when: - tt.setUp() - tt.testCRUD() - tt.tearDown() - - then: - true == true - } -} - -@Mixin(DatastoreUnitTestMixin) -class TestTests extends GroovyTestCase { - - protected void setUp() { - super.setUp() - connect() - } - - protected void tearDown() { - super.tearDown() - disconnect() - } - - void testCRUD() { - mockDomain TestDomain - - def t = new TestDomain(name:"Bob") - t.save() - - assert t.id != null - - t = TestDomain.get(t.id) - - assert t != null - } -} - -class TestDomain { - Long id - Long version - String name -} diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/test/SessionLifecycleTests.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/test/SessionLifecycleTests.groovy deleted file mode 100644 index 9cad1ef0f..000000000 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/test/SessionLifecycleTests.groovy +++ /dev/null @@ -1,39 +0,0 @@ -package org.grails.datastore.test - -/** - * Tests that the session is correctly shared across all operations - */ -import grails.datastore.test.DatastoreUnitTestMixin -import grails.persistence.Entity - -@Mixin(DatastoreUnitTestMixin) -class SessionLifeCycleTests extends GroovyTestCase { - - protected void tearDown() { - disconnect() - } - - void testSample() { - mockDomain(Sample) - def s = new Sample(name: "Larry") - s.save() - - assert Sample.count() == 1 - assertTrue !Sample.list().isEmpty() - } - - void testSampleMockNoSave() { - def s = new Sample(name: "Larry") - mockDomain(Sample, [s]) - - assertTrue !Sample.list().isEmpty() - } -} - -@Entity -class Sample { - Long id - Long version - String name - -} diff --git a/grails-datastore-gorm/build.gradle b/grails-datastore-gorm/build.gradle deleted file mode 100644 index c2c750695..000000000 --- a/grails-datastore-gorm/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -dependencies { - - compile project(":grails-datastore-core") -// compile "org.grails:grails-test:$grailsVersion", { -// exclude module: "grails-datastore-gorm" -// } - - compile "org.grails:grails-core:$grailsVersion" - compile("org.grails:grails-bootstrap:$grailsVersion") { - transitive = false - } - compile "org.grails:grails-async:$grailsVersion" - compile "org.slf4j:slf4j-api:$slf4jVersion" - compile "org.slf4j:jcl-over-slf4j:$slf4jVersion" -} - -def astTransformPath -jar.doFirst { - def metaInfPath = "${compileGroovy.destinationDir}/META-INF/services" - - ant.mkdir(dir:metaInfPath) - astTransformPath = new File(metaInfPath, "org.codehaus.groovy.transform.ASTTransformation") - astTransformPath.text = "org.grails.datastore.gorm.query.transform.GlobalDetachedCriteriaASTTransformation" -} -jar.doLast { - if(astTransformPath) { - ant.delete file:astTransformPath - } -} \ No newline at end of file diff --git a/grails-datastore-gorm/src/main/groovy/grails/gorm/CriteriaBuilder.java b/grails-datastore-gorm/src/main/groovy/grails/gorm/CriteriaBuilder.java deleted file mode 100644 index 6adf0e584..000000000 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/CriteriaBuilder.java +++ /dev/null @@ -1,1028 +0,0 @@ -/* Copyright (C) 2010 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 grails.gorm; - -import static org.grails.datastore.gorm.finders.DynamicFinder.populateArgumentsForCriteria; -import groovy.lang.Closure; -import groovy.lang.GroovyObjectSupport; -import groovy.lang.GroovySystem; -import groovy.lang.MetaMethod; -import groovy.lang.MetaObjectProtocol; -import groovy.lang.MissingMethodException; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import org.grails.datastore.mapping.core.Session; -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.query.AssociationQuery; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.Restrictions; -import org.grails.datastore.mapping.query.api.Criteria; -import org.grails.datastore.mapping.query.api.ProjectionList; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.springframework.util.Assert; - -/** - * Criteria builder implementation that operates against Spring datastore abstraction. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class CriteriaBuilder extends GroovyObjectSupport implements Criteria, ProjectionList { - - public static final String ORDER_DESCENDING = "desc"; - public static final String ORDER_ASCENDING = "asc"; - - private static final String ROOT_DO_CALL = "doCall"; - private static final String ROOT_CALL = "call"; - private static final String SCROLL_CALL = "scroll"; - - protected Class targetClass; - protected Session session; - protected Query query; - private boolean uniqueResult = false; - private boolean paginationEnabledList; - protected List orderEntries = new ArrayList(); - private List logicalExpressionStack = new ArrayList(); - protected MetaObjectProtocol queryMetaClass; - protected Query.ProjectionList projectionList; - protected PersistentEntity persistentEntity; - - public CriteriaBuilder(final Class targetClass, final Session session) { - Assert.notNull(targetClass, "Argument [targetClass] cannot be null"); - Assert.notNull(session, "Argument [session] cannot be null"); - - persistentEntity = session.getDatastore().getMappingContext().getPersistentEntity( - targetClass.getName()); - if (persistentEntity == null) { - throw new IllegalArgumentException("Class [" + targetClass.getName() + - "] is not a persistent entity"); - } - - this.targetClass = targetClass; - this.session = session; - } - - public CriteriaBuilder(final Class targetClass, final Session session, final Query query) { - this(targetClass, session); - this.query = query; - } - - public void setUniqueResult(boolean uniqueResult) { - this.uniqueResult = uniqueResult; - } - - public Criteria cache(boolean cache) { - query.cache(cache); - return this; - } - - public Criteria join(String property) { - query.join(property); - return this; - } - - public Query.ProjectionList id() { - if (projectionList != null) { - projectionList.id(); - } - return projectionList; - } - - /** - * Count the number of records returned - * @return The project list - */ - - public Query.ProjectionList count() { - if (projectionList != null) { - projectionList.count(); - } - return projectionList; - } - - /** - * Projection that signifies to count distinct results - * - * @param property The name of the property - * @return The projection list - */ - public ProjectionList countDistinct(String property) { - if (projectionList != null) { - projectionList.countDistinct(property); - } - return projectionList; - } - - /** - * Projection that signifies to return only distinct results - * - * @return The projection list - */ - public ProjectionList distinct() { - if (projectionList != null) { - projectionList.distinct(); - } - return projectionList; - } - - /** - * Projection that signifies to return only distinct results - * - * @param property The name of the property - * @return The projection list - */ - public ProjectionList distinct(String property) { - if (projectionList != null) { - projectionList.distinct(property); - } - return projectionList; - } - - /** - * Count the number of records returned - * @return The project list - */ - public ProjectionList rowCount() { - return count(); - } - - /** - * A projection that obtains the value of a property of an entity - * @param name The name of the property - * @return The projection list - */ - public ProjectionList property(String name) { - if (projectionList != null) { - projectionList.property(name); - } - return projectionList; - } - - /** - * Computes the sum of a property - * - * @param name The name of the property - * @return The projection list - */ - public ProjectionList sum(String name) { - if (projectionList != null) { - projectionList.sum(name); - } - return projectionList; - } - - /** - * Computes the min value of a property - * - * @param name The name of the property - * @return The projection list - */ - public ProjectionList min(String name) { - if (projectionList != null) { - projectionList.min(name); - } - return projectionList; - } - - /** - * Computes the max value of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - public ProjectionList max(String name) { - if (projectionList != null) { - projectionList.max(name); - } - return projectionList; - } - - /** - * Computes the average value of a property - * - * @param name The name of the property - * @return The PropertyProjection instance - */ - public ProjectionList avg(String name) { - if (projectionList != null) { - projectionList.avg(name); - } - return projectionList; - } - - /** - * Defines an executes a list query in a single call. Example: Foo.createCriteria.list { } - * @param callable The closure to execute - * - * @return The result list - */ - public List list(Closure callable) { - initializeQuery(); - invokeClosureNode(callable); - - return query.list(); - } - - /** - * Defines an executes a get query ( a single result) in a single call. Example: Foo.createCriteria.get { } - * - * - * @param callable The closure to execute - * - * @return A single result - */ - public Object get(Closure callable) { - initializeQuery(); - invokeClosureNode(callable); - - uniqueResult = true; - return query.singleResult(); - } - - /** - * Defines an executes a list distinct query in a single call. Example: Foo.createCriteria.listDistinct { } - * @param callable The closure to execute - * - * @return The result list - */ - public List listDistinct(Closure callable) { - initializeQuery(); - invokeClosureNode(callable); - - query.projections().distinct(); - return query.list(); - } - - public List list(Map paginateParams, Closure callable) { - initializeQuery(); - - paginationEnabledList = true; - orderEntries = new ArrayList(); - invokeClosureNode(callable); - populateArgumentsForCriteria(targetClass, query, paginateParams); - return new PagedResultList(query); - } - - /** - * Defines an executes a count query in a single call. Example: Foo.createCriteria.count { } - * @param callable The closure to execute - * - * @return The result count - */ - public Number count(Closure callable) { - initializeQuery(); - invokeClosureNode(callable); - uniqueResult = true; - query.projections().count(); - return (Number) query.singleResult(); - } - - @Override - public Object invokeMethod(String name, Object obj) { - Object[] args = obj.getClass().isArray() ? (Object[])obj : new Object[]{obj}; - - if (isCriteriaConstructionMethod(name, args)) { - - initializeQuery(); - - uniqueResult = false; - - invokeClosureNode(args[0]); - - Object result; - if (!uniqueResult) { - result = query.list(); - } - else { - result = query.singleResult(); - } - query = null; - return result; - } - - MetaMethod metaMethod = getMetaClass().getMetaMethod(name, args); - if (metaMethod != null) { - return metaMethod.invoke(this, args); - } - - metaMethod = queryMetaClass.getMetaMethod(name, args); - if (metaMethod != null) { - return metaMethod.invoke(query, args); - } - - if (args.length == 1 && args[0] instanceof Closure) { - - final PersistentProperty property = persistentEntity.getPropertyByName(name); - if (property instanceof Association) { - Association association = (Association) property; - Query previousQuery = query; - PersistentEntity previousEntity = persistentEntity; - List previousLogicalExpressionStack = logicalExpressionStack; - - Query associationQuery = null; - try { - associationQuery = query.createQuery(property.getName()); - if (associationQuery instanceof AssociationQuery) { - previousQuery.add((Query.Criterion) associationQuery); - } - query = associationQuery; - persistentEntity = association.getAssociatedEntity(); - logicalExpressionStack = new ArrayList(); - invokeClosureNode(args[0]); - return query; - } - finally { - - logicalExpressionStack = previousLogicalExpressionStack; - persistentEntity = previousEntity; - query = previousQuery; - } - } - } - - throw new MissingMethodException(name, getClass(), args); - } - - /** - * Defines projections - * - * @param callable The closure defining the projections - * @return The projections list - */ - public ProjectionList projections(Closure callable) { - projectionList = query.projections(); - invokeClosureNode(callable); - return projectionList; - } - - public Criteria and(Closure callable) { - handleJunction(new Query.Conjunction(), callable); - return this; - } - - public Criteria or(Closure callable) { - handleJunction(new Query.Disjunction(), callable); - return this; - } - - public Criteria not(Closure callable) { - handleJunction(new Query.Negation(), callable); - return this; - } - - public Criteria idEquals(Object value) { - addToCriteria(Restrictions.idEq(value)); - return this; - } - - public Criteria isEmpty(String propertyName) { - validatePropertyName(propertyName, "isEmpty"); - addToCriteria(Restrictions.isEmpty(propertyName)); - return this; - } - - public Criteria isNotEmpty(String propertyName) { - validatePropertyName(propertyName, "isNotEmpty"); - addToCriteria(Restrictions.isNotEmpty(propertyName)); - return this; - } - - public Criteria isNull(String propertyName) { - validatePropertyName(propertyName, "isNull"); - addToCriteria(Restrictions.isNull(propertyName)); - return this; - } - - public Criteria isNotNull(String propertyName) { - validatePropertyName(propertyName, "isNotNull"); - addToCriteria(Restrictions.isNotNull(propertyName)); - return this; - } - - /** - * Creates an "equals" Criterion based on the specified property name and value. - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria eq(String propertyName, Object propertyValue) { - validatePropertyName(propertyName, "eq"); - addToCriteria(Restrictions.eq(propertyName, propertyValue)); - return this; - } - - /** - * Creates a subquery criterion that ensures the given property is equal to all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria eqAll(String propertyName, Closure propertyValue) { - return eqAll(propertyName, buildQueryableCriteria(propertyValue)); - } - - @SuppressWarnings("unchecked") - private QueryableCriteria buildQueryableCriteria(Closure queryClosure) { - return new DetachedCriteria(targetClass).build(queryClosure); - } - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria gtAll(String propertyName, Closure propertyValue) { - return gtAll(propertyName, buildQueryableCriteria(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria ltAll(String propertyName, Closure propertyValue) { - return ltAll(propertyName, buildQueryableCriteria(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria geAll(String propertyName, Closure propertyValue) { - return geAll(propertyName, buildQueryableCriteria(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria leAll(String propertyName, Closure propertyValue) { - return leAll(propertyName, buildQueryableCriteria(propertyValue)); - } - - /** - * Creates a subquery criterion that ensures the given property is equal to all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria eqAll(String propertyName, QueryableCriteria propertyValue) { - validatePropertyName(propertyName, "eqAll"); - addToCriteria(new Query.EqualsAll(propertyName, propertyValue)); - return this; - } - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria gtAll(String propertyName, QueryableCriteria propertyValue) { - validatePropertyName(propertyName, "gtAll"); - addToCriteria(new Query.GreaterThanAll(propertyName, propertyValue)); - return this; - } - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria ltAll(String propertyName, QueryableCriteria propertyValue) { - validatePropertyName(propertyName, "ltAll"); - addToCriteria(new Query.LessThanAll(propertyName, propertyValue)); - return this; - } - - /** - * Creates a subquery criterion that ensures the given property is greater than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria geAll(String propertyName, QueryableCriteria propertyValue) { - validatePropertyName(propertyName, "geAll"); - addToCriteria(new Query.GreaterThanEqualsAll(propertyName, propertyValue)); - return this; - } - - /** - * Creates a subquery criterion that ensures the given property is less than all the given returned values - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria leAll(String propertyName, QueryableCriteria propertyValue) { - validatePropertyName(propertyName, "leAll"); - addToCriteria(new Query.LessThanEqualsAll(propertyName, propertyValue)); - return this; - } - - /** - * Creates an "equals" Criterion based on the specified property name and value. - * - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria idEq(Object propertyValue) { - addToCriteria(Restrictions.idEq(propertyValue)); - return this; - } - - /** - * Creates a "not equals" Criterion based on the specified property name and value. - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria ne(String propertyName, Object propertyValue) { - validatePropertyName(propertyName, "ne"); - addToCriteria(Restrictions.ne(propertyName, propertyValue)); - return this; - } - - /** - * Restricts the results by the given property value range (inclusive) - * - * @param propertyName The property name - * - * @param start The start of the range - * @param finish The end of the range - * @return A Criterion instance - */ - public Criteria between(String propertyName, Object start, Object finish) { - validatePropertyName(propertyName, "between"); - addToCriteria(Restrictions.between(propertyName, start, finish)); - return this; - } - /** - * Used to restrict a value to be greater than or equal to the given value - * @param property The property - * @param value The value - * @return The Criterion instance - */ - public Criteria gte(String property, Object value) { - validatePropertyName(property, "gte"); - addToCriteria(Restrictions.gte(property, value)); - return this; - } - - /** - * Used to restrict a value to be greater than or equal to the given value - * @param property The property - * @param value The value - * @return The Criterion instance - */ - public Criteria ge(String property, Object value) { - gte(property, value); - return this; - } - - /** - * Used to restrict a value to be greater than or equal to the given value - * @param property The property - * @param value The value - * @return The Criterion instance - */ - public Criteria gt(String property, Object value) { - validatePropertyName(property, "gt"); - addToCriteria(Restrictions.gt(property, value)); - return this; - } - - /** - * Used to restrict a value to be less than or equal to the given value - * @param property The property - * @param value The value - * @return The Criterion instance - */ - public Criteria lte(String property, Object value) { - validatePropertyName(property, "lte"); - addToCriteria(Restrictions.lte(property, value)); - return this; - } - - /** - * Used to restrict a value to be less than or equal to the given value - * @param property The property - * @param value The value - * @return The Criterion instance - */ - public Criteria le(String property, Object value) { - lte(property, value); - return this; - } - - /** - * Used to restrict a value to be less than or equal to the given value - * @param property The property - * @param value The value - * @return The Criterion instance - */ - public Criteria lt(String property, Object value) { - validatePropertyName(property, "lt"); - addToCriteria(Restrictions.lt(property, value)); - return this; - } - - /** - * Creates an like Criterion based on the specified property name and value. - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria like(String propertyName, Object propertyValue) { - validatePropertyName(propertyName, "like"); - Assert.notNull(propertyValue, "Cannot use like expression with null value"); - addToCriteria(Restrictions.like(propertyName, propertyValue.toString())); - return this; - } - - /** - * Creates an ilike Criterion based on the specified property name and value. Unlike a like condition, ilike is case insensitive - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria ilike(String propertyName, Object propertyValue) { - validatePropertyName(propertyName, "ilike"); - Assert.notNull(propertyValue, "Cannot use ilike expression with null value"); - addToCriteria(Restrictions.ilike(propertyName, propertyValue.toString())); - return this; - } - - /** - * Creates an rlike Criterion based on the specified property name and value. - * - * @param propertyName The property name - * @param propertyValue The property value - * - * @return A Criterion instance - */ - public Criteria rlike(String propertyName, Object propertyValue) { - validatePropertyName(propertyName, "like"); - Assert.notNull(propertyValue, "Cannot use like expression with null value"); - addToCriteria(Restrictions.rlike(propertyName, propertyValue.toString())); - return this; - } - - /** - * Creates an "in" Criterion based on the specified property name and list of values. - * - * @param propertyName The property name - * @param values The values - * - * @return A Criterion instance - */ - public Criteria in(String propertyName, Collection values) { - validatePropertyName(propertyName, "in"); - Assert.notNull(values, "Cannot use in expression with null values"); - addToCriteria(Restrictions.in(propertyName, values)); - return this; - } - - /** - * Creates an "in" Criterion based on the specified property name and list of values. - * - * @param propertyName The property name - * @param values The values - * - * @return A Criterion instance - */ - public Criteria inList(String propertyName, Collection values) { - in(propertyName, values); - return this; - } - - /** - * Creates an "in" Criterion based on the specified property name and list of values. - * - * @param propertyName The property name - * @param values The values - * - * @return A Criterion instance - */ - public Criteria inList(String propertyName, Object[] values) { - return in(propertyName, Arrays.asList(values)); - } - - /** - * Creates an "in" Criterion based on the specified property name and list of values. - * - * @param propertyName The property name - * @param values The values - * - * @return A Criterion instance - */ - public Criteria in(String propertyName, Object[] values) { - return in(propertyName, Arrays.asList(values)); - } - - public Criteria sizeEq(String propertyName, int size) { - validatePropertyName(propertyName, "sizeEq"); - addToCriteria(Restrictions.sizeEq(propertyName, size)); - return this; - - } - - public Criteria sizeGt(String propertyName, int size) { - validatePropertyName(propertyName, "sizeGt"); - addToCriteria(Restrictions.sizeGt(propertyName, size)); - return this; - } - - public Criteria sizeGe(String propertyName, int size) { - validatePropertyName(propertyName, "sizeGe"); - addToCriteria(Restrictions.sizeGe(propertyName, size)); - return this; - } - - public Criteria sizeLe(String propertyName, int size) { - validatePropertyName(propertyName, "sizeLe"); - addToCriteria(Restrictions.sizeLe(propertyName, size)); - return this; - } - - public Criteria sizeLt(String propertyName, int size) { - validatePropertyName(propertyName, "sizeLt"); - addToCriteria(Restrictions.sizeLt(propertyName, size)); - return this; - } - - public Criteria sizeNe(String propertyName, int size) { - validatePropertyName(propertyName, "sizeNe"); - addToCriteria(Restrictions.sizeNe(propertyName, size)); - return this; - } - - /** - * Constraints a property to be equal to a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criteria - */ - public Criteria eqProperty(String propertyName, String otherPropertyName) { - validatePropertyName(propertyName, "eqProperty"); - validatePropertyName(otherPropertyName, "eqProperty"); - addToCriteria(Restrictions.eqProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Constraints a property to be not equal to a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criteria - */ - public Criteria neProperty(String propertyName, String otherPropertyName) { - validatePropertyName(propertyName, "neProperty"); - validatePropertyName(otherPropertyName, "neProperty"); - addToCriteria(Restrictions.neProperty(propertyName, otherPropertyName)); - return this; - - } - - /** - * Constraints a property to be greater than a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criteria - */ - public Criteria gtProperty(String propertyName, String otherPropertyName) { - validatePropertyName(propertyName, "gtProperty"); - validatePropertyName(otherPropertyName, "gtProperty"); - addToCriteria(Restrictions.gtProperty(propertyName, otherPropertyName)); - return this; - - } - - /** - * Constraints a property to be greater than or equal to a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criteria - */ - public Criteria geProperty(String propertyName, String otherPropertyName) { - validatePropertyName(propertyName, "geProperty"); - validatePropertyName(otherPropertyName, "geProperty"); - addToCriteria(Restrictions.geProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Constraints a property to be less than a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criteria - */ - public Criteria ltProperty(String propertyName, String otherPropertyName) { - validatePropertyName(propertyName, "ltProperty"); - validatePropertyName(otherPropertyName, "ltProperty"); - addToCriteria(Restrictions.ltProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Constraints a property to be less than or equal to a specified other property - * - * @param propertyName The property - * @param otherPropertyName The other property - * @return This criteria - */ - public Criteria leProperty(String propertyName, String otherPropertyName) { - validatePropertyName(propertyName, "leProperty"); - validatePropertyName(otherPropertyName, "leProperty"); - addToCriteria(Restrictions.leProperty(propertyName, otherPropertyName)); - return this; - } - - /** - * Orders by the specified property name (defaults to ascending) - * - * @param propertyName The property name to order by - * @return A Order instance - */ - public Criteria order(String propertyName) { - Query.Order o = Query.Order.asc(propertyName); - if (paginationEnabledList) { - orderEntries.add(o); - } - else { - query.order(o); - } - return this; - } - - /** - * Orders by the specified property name and direction - * - * @param propertyName The property name to order by - * @param direction Either "asc" for ascending or "desc" for descending - * - * @return A Order instance - */ - public Criteria order(String propertyName, String direction) { - Query.Order o; - if (direction.equals(ORDER_DESCENDING)) { - o = Query.Order.desc(propertyName); - } - else { - o = Query.Order.asc(propertyName); - } - if (paginationEnabledList) { - orderEntries.add(o); - } - else { - query.order(o); - } - return this; - } - - protected void validatePropertyName(String propertyName, String methodName) { - if (persistentEntity == null) return; - if (propertyName == null) { - throw new IllegalArgumentException("Cannot use [" + methodName + - "] restriction with null property name"); - } - - PersistentProperty property = persistentEntity.getPropertyByName(propertyName); - if (property == null && persistentEntity.getIdentity().getName().equals(propertyName)) { - property = persistentEntity.getIdentity(); - } - if (property == null && !session.getDatastore().isSchemaless()) { - throw new IllegalArgumentException("Property [" + propertyName + - "] is not a valid property of class [" + persistentEntity + "]"); - } - } - - private void initializeQuery() { - query = session.createQuery(targetClass); - queryMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(query.getClass()); - } - - private boolean isCriteriaConstructionMethod(String name, Object[] args) { - return (name.equals(ROOT_CALL) || - name.equals(ROOT_DO_CALL) || - name.equals(SCROLL_CALL) && args.length == 1 && args[0] instanceof Closure); - } - - private void invokeClosureNode(Object args) { - if (args instanceof Closure) { - Closure callable = (Closure)args; - callable.setDelegate(this); - callable.setResolveStrategy(Closure.DELEGATE_FIRST); - callable.call(); - } - } - - private void handleJunction(Query.Junction junction, Closure callable) { - logicalExpressionStack.add(junction); - try { - if (callable != null) { - invokeClosureNode(callable); - } - } finally { - Query.Junction logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - addToCriteria(logicalExpression); - } - } - - /* - * adds and returns the given criterion to the currently active criteria set. - * this might be either the root criteria or a currently open - * LogicalExpression. - */ - protected Query.Criterion addToCriteria(Query.Criterion c) { - if (c instanceof Query.PropertyCriterion) { - Query.PropertyCriterion pc = (Query.PropertyCriterion) c; - - Object value = pc.getValue(); - if (value instanceof Closure) { - pc.setValue(buildQueryableCriteria((Closure) value)); - } - } - if (!logicalExpressionStack.isEmpty()) { - logicalExpressionStack.get(logicalExpressionStack.size() - 1).add(c); - } - else { - if (query == null) { - initializeQuery(); - } - query.add(c); - } - return c; - } - - public Query getQuery() { - return query; - } - - public void build(Closure criteria) { - if (criteria != null) { - invokeClosureNode(criteria); - } - } -} diff --git a/grails-datastore-gorm/src/main/groovy/grails/gorm/DetachedCriteria.groovy b/grails-datastore-gorm/src/main/groovy/grails/gorm/DetachedCriteria.groovy deleted file mode 100644 index 3f105f8f5..000000000 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/DetachedCriteria.groovy +++ /dev/null @@ -1,944 +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 grails.gorm - -import grails.async.Promise -import grails.async.Promises - -import javax.persistence.FetchType - -import org.codehaus.groovy.runtime.typehandling.GroovyCastException -import org.grails.datastore.gorm.async.AsyncQuery -import org.grails.datastore.gorm.finders.DynamicFinder -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.query.GormOperations -import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.model.types.Association -import org.grails.datastore.mapping.query.Projections -import org.grails.datastore.mapping.query.Query -import org.grails.datastore.mapping.query.Restrictions -import org.grails.datastore.mapping.query.Query.Criterion -import org.grails.datastore.mapping.query.Query.Junction -import org.grails.datastore.mapping.query.Query.Order -import org.grails.datastore.mapping.query.Query.Projection -import org.grails.datastore.mapping.query.Query.PropertyCriterion -import org.grails.datastore.mapping.query.Query.Order.Direction -import org.grails.datastore.mapping.query.api.Criteria -import org.grails.datastore.mapping.query.api.ProjectionList -import org.grails.datastore.mapping.query.api.QueryableCriteria - -/** - * Represents criteria that is not bound to the current connection and can be built up and re-used at a later date. - * - * @author Graeme Rocher - * @since 1.0 - */ -class DetachedCriteria implements QueryableCriteria, Cloneable, Iterable, GormOperations { - - protected List criteria = [] - protected List orders = [] - protected List projections = [] - protected Class targetClass - protected List dynamicFinders - protected Integer defaultOffset - protected Integer defaultMax - - protected List junctions = [] - protected PersistentEntity persistentEntity - protected Map fetchStrategies = [:] - protected Closure lazyQuery - - ProjectionList projectionList = new DetachedProjections(projections) - - /** - * Constructs a DetachedCriteria instance target the given class - * @param targetClass - */ - DetachedCriteria(Class targetClass) { - this.targetClass = targetClass - } - - /** - * Allow casting to a Promise - * @param c The type to cast to - * @return The cast type - */ - public N asType(Class c) { - if (c == Promise) { - return (N)Promises.createPromise { - list() - } - } - else { - throw new GroovyCastException(this, c) - } - } - - Map getFetchStrategies() { - return fetchStrategies - } - - /** - * Specifies whether a join query should be used (if join queries are supported by the underlying datastore) - * - * @param property The property - * @return The query - */ - Criteria join(String property) { - fetchStrategies[property] = FetchType.EAGER - return this - } - - /** - * Specifies whether a select (lazy) query should be used (if join queries are supported by the underlying datastore) - * - * @param property The property - * @return The query - */ - Criteria select(String property) { - fetchStrategies[property] = FetchType.LAZY - return this - } - - @Override - T getPersistentClass() { - getPersistentEntity().getJavaClass() - } - - PersistentEntity getPersistentEntity() { - if (persistentEntity == null) initialiseIfNecessary(targetClass) - return persistentEntity - } - - protected initialiseIfNecessary(Class targetClass) { - if (dynamicFinders != null) { - return - } - - try { - dynamicFinders = targetClass.gormDynamicFinders - persistentEntity = targetClass.gormPersistentEntity - } catch (MissingPropertyException mpe) { - throw new IllegalArgumentException("Class [$targetClass.name] is not a domain class") - } - } - - void add(Criterion criterion) { - applyLazyCriteria() - if (criterion instanceof PropertyCriterion) { - if (criterion.value instanceof Closure) { - criterion.value = buildQueryableCriteria(criterion.value) - } - } - if (junctions) { - junctions[-1].add criterion - } - else { - criteria << criterion - } - } - - List getCriteria() { criteria } - - List getProjections() { projections } - - List getOrders() { orders } - - /** - * Evaluate projections within the context of the given closure - * - * @param callable The callable - * @return The projection list - */ - Criteria projections(Closure callable) { - callable.delegate = projectionList - callable.call() - return this - } - - /** - * Handles a conjunction - * @param callable Callable closure - * @return This criterion - */ - Criteria and(Closure callable) { - junctions << new Query.Conjunction() - handleJunction(callable) - return this - } - - /** - * Handles a disjunction - * @param callable Callable closure - * @return This criterion - */ - Criteria or(Closure callable) { - junctions << new Query.Disjunction() - handleJunction(callable) - return this - } - - /** - * Handles a disjunction - * @param callable Callable closure - * @return This criterion - */ - Criteria not(Closure callable) { - junctions << new Query.Negation() - handleJunction(callable) - return this - } - - /** - * @see Criteria - */ - Criteria 'in'(String propertyName, Collection values) { - inList(propertyName, values) - } - - /** - * @see Criteria - */ - Criteria 'in'(String propertyName, Object[] values) { - inList(propertyName, values) - } - - /** - * @see Criteria - */ - Criteria order(String propertyName) { - orders << new Order(propertyName) - return this - } - - /** - * @see Criteria - */ - Criteria order(String propertyName, String direction) { - orders << new Order(propertyName, Direction.valueOf(direction.toUpperCase())) - return this - } - - /** - * @see Criteria - */ - Criteria inList(String propertyName, Collection values) { - add Restrictions.in(propertyName, values) - return this - } - - /** - * @see Criteria - */ - Criteria inList(String propertyName, Object[] values) { - add Restrictions.in(propertyName, Arrays.asList(values)) - return this - } - - /** - * @see Criteria - */ - Criteria sizeEq(String propertyName, int size) { - add Restrictions.sizeEq(propertyName, size) - return this - } - - /** - * @see Criteria - */ - Criteria sizeGt(String propertyName, int size) { - add Restrictions.sizeGt(propertyName, size) - return this - } - - /** - * @see Criteria - */ - Criteria sizeGe(String propertyName, int size) { - add Restrictions.sizeGe(propertyName, size) - return this - } - - /** - * @see Criteria - */ - Criteria sizeLe(String propertyName, int size) { - add Restrictions.sizeLe(propertyName, size) - return this - } - - /** - * @see Criteria - */ - Criteria sizeLt(String propertyName, int size) { - add Restrictions.sizeLt(propertyName, size) - return this - } - - /** - * @see Criteria - */ - Criteria sizeNe(String propertyName, int size) { - add Restrictions.sizeNe(propertyName, size) - return this - } - - /** - * @see Criteria - */ - Criteria eqProperty(String propertyName, String otherPropertyName) { - add Restrictions.eqProperty(propertyName,otherPropertyName) - return this - } - - /** - * @see Criteria - */ - Criteria neProperty(String propertyName, String otherPropertyName) { - add Restrictions.neProperty(propertyName,otherPropertyName) - return this - } - - /** - * @see Criteria - */ - Criteria gtProperty(String propertyName, String otherPropertyName) { - add Restrictions.gtProperty(propertyName,otherPropertyName) - return this - } - - /** - * @see Criteria - */ - Criteria geProperty(String propertyName, String otherPropertyName) { - add Restrictions.geProperty(propertyName,otherPropertyName) - return this - } - - /** - * @see Criteria - */ - Criteria ltProperty(String propertyName, String otherPropertyName) { - add Restrictions.ltProperty(propertyName,otherPropertyName) - return this - } - - /** - * @see Criteria - */ - Criteria leProperty(String propertyName, String otherPropertyName) { - add Restrictions.leProperty(propertyName,otherPropertyName) - return this - } - - /** - * @see Criteria - */ - Criteria idEquals(Object value) { - add Restrictions.idEq(value) - return this - } - - /** - * @see Criteria - */ - Criteria isEmpty(String propertyName) { - add Restrictions.isEmpty(propertyName) - return this - } - - /** - * @see Criteria - */ - Criteria isNotEmpty(String propertyName) { - add Restrictions.isNotEmpty(propertyName) - return this - } - - /** - * @see Criteria - */ - Criteria isNull(String propertyName) { - add Restrictions.isNull(propertyName) - return this - } - - /** - * @see Criteria - */ - Criteria isNotNull(String propertyName) { - add Restrictions.isNotNull(propertyName) - return this - } - - /** - * @see Criteria - */ - Criteria eq(String propertyName, Object propertyValue) { - add Restrictions.eq(propertyName,propertyValue) - return this - } - - /** - * @see Criteria - */ - Criteria idEq(Object propertyValue) { - add Restrictions.idEq(propertyValue) - return this - } - - /** - * @see Criteria - */ - Criteria ne(String propertyName, Object propertyValue) { - add Restrictions.ne(propertyName,propertyValue) - return this - } - - /** - * @see Criteria - */ - Criteria between(String propertyName, Object start, Object finish) { - add Restrictions.between(propertyName, start, finish) - return this - } - - /** - * @see Criteria - */ - Criteria gte(String property, Object value) { - add Restrictions.gte(property,value) - return this - } - - /** - * @see Criteria - */ - Criteria ge(String property, Object value) { - gte(property, value) - } - - /** - * @see Criteria - */ - Criteria gt(String property, Object value) { - add Restrictions.gt(property,value) - return this - } - - /** - * @see Criteria - */ - Criteria lte(String property, Object value) { - add Restrictions.lte(property, value) - return this - } - - /** - * @see Criteria - */ - Criteria le(String property, Object value) { - lte(property,value) - } - - /** - * @see Criteria - */ - Criteria lt(String property, Object value) { - add Restrictions.lt(property,value) - return this - } - - /** - * @see Criteria - */ - Criteria like(String propertyName, Object propertyValue) { - add Restrictions.like(propertyName,propertyValue.toString()) - return this - } - - /** - * @see Criteria - */ - Criteria ilike(String propertyName, Object propertyValue) { - add Restrictions.ilike(propertyName, propertyValue.toString()) - return this - } - - /** - * @see Criteria - */ - Criteria rlike(String propertyName, Object propertyValue) { - add Restrictions.rlike(propertyName, propertyValue.toString()) - return this - } - - Criteria eqAll(String propertyName, Closure propertyValue) { - eqAll(propertyName, buildQueryableCriteria(propertyValue)) - } - - private QueryableCriteria buildQueryableCriteria(Closure queryClosure) { - return new DetachedCriteria(targetClass).build(queryClosure) - } - - Criteria gtAll(String propertyName, Closure propertyValue) { - gtAll(propertyName, buildQueryableCriteria(propertyValue)) - } - - Criteria ltAll(String propertyName, Closure propertyValue) { - ltAll(propertyName, buildQueryableCriteria(propertyValue)) - } - - Criteria geAll(String propertyName, Closure propertyValue) { - geAll(propertyName, buildQueryableCriteria(propertyValue)) - } - - Criteria leAll(String propertyName, Closure propertyValue) { - leAll(propertyName, buildQueryableCriteria(propertyValue)) - } - - @Override - Criteria eqAll(String propertyName, QueryableCriteria propertyValue) { - add new Query.EqualsAll(propertyName, propertyValue) - return this - } - - @Override - Criteria gtAll(String propertyName, QueryableCriteria propertyValue) { - add new Query.GreaterThanAll(propertyName, propertyValue) - return this - } - - @Override - Criteria ltAll(String propertyName, QueryableCriteria propertyValue) { - add new Query.LessThanAll(propertyName, propertyValue) - return this - } - - @Override - Criteria geAll(String propertyName, QueryableCriteria propertyValue) { - add new Query.GreaterThanEqualsAll(propertyName, propertyValue) - return this - } - - @Override - Criteria leAll(String propertyName, QueryableCriteria propertyValue) { - add new Query.LessThanEqualsAll(propertyName, propertyValue) - return this - } - - class DetachedProjections implements ProjectionList { - - List projections - - DetachedProjections(List projections) { - this.projections = projections - } - - ProjectionList avg(String name) { - projections << Projections.avg(name) - return this - } - - ProjectionList max(String name) { - projections << Projections.max(name) - return this - } - - ProjectionList min(String name) { - projections << Projections.min(name) - return this - } - - ProjectionList sum(String name) { - projections << Projections.sum(name) - return this - } - - ProjectionList property(String name) { - projections << Projections.property(name) - return this - } - - ProjectionList rowCount() { - projections << Projections.count() - return this - } - - ProjectionList distinct(String property) { - projections << Projections.distinct(property) - return this - } - - ProjectionList distinct() { - projections << Projections.distinct() - return this - } - - ProjectionList countDistinct(String property) { - projections << Projections.countDistinct(property) - return this - } - - ProjectionList count() { - projections << Projections.count() - return this - } - - ProjectionList id() { - projections << Projections.id() - return this - } - } - - /** - * Where method derives a new query from this query. This method will not mutate the original query, but instead return a new one. - * - * @param additionalQuery The additional query - * @return A new query - */ - DetachedCriteria where(Closure additionalQuery) { - DetachedCriteria newQuery = clone() - return newQuery.build(additionalQuery) - } - - /** - * Synonym for #get - */ - T find(Map args = Collections.emptyMap(), Closure additionalCriteria = null) { - get(args, additionalCriteria) - } - - /** - * Synonym for #get - */ - T find(Closure additionalCriteria) { - get(Collections.emptyMap(), additionalCriteria) - } - - /** - * Returns a single result matching the criterion contained within this DetachedCriteria instance - * - * @return A single entity - */ - T get(Map args = Collections.emptyMap(), Closure additionalCriteria = null) { - (T)withPopulatedQuery(args, additionalCriteria) { Query query -> - query.singleResult() - } - } - - /** - * Returns a single result matching the criterion contained within this DetachedCriteria instance - * - * @return A single entity - */ - T get(Closure additionalCriteria) { - get(Collections.emptyMap(), additionalCriteria) - } - - /** - * Returns a single result matching the criterion contained within this DetachedCriteria instance - * - * @return A list of matching instances - */ - List list(Map args = Collections.emptyMap(), Closure additionalCriteria = null) { - (List)withPopulatedQuery(args, additionalCriteria) { Query query -> - if (args?.max) { - return new PagedResultList(query) - } - return query.list() - } - } - - /** - * Lists all records matching the criterion contained within this DetachedCriteria instance - * - * @return A list of matching instances - */ - List list(Closure additionalCriteria) { - list(Collections.emptyMap(), additionalCriteria) - } - - /** - * Counts the number of records returned by the query - * - * @param args The arguments - * @return The count - */ - Number count(Map args = Collections.emptyMap(), Closure additionalCriteria = null) { - (Number)withPopulatedQuery(args, additionalCriteria) { Query query -> - query.projections().count() - query.singleResult() - } - } - - /** - * Counts the number of records returned by the query - * - * @param args The arguments - * @return The count - */ - Number count(Closure additionalCriteria) { - (Number)withPopulatedQuery(Collections.emptyMap(), additionalCriteria) { Query query -> - query.projections().count() - query.singleResult() - } - } - - /** - * Counts the number of records returned by the query - * - * @param args The arguments - * @return The count - */ - boolean exists(Closure additionalCriteria = null) { - (Boolean)withPopulatedQuery(Collections.emptyMap(), additionalCriteria) { Query query -> - query.projections().count() - query.singleResult() > 0 - } - } - - /** - * Deletes all entities matching this criteria - * - * @return The total number deleted - */ - Number deleteAll() { - targetClass.withDatastoreSession { Session session -> - session.deleteAll(this) - } - } - - /** - * Updates all entities matching this criteria - * - * @return The total number deleted - */ - Number updateAll(Map properties) { - targetClass.withDatastoreSession { Session session -> - session.updateAll(this, properties) - } - } - - /** - * Enable the builder syntax for contructing Criteria - * - * @param callable The callable closure - * @return This criteria instance - */ - - DetachedCriteria build(Closure callable) { - DetachedCriteria newCriteria = this.clone() - newCriteria.with callable - return newCriteria - } - - /** - * Enable the builder syntax for contructing Criteria - * - * @param callable The callable closure - * @return This criteria instance - */ - - DetachedCriteria buildLazy(Closure callable) { - DetachedCriteria newCriteria = this.clone() - newCriteria.lazyQuery = callable - return newCriteria - } - - /** - * Sets the default max to use and returns a new criteria instance. This method does not mutate the original criteria! - * - * @param max The max to use - * @return A new DetachedCriteria instance derived from this - */ - DetachedCriteria max(int max) { - DetachedCriteria newCriteria = this.clone() - newCriteria.defaultMax = max - return newCriteria - } - - /** - * Sets the default offset to use and returns a new criteria instance. This method does not mutate the original criteria! - * - * @param offset The offset to use - * @return A new DetachedCriteria instance derived from this - */ - DetachedCriteria offset(int offset) { - DetachedCriteria newCriteria = this.clone() - newCriteria.defaultOffset = offset - return newCriteria - } - - /** - * Adds a sort order to this criteria instance - * - * @param property The property to sort by - * @return This criteria instance - */ - DetachedCriteria sort(String property) { - DetachedCriteria newCriteria = this.clone() - newCriteria.orders.add(new Order(property)) - return newCriteria - } - - /** - * Adds a sort order to this criteria instance - * - * @param property The property to sort by - * @param direction The direction to sort by - * @return This criteria instance - */ - DetachedCriteria sort(String property, String direction) { - DetachedCriteria newCriteria = this.clone() - newCriteria.orders.add(new Order(property, "desc".equalsIgnoreCase(direction) ? Direction.DESC : Direction.ASC)) - return newCriteria - } - - /** - * Adds a property projection - * - * @param property The property to sort by - * @return This criteria instance - */ - DetachedCriteria property(String property) { - DetachedCriteria newCriteria = this.clone() - newCriteria.projectionList.property(property) - return newCriteria - } - - def propertyMissing(String name) { - final entity = getPersistentEntity() - final p = entity.getPropertyByName(name) - if (p == null) { - throw new MissingPropertyException(name, DetachedCriteria) - } - return property(name) - } - - /** - * Adds a distinct property projection - * - * @param property The property to obtain the distinct value for - * @return This criteria instance - */ - DetachedCriteria distinct(String property) { - DetachedCriteria newCriteria = this.clone() - newCriteria.projectionList.distinct(property) - return newCriteria - } - - /** - * @return The async version of the DetachedCriteria API - */ - AsyncQuery getAsync() { - return new AsyncQuery(this) - } - - /** - * Method missing handler that deals with the invocation of dynamic finders - * - * @param methodName The method name - * @param args The arguments - * @return The result of the method call - */ - def methodMissing(String methodName, args) { - initialiseIfNecessary(targetClass) - def method = dynamicFinders.find { FinderMethod f -> f.isMethodMatch(methodName) } - if (method != null) { - return method.invoke(targetClass, methodName,this, args) - } - - if (!args || args.size() != 1 || !(args[-1] instanceof Closure)) { - throw new MissingMethodException(methodName, DetachedCriteria, args) - } - - final prop = persistentEntity.getPropertyByName(methodName) - if (!(prop instanceof Association)) { - throw new MissingMethodException(methodName, DetachedCriteria, args) - } - - def associationCriteria = new DetachedAssociationCriteria(prop.associatedEntity.javaClass, prop) - add associationCriteria - final callable = args[-1] - callable.delegate = associationCriteria - callable.call() - } - - @Override - Iterator iterator() { - return list().iterator() - } - - @Override - protected DetachedCriteria clone() { - def criteria = new DetachedCriteria(targetClass) - criteria.criteria = new ArrayList(this.criteria) - final projections = new ArrayList(this.projections) - criteria.projections = projections - criteria.projectionList = new DetachedProjections(projections) - criteria.orders = new ArrayList(this.orders) - criteria.defaultMax = defaultMax - criteria.defaultOffset = defaultOffset - return criteria - } - - protected void handleJunction(Closure callable) { - try { - callable.delegate = this - callable.call() - } - finally { - def lastJunction = junctions.remove(junctions.size() - 1) - add lastJunction - } - } - - private withPopulatedQuery(Map args, Closure additionalCriteria, Closure callable) { - targetClass.withDatastoreSession { Session session -> - applyLazyCriteria() - Query query = session.createQuery(targetClass) - if (defaultMax != null) { - query.max(defaultMax) - } - if (defaultOffset != null) { - query.offset(defaultOffset) - } - DynamicFinder.applyDetachedCriteria(query, this) - - if (additionalCriteria != null) { - def additionalDetached = new DetachedCriteria(targetClass).build(additionalCriteria) - DynamicFinder.applyDetachedCriteria(query, additionalDetached) - } - - DynamicFinder.populateArgumentsForCriteria(targetClass, query, args) - - callable.call(query) - } - } - - private void applyLazyCriteria() { - if (lazyQuery == null) { - return - } - - def criteria = lazyQuery - lazyQuery = null - this.with criteria - } -} diff --git a/grails-datastore-gorm/src/main/groovy/grails/gorm/PagedResultList.java b/grails-datastore-gorm/src/main/groovy/grails/gorm/PagedResultList.java deleted file mode 100644 index 66e4b34f2..000000000 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/PagedResultList.java +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (C) 2010 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 grails.gorm; - -import java.util.AbstractList; -import java.util.List; - -import org.grails.datastore.mapping.query.Query; - -/** - * A result list implementation that provides an additional property called 'totalCount' to obtain the total number of - * records. Useful for pagination. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class PagedResultList extends AbstractList { - - private Query query; - private List resultList; - private int totalCount = Integer.MIN_VALUE; - - public PagedResultList(Query query) { - this.query = query; - } - - /** - * @return The total number of records for this query - */ - public int getTotalCount() { - initialize(); - if (totalCount == Integer.MIN_VALUE) { - Query newQuery = (Query)query.clone(); - newQuery.projections().count(); - Number result = (Number) newQuery.singleResult(); - totalCount = result == null ? 0 : result.intValue(); - } - - return totalCount; - } - - @Override - public Object get(int i) { - initialize(); - return resultList.get(i); - } - - @Override - public Object set(int i, Object o) { - initialize(); - return resultList.set(i, o); - } - - @Override - public Object remove(int i) { - initialize(); - return resultList.remove(i); - } - - @Override - public void add(int i, Object o) { - initialize(); - resultList.add(i, o); - } - - private void initialize() { - if (resultList == null) { - resultList = query.list(); - } - } - - @Override - public int size() { - initialize(); - return resultList.size(); - } -} 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 deleted file mode 100644 index 60b6a6622..000000000 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/dirty/checking/DirtyCheck.groovy +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2013 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 grails.gorm.dirty.checking - -import org.codehaus.groovy.transform.GroovyASTTransformationClass - -import java.lang.annotation.ElementType -import java.lang.annotation.Retention -import java.lang.annotation.RetentionPolicy -import java.lang.annotation.Target - -/** - * Apply to enhance an entity with dirty checking support - * - * @author Graeme Rocher - * @since 2.0 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target([ElementType.TYPE]) -@GroovyASTTransformationClass("org.codehaus.groovy.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/codehaus/groovy/grails/compiler/gorm/DirtyCheckTransformation.groovy deleted file mode 100644 index 67fdbfc38..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/DirtyCheckTransformation.groovy +++ /dev/null @@ -1,45 +0,0 @@ -package org.codehaus.groovy.grails.compiler.gorm - -import grails.gorm.dirty.checking.DirtyCheck -import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.ASTNode -import org.codehaus.groovy.ast.AnnotatedNode -import org.codehaus.groovy.ast.AnnotationNode -import org.codehaus.groovy.ast.ClassNode -import org.codehaus.groovy.control.CompilePhase -import org.codehaus.groovy.control.SourceUnit -import org.codehaus.groovy.transform.ASTTransformation -import org.codehaus.groovy.transform.GroovyASTTransformation - -/** - * Applies the DirtyCheck transformation - * - * @author Graeme Rocher - * @since 2.0 - */ -@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) -class DirtyCheckTransformation implements ASTTransformation { - - private static final ClassNode MY_TYPE = new ClassNode(DirtyCheck.class); - private static final String MY_TYPE_NAME = "@" + MY_TYPE.getNameWithoutPackage(); - - @Override - @CompileStatic - void visit(ASTNode[] astNodes, SourceUnit source) { - - AnnotatedNode parent = (AnnotatedNode) astNodes[1]; - AnnotationNode node = (AnnotationNode) astNodes[0]; - - if (!(astNodes[0] instanceof AnnotationNode) || !(astNodes[1] instanceof AnnotatedNode)) { - throw new RuntimeException("Internal error: wrong types: ${node.getClass()} / ${parent.getClass()}"); - } - - if (!MY_TYPE.equals(node.getClassNode()) || !(parent instanceof ClassNode)) { - return; - } - - ClassNode cNode = (ClassNode) parent; - - new DirtyCheckingTransformer().performInjection(source, cNode) - } -} 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/codehaus/groovy/grails/compiler/gorm/DirtyCheckingTransformer.groovy deleted file mode 100644 index 56e815012..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/DirtyCheckingTransformer.groovy +++ /dev/null @@ -1,375 +0,0 @@ -package org.codehaus.groovy.grails.compiler.gorm - -import grails.artefact.Artefact -import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.ClassHelper -import org.codehaus.groovy.ast.ClassNode -import org.codehaus.groovy.ast.FieldNode -import org.codehaus.groovy.ast.GenericsType -import org.codehaus.groovy.ast.MethodNode -import org.codehaus.groovy.ast.Parameter -import org.codehaus.groovy.ast.PropertyNode -import org.codehaus.groovy.ast.VariableScope -import org.codehaus.groovy.ast.expr.ArgumentListExpression -import org.codehaus.groovy.ast.expr.BinaryExpression -import org.codehaus.groovy.ast.expr.BooleanExpression -import org.codehaus.groovy.ast.expr.ConstantExpression -import org.codehaus.groovy.ast.expr.ListExpression -import org.codehaus.groovy.ast.expr.MapExpression -import org.codehaus.groovy.ast.expr.MethodCallExpression -import org.codehaus.groovy.ast.expr.NotExpression -import org.codehaus.groovy.ast.expr.PropertyExpression -import org.codehaus.groovy.ast.expr.VariableExpression -import org.codehaus.groovy.ast.stmt.BlockStatement -import org.codehaus.groovy.ast.stmt.EmptyStatement -import org.codehaus.groovy.ast.stmt.ExpressionStatement -import org.codehaus.groovy.ast.stmt.IfStatement -import org.codehaus.groovy.ast.stmt.ReturnStatement -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 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 org.codehaus.groovy.syntax.Token -import org.codehaus.groovy.syntax.Types -import org.grails.datastore.mapping.dirty.checking.DirtyCheckable -import org.grails.datastore.mapping.reflect.NameUtils - -import static java.lang.reflect.Modifier.* -import org.codehaus.groovy.ast.AnnotationNode -import grails.persistence.PersistenceMethod - -/** - * - * Transforms a domain class making it possible for the domain class to take responsibility of tracking changes to itself, thus removing the responsibility from the ORM system which would have to maintain parallel state - * and compare the state of the domain class to the stored state. With this transformation the storage of the state is not necessary as the state is kept in the domain class itself - * - * @author Graeme Rocher - * @since 2.0 - */ -@AstTransformer -@CompileStatic -class DirtyCheckingTransformer implements GrailsDomainClassInjector, GrailsArtefactClassInjector { - private static final String VOID = "void"; - public static final String CHANGE_TRACKING_FIELD_NAME = '$changedProperties' - private static final Class[] EMPTY_JAVA_CLASS_ARRAY = []; - private static final Class[] OBJECT_CLASS_ARG = [Object.class]; - public static final String METHOD_NAME_TRACK_CHANGES = "trackChanges" - public static final String METHOD_NAME_MARK_DIRTY = "markDirty" - public static final String METHOD_NAME_RESET_DIRTY = "resetDirty" - public static final String METHOD_NAME_IS_DIRTY = "hasChanged" - public static final ConstantExpression CONSTANT_NULL = new ConstantExpression(null) - public static final String METHOD_NAME_GET_DIRTY_PROPERTY_NAMES = "listDirtyPropertyNames" - public static final String METHOD_NAME_GET_PERSISTENT_VALUE = "getOriginalValue" - - @Override - void performInjectionOnAnnotatedClass(SourceUnit source, ClassNode classNode) { - // First add a local field that will store the change tracking state. The field is a simple list of property names that have changed - // the field is only added to root clauses that extend from java.lang.Object - final changeTrackingVariable = new VariableExpression(CHANGE_TRACKING_FIELD_NAME) - final mapClassNode = new ClassNode(Map).getPlainNodeReference() - final changeTrackableClassNode = new ClassNode(DirtyCheckable).getPlainNodeReference() - - MethodNode putInMapMethodNode = mapClassNode.getMethods("put")[0] - MethodNode containsKeyMethodNode = mapClassNode.getMethods("containsKey")[0] - final markDirtyMethodNode = changeTrackableClassNode.getMethod(METHOD_NAME_MARK_DIRTY, new Parameter(ClassHelper.STRING_TYPE, "propertyName")) - - final shouldWeave = classNode.getSuperClass().equals(OBJECT_CLASS_NODE) - if (shouldWeave) { - FieldNode changingTrackingField = new FieldNode(CHANGE_TRACKING_FIELD_NAME, (PROTECTED | TRANSIENT).intValue(), mapClassNode, classNode, null); - if(!classNode.getField(CHANGE_TRACKING_FIELD_NAME)) { - classNode.addField(changingTrackingField) - } - - final persistenceMethodAnnotation = new AnnotationNode(new ClassNode(PersistenceMethod.class).getPlainNodeReference()) - // we also need to make it implement the ChangeTrackable interface - - // Implement the trackChanges method such that: - // void trackChanges() { if( !$changedProperties ) $changedProperties = [:] } - classNode.addInterface(changeTrackableClassNode) - final trackChangesBody = new BlockStatement() - final assignChangeTrackingFieldStatement = new ExpressionStatement( - new BinaryExpression(changeTrackingVariable, - Token.newSymbol(Types.EQUAL, 0, 0), - new MapExpression()) - ) - - trackChangesBody.addStatement(assignChangeTrackingFieldStatement) - if(!classNode.getMethod(METHOD_NAME_TRACK_CHANGES, ZERO_PARAMETERS)) { - - final method = classNode.addMethod(METHOD_NAME_TRACK_CHANGES, PUBLIC, ClassHelper.VOID_TYPE, ZERO_PARAMETERS, null, trackChangesBody) - method.addAnnotation(persistenceMethodAnnotation) - } - - // Implement the hasChanged method such that: - // boolean hasChanged() { $changedProperties == null || $changedProperties } - if(!classNode.getMethod(METHOD_NAME_IS_DIRTY, ZERO_PARAMETERS)) { - final leftExpression = new BinaryExpression(changeTrackingVariable, Token.newSymbol(Types.COMPARE_EQUAL, 0, 0), CONSTANT_NULL) - final rightExpression = changeTrackingVariable - final fullCondition = new BinaryExpression(leftExpression, Token.newSymbol(Types.LOGICAL_OR, 0, 0), rightExpression) - classNode.addMethod(METHOD_NAME_IS_DIRTY, PUBLIC, ClassHelper.boolean_TYPE, ZERO_PARAMETERS, null, new ReturnStatement(fullCondition)) - } - - // Implement the hasChanged(String propertyName) method such that - // boolean hasChanged() { $changedProperties == null || $changedProperties && $changedProperties.containsKey(propertyName) } - final propertyNameParameter = new Parameter(ClassHelper.STRING_TYPE, "propertyName") - final propertyNameParameterArray = [propertyNameParameter] as Parameter[] - if(!classNode.getMethod(METHOD_NAME_IS_DIRTY, propertyNameParameterArray )) { - final containsMethodCallExpression = new MethodCallExpression(changeTrackingVariable, "contains", new VariableExpression(propertyNameParameter)) - containsMethodCallExpression.methodTarget = containsKeyMethodNode - final leftExpression = new BinaryExpression(changeTrackingVariable, Token.newSymbol(Types.COMPARE_EQUAL, 0, 0), CONSTANT_NULL) - final rightExpression = new BinaryExpression(changeTrackingVariable, Token.newSymbol(Types.LOGICAL_AND, 0, 0), containsMethodCallExpression) - final fullCondition = new BinaryExpression(leftExpression, Token.newSymbol(Types.LOGICAL_OR, 0, 0), rightExpression) - final newMethod = classNode.addMethod(METHOD_NAME_IS_DIRTY, PUBLIC, ClassHelper.boolean_TYPE, propertyNameParameterArray, null, new ReturnStatement(fullCondition)) - final scope = new VariableScope() - scope.putReferencedClassVariable(propertyNameParameter) - newMethod.setVariableScope(scope) - } - - // Implement the markDiry() method such that - // void markDirty() { if( $changeProperties != null) $changeProperties.put className, '$DIRTY_MARKER' } - final markDirtyBody = new BlockStatement() - - final addMethodCall = new MethodCallExpression(changeTrackingVariable, putInMapMethodNode.name, new ArgumentListExpression(new ConstantExpression(classNode.name), new ConstantExpression('$DIRTY_MARKER'))) - addMethodCall.setMethodTarget(putInMapMethodNode) - final changeTrackingVariableNullCheck = new BooleanExpression(new BinaryExpression(changeTrackingVariable, Token.newSymbol(Types.COMPARE_NOT_EQUAL, 0, 0), CONSTANT_NULL)) - def ifNotNullStatement = new IfStatement(changeTrackingVariableNullCheck, new ExpressionStatement(addMethodCall), new EmptyStatement()) - markDirtyBody.addStatement(ifNotNullStatement) - if(!classNode.getMethod(METHOD_NAME_MARK_DIRTY, ZERO_PARAMETERS)) { - - final method = classNode.addMethod(METHOD_NAME_MARK_DIRTY, PUBLIC, ClassHelper.VOID_TYPE, ZERO_PARAMETERS, null, markDirtyBody) - method.addAnnotation(persistenceMethodAnnotation) - } - - // Implement the markDirty(String propertyName) method such that - // void markDirty(String propertyName) { if( $changeProperties != null) $changeProperties.put propertyName, getProperty(propertyName) } - if(!classNode.getMethod(METHOD_NAME_MARK_DIRTY, propertyNameParameterArray)) { - final markPropertyDirtyBody = new BlockStatement() - final propertyNameVar = new VariableExpression(propertyNameParameter) - final addPropertyMethodCall = new MethodCallExpression(changeTrackingVariable, putInMapMethodNode.name, new ArgumentListExpression(propertyNameVar, new MethodCallExpression(THIS_EXPR, "getProperty", propertyNameVar))) - addPropertyMethodCall.methodTarget = putInMapMethodNode - final containsKeyMethodCall = new MethodCallExpression(changeTrackingVariable, containsKeyMethodNode.name, propertyNameVar) - containsKeyMethodCall.methodTarget = containsKeyMethodNode - ifNotNullStatement = new IfStatement(new BooleanExpression(new BinaryExpression(changeTrackingVariableNullCheck, Token.newSymbol(Types.LOGICAL_AND, 0, 0), new NotExpression(containsKeyMethodCall))), new ExpressionStatement(addPropertyMethodCall), new EmptyStatement()) - markPropertyDirtyBody.addStatement(ifNotNullStatement) - final newMethod = classNode.addMethod(METHOD_NAME_MARK_DIRTY, PUBLIC, ClassHelper.VOID_TYPE, propertyNameParameterArray, null, markPropertyDirtyBody) - final scope = new VariableScope() - scope.putReferencedClassVariable(propertyNameParameter) - newMethod.setVariableScope(scope) - newMethod.addAnnotation(persistenceMethodAnnotation) - - } - - // Implement listDirtyProperties() such that - // List listDirtyProperties() { trackChanges(); $changeProperties.keySet().toList() } - if(!classNode.getMethod(METHOD_NAME_GET_DIRTY_PROPERTY_NAMES, ZERO_PARAMETERS)) { - final methodBody = new BlockStatement() - final returnDirtyPropertyNames = new ReturnStatement(new MethodCallExpression(new MethodCallExpression(changeTrackingVariable, "keySet", ZERO_ARGS), "toList", ZERO_ARGS)) - methodBody.addStatement(new IfStatement(new BooleanExpression(changeTrackingVariable), returnDirtyPropertyNames, new ReturnStatement(new ListExpression()))) - final newMethod = classNode.addMethod(METHOD_NAME_GET_DIRTY_PROPERTY_NAMES, PUBLIC, ClassHelper.make(List).getPlainNodeReference(), ZERO_PARAMETERS, null, methodBody) - newMethod.addAnnotation(persistenceMethodAnnotation) - } - - // Implement getOriginalValue(String) such that - // Object getOriginalValue(String propertyName) { $changedProperties.get(propertyName) } - if(!classNode.getMethod(METHOD_NAME_GET_PERSISTENT_VALUE, propertyNameParameterArray)) { - - final methodBody = new BlockStatement() - final propertyNameVariable = new VariableExpression(propertyNameParameter) - final containsKeyMethodCall = new MethodCallExpression(changeTrackingVariable, containsKeyMethodNode.name, propertyNameVariable) - containsKeyMethodCall.methodTarget = containsKeyMethodNode - methodBody.addStatement(new IfStatement(new BooleanExpression(containsKeyMethodCall), - new ExpressionStatement( new MethodCallExpression(changeTrackingVariable, "get", propertyNameVariable) ), - new ReturnStatement(new MethodCallExpression(THIS_EXPR, "getProperty", propertyNameVariable)))) - final newMethod = classNode.addMethod(METHOD_NAME_GET_PERSISTENT_VALUE, PUBLIC, ClassHelper.OBJECT_TYPE, propertyNameParameterArray, null, methodBody) - newMethod.addAnnotation(persistenceMethodAnnotation) - } - // Now we go through all the properties, if the property is a persistent property and change tracking has been initiated then we add to the setter of the property - // code that will mark the property as dirty. Note that if the property has no getter we have to add one, since only adding the setter results in a read-only property - final propertyNodes = classNode.getProperties() - - Map gettersAndSetters = [:] - - for (MethodNode mn in classNode.methods) { - final methodName = mn.name - if(!mn.isPublic() || mn.isStatic() || mn.isSynthetic()) continue - - if (isSetter(methodName, mn)) { - String propertyName = NameUtils.getPropertyNameForGetterOrSetter(methodName) - GetterAndSetter getterAndSetter = getGetterAndSetterForPropertyName(gettersAndSetters, propertyName) - getterAndSetter.setter = mn - } else if (isGetter(methodName, mn)) { - String propertyName = NameUtils.getPropertyNameForGetterOrSetter(methodName) - GetterAndSetter getterAndSetter = getGetterAndSetterForPropertyName(gettersAndSetters, propertyName) - getterAndSetter.getter = mn - } - } - - for (PropertyNode pn in propertyNodes) { - final propertyName = pn.name - if (!pn.isStatic() && pn.isPublic() && !GrailsDomainConfigurationUtil.isConfigurational(propertyName)) { - if(isTransient(pn.modifiers) || isFinal(pn.modifiers)) continue - - final getterAndSetter = gettersAndSetters[propertyName] - - // if there is no explicit getter and setter then one will be generated by Groovy, so we must add these to track changes - if(getterAndSetter == null) { - final propertyField = pn.getField() - - // first add the getter - final getterName = NameUtils.getGetterName(propertyName) - ClassNode originalReturnType = pn.getType() - ClassNode returnType; - if(!originalReturnType.getNameWithoutPackage().equals(VOID)) { - if(ClassHelper.isPrimitiveType(originalReturnType.redirect())) { - returnType = originalReturnType.getPlainNodeReference() - } else { - returnType = alignReturnType(classNode, originalReturnType); - } - } - else { - returnType = originalReturnType - } - classNode.addMethod(getterName, PUBLIC, returnType, ZERO_PARAMETERS, null, new ReturnStatement(new VariableExpression(propertyField.getName()))) - - // now add the setter that tracks changes. Each setters becomes: - // void setFoo(String foo) { markDirty("foo"); this.foo = foo } - final setterName = NameUtils.getSetterName(propertyName) - final setterParameter = new Parameter(returnType, propertyName) - final setterBody = new BlockStatement() - MethodCallExpression markDirtyMethodCall = createMarkDirtyMethodCall(markDirtyMethodNode, propertyName) - setterBody.addStatement(new ExpressionStatement(markDirtyMethodCall)) - setterBody.addStatement( new ExpressionStatement( - new BinaryExpression(new PropertyExpression(THIS_EXPR, propertyField.name), - Token.newSymbol(Types.EQUAL, 0, 0), - new VariableExpression(setterParameter)) - ) - ) - - classNode.addMethod(setterName, PUBLIC, ClassHelper.VOID_TYPE, [setterParameter] as Parameter[], null, setterBody) - } - else if(getterAndSetter.hasBoth()) { - // if both a setter and getter are present, we get hold of the setter and weave the markDirty method call into it - weaveIntoExistingSetter(propertyName, getterAndSetter, markDirtyMethodNode) - } - else { - // there isn't both a getter and a setter then this is not a candidate for persistence, so we eliminate it from change tracking - gettersAndSetters.remove(propertyName) - } - } - } - - // We also need to search properties that are represented as getters with setters. This requires going through all the methods and finding getter/setter pairs that are public - gettersAndSetters.each { String propertyName, GetterAndSetter getterAndSetter -> - if(getterAndSetter.hasBoth()) { - weaveIntoExistingSetter(propertyName, getterAndSetter, markDirtyMethodNode) - } - } - } - } - - @Override - void performInjection(SourceUnit source, GeneratorContext context, ClassNode classNode) { - if (!classNode.getAnnotations(new ClassNode(Artefact.class)).isEmpty()) return; - - performInjectionOnAnnotatedClass(source, classNode) - } - - @Override - void performInjection(SourceUnit source, ClassNode classNode) { - performInjection(source, null, classNode) - } - - public boolean shouldInject(URL url) { - return GrailsResourceUtils.isDomainClass(url); - } - - @Override - void performInjectionOnAnnotatedEntity(ClassNode classNode) { - performInjectionOnAnnotatedClass(null, classNode) - } - - - private static ClassNode alignReturnType(final ClassNode receiver, final ClassNode originalReturnType) { - ClassNode copiedReturnType = originalReturnType.getPlainNodeReference(); - - final genericTypes = originalReturnType.getGenericsTypes() - if (genericTypes) { - List newGenericTypes = [] - - for(GenericsType gt in genericTypes) { - ClassNode[] upperBounds = null - if (gt.upperBounds) { - upperBounds = gt.upperBounds.collect { ClassNode cn -> cn.plainNodeReference } as ClassNode[] - } - newGenericTypes << new GenericsType(gt.type.plainNodeReference, upperBounds, gt.lowerBound?.plainNodeReference) - } - copiedReturnType.setGenericsTypes(newGenericTypes as GenericsType[]) - } - - return copiedReturnType; - } - protected void weaveIntoExistingSetter(String propertyName, GetterAndSetter getterAndSetter, MethodNode markDirtyMethodNode) { - final setterMethod = getterAndSetter.setter - if(setterMethod.getAnnotations(new ClassNode(PersistenceMethod))) return - - final currentBody = setterMethod.code - final setterParameter = setterMethod.getParameters()[0] - MethodCallExpression markDirtyMethodCall = createMarkDirtyMethodCall(markDirtyMethodNode, propertyName) - final newBody = new BlockStatement() - newBody.addStatement(new ExpressionStatement(markDirtyMethodCall)) - newBody.addStatement(currentBody) - setterMethod.code = newBody - } - - protected MethodCallExpression createMarkDirtyMethodCall(MethodNode markDirtyMethodNode, String propertyName) { - final markDirtyMethodCall = new MethodCallExpression(THIS_EXPR, markDirtyMethodNode.name, new ConstantExpression(propertyName)) - markDirtyMethodCall.methodTarget = markDirtyMethodNode - markDirtyMethodCall - } - - protected GetterAndSetter getGetterAndSetterForPropertyName(LinkedHashMap gettersAndSetters, String propertyName) { - def getterAndSetter = gettersAndSetters[propertyName] - if (getterAndSetter == null) { - getterAndSetter = new GetterAndSetter() - gettersAndSetters[propertyName] = getterAndSetter - } - getterAndSetter - } - - - - private boolean isSetter(String methodName, MethodNode declaredMethod) { - return declaredMethod.getParameters().length == 1 && GrailsClassUtils.isSetter(methodName, OBJECT_CLASS_ARG); - } - - private boolean isGetter(String methodName, MethodNode declaredMethod) { - return declaredMethod.getParameters().length == 0 && GrailsClassUtils.isGetter(methodName, EMPTY_JAVA_CLASS_ARRAY); - } - - @Override - String[] getArtefactTypes() { - return [DomainClassArtefactHandler.TYPE] as String[]; - } - - @CompileStatic - class GetterAndSetter { - MethodNode getter - MethodNode setter - - boolean hasBoth() { - getter && setter - } - - boolean hasNeither() { - !getter && !setter - } - } -} 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/codehaus/groovy/grails/compiler/gorm/GormTransformer.java deleted file mode 100644 index 43aa7ed4c..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/GormTransformer.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 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.codehaus.groovy.grails.compiler.gorm; - -import grails.persistence.Entity; - -import java.net.URL; -import java.util.Arrays; -import java.util.List; - -import grails.persistence.PersistenceMethod; -import org.codehaus.groovy.ast.AnnotationNode; -import org.codehaus.groovy.ast.ClassNode; -import org.codehaus.groovy.ast.MethodNode; -import org.codehaus.groovy.ast.expr.ClassExpression; -import org.codehaus.groovy.ast.expr.MethodCallExpression; -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.GrailsClassUtils; -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.datastore.gorm.GormInstanceApi; -import org.grails.datastore.gorm.GormStaticApi; - -/** - * Transforms GORM entities making the GORM API available to Java. - * - * @author Graeme Rocher - * @since 2.0 - */ -@AstTransformer -public class GormTransformer extends AbstractGrailsArtefactTransformer { - - public static final String NEW_INSTANCE_METHOD = "newInstance"; - - private static final List EXCLUDES = Arrays.asList("create", "setTransactionManager"); - private static final Class[] EMPTY_JAVA_CLASS_ARRAY = {}; - private static final Class[] OBJECT_CLASS_ARG = { Object.class }; - - @Override - protected boolean isStaticCandidateMethod(ClassNode classNode, MethodNode declaredMethod) { - String methodName = declaredMethod.getName(); - return !EXCLUDES.contains(methodName) && - !isGetter(methodName, declaredMethod) && - !isSetter(methodName, declaredMethod) && - super.isStaticCandidateMethod(classNode, declaredMethod); - } - - private boolean isSetter(String methodName, MethodNode declaredMethod) { - return declaredMethod.getParameters().length ==2 && GrailsClassUtils.isSetter(methodName, OBJECT_CLASS_ARG); - } - - private boolean isGetter(String methodName, MethodNode declaredMethod) { - return declaredMethod.getParameters().length == 1 && GrailsClassUtils.isGetter(methodName, EMPTY_JAVA_CLASS_ARRAY); - } - - @Override - public String getArtefactType() { - return DomainClassArtefactHandler.TYPE; - } - - public Class getInstanceImplementation() { - return GormInstanceApi.class; - } - - public Class getStaticImplementation() { - return GormStaticApi.class; - } - - @Override - protected boolean requiresStaticLookupMethod() { - return true; - } - - @Override - protected AnnotationNode getMarkerAnnotation() { - return new AnnotationNode(new ClassNode(PersistenceMethod.class).getPlainNodeReference()); - } - - protected MethodNode populateAutowiredApiLookupMethod(ClassNode classNode, ClassNode implementationNode, String apiInstanceProperty, String methodName, BlockStatement methodBody) { - return new MethodNode(methodName, PUBLIC_STATIC_MODIFIER, implementationNode,ZERO_PARAMETERS,null,methodBody); - } - - @Override - protected void performInjectionInternal(String apiInstanceProperty, SourceUnit source, ClassNode classNode) { - classNode.setUsingGenerics(true); - GrailsASTUtils.addAnnotationIfNecessary(classNode, Entity.class); - - 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); - classNode = GrailsASTUtils.nonGeneric(classNode); - if (methodNode == null) { - classNode.addMethod(new MethodNode(CreateDynamicMethod.METHOD_NAME, PUBLIC_STATIC_MODIFIER, classNode, ZERO_PARAMETERS,null, methodBody)); - } - } - - public boolean shouldInject(URL url) { - return GrailsResourceUtils.isDomainClass(url); - } -} 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/codehaus/groovy/grails/compiler/gorm/GormValidationTransformer.java deleted file mode 100644 index cf854de48..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/codehaus/groovy/grails/compiler/gorm/GormValidationTransformer.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 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.codehaus.groovy.grails.compiler.gorm; - -import java.net.URL; -import java.util.Arrays; - -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.GrailsClassUtils; -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.datastore.gorm.GormValidationApi; - -/** - * Makes the validate methods statically available via an AST transformation. - * - * @author Graeme Rocher - * @since 2.0 - */ -@AstTransformer -public class GormValidationTransformer extends AbstractGrailsArtefactTransformer{ - - public static final String HAS_ERRORS_METHOD = "hasErrors"; - private static final java.util.List EXCLUDES = Arrays.asList( - "setErrors", "getErrors", HAS_ERRORS_METHOD, - "getBeforeValidateHelper", "setBeforeValidateHelper", - "getValidator", "setValidator"); - private static final Class[] EMPTY_JAVA_CLASS_ARRAY = {}; - private static final Class[] OBJECT_CLASS_ARG = { Object.class }; - - @Override - protected boolean isStaticCandidateMethod(ClassNode classNode, MethodNode declaredMethod) { - String methodName = declaredMethod.getName(); - return !EXCLUDES.contains(methodName) && - !isGetter(methodName, declaredMethod) && - !isSetter(methodName, declaredMethod) && - super.isStaticCandidateMethod(classNode, declaredMethod); - } - - private boolean isSetter(String methodName, MethodNode declaredMethod) { - return declaredMethod.getParameters().length ==1 && GrailsClassUtils.isSetter(methodName, OBJECT_CLASS_ARG); - } - - private boolean isGetter(String methodName, MethodNode declaredMethod) { - return declaredMethod.getParameters().length == 0 && GrailsClassUtils.isGetter(methodName, EMPTY_JAVA_CLASS_ARRAY); - } - @Override - protected boolean requiresStaticLookupMethod() { - return true; - } - - @Override - public String getArtefactType() { - return DomainClassArtefactHandler.TYPE; - } - - @Override - public Class getInstanceImplementation() { - return GormValidationApi.class; - } - - @Override - public Class getStaticImplementation() { - return null; // no static API - } - - public boolean shouldInject(URL url) { - return GrailsResourceUtils.isDomainClass(url); - } - - @Override - protected boolean isCandidateInstanceMethod(ClassNode classNode, MethodNode declaredMethod) { - return !EXCLUDES.contains(declaredMethod.getName()) && super.isCandidateInstanceMethod(classNode, declaredMethod); - } - - @Override - protected void performInjectionInternal(String apiInstanceProperty, SourceUnit source, ClassNode classNode) { - final PropertyNode errorsProperty = classNode.getProperty(GrailsDomainClassProperty.ERRORS); - if (errorsProperty == null) { - addErrorsProperty(classNode); - } - } - - private void addErrorsProperty(ClassNode classNode) { - ASTErrorsHelper errorsHelper = new ASTValidationErrorsHelper(); - errorsHelper.injectErrorsCode(classNode); - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/AbstractDatastoreApi.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/AbstractDatastoreApi.groovy deleted file mode 100644 index 358654b35..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/AbstractDatastoreApi.groovy +++ /dev/null @@ -1,43 +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 - -import groovy.transform.CompileStatic; - -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.core.DatastoreUtils -import org.grails.datastore.mapping.core.SessionCallback -import org.grails.datastore.mapping.core.VoidSessionCallback - -/** - * @author Burt Beckwith - */ -@CompileStatic -abstract class AbstractDatastoreApi { - - protected Datastore datastore - - protected AbstractDatastoreApi(Datastore datastore) { - this.datastore = datastore - } - - protected T execute(SessionCallback callback) { - DatastoreUtils.execute datastore, callback - } - - protected void execute(VoidSessionCallback callback) { - DatastoreUtils.execute datastore, callback - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/AbstractGormApi.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/AbstractGormApi.groovy deleted file mode 100644 index b820b76c2..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/AbstractGormApi.groovy +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2010 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 - -import groovy.transform.CompileStatic -import groovy.transform.TypeChecked -import groovy.transform.TypeCheckingMode - -import java.lang.reflect.Method -import java.lang.reflect.Modifier - -import org.grails.datastore.gorm.utils.ReflectionUtils -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.model.PersistentEntity - -/** - * Abstract GORM API provider. - * - * @author Graeme Rocher - * @param the entity/domain class - * @since 1.0 - */ -@CompileStatic -abstract class AbstractGormApi extends AbstractDatastoreApi { - - static final List EXCLUDES = [ - 'setProperty', - 'getProperty', - 'getMetaClass', - 'setMetaClass', - 'invokeMethod', - 'getMethods', - 'getExtendedMethods', - 'wait', - 'equals', - 'toString', - 'hashCode', - 'getClass', - 'notify', - 'notifyAll', - 'setTransactionManager' - ] - - protected Class persistentClass - protected PersistentEntity persistentEntity - private List methods = [] - private List extendedMethods = [] - - AbstractGormApi(Class persistentClass, Datastore datastore) { - super(datastore) - this.persistentClass = persistentClass - this.persistentEntity = datastore.getMappingContext().getPersistentEntity(persistentClass.name) - - final clazz = getClass() - clazz = initializeMethods(clazz) - } - - @CompileStatic(TypeCheckingMode.SKIP) - protected initializeMethods(clazz) { - while (clazz != Object) { - final methodsToAdd = clazz.declaredMethods.findAll { Method m -> - def mods = m.getModifiers() - !m.isSynthetic() && !Modifier.isStatic(mods) && Modifier.isPublic(mods) && - !AbstractGormApi.EXCLUDES.contains(m.name) - } - methods.addAll methodsToAdd - if (clazz != GormStaticApi.class && clazz != GormInstanceApi && clazz != GormValidationApi && clazz != AbstractGormApi) { - def extendedMethodsToAdd = methodsToAdd.findAll { Method m -> !ReflectionUtils.isMethodOverriddenFromParent(m)} - extendedMethods.addAll extendedMethodsToAdd - } - clazz = clazz.getSuperclass() - } - return clazz - } - - List getMethods() { methods } - - List getExtendedMethods() { extendedMethods } -} 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 deleted file mode 100644 index 4a50955bf..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormEnhancer.groovy +++ /dev/null @@ -1,273 +0,0 @@ -/* Copyright (C) 2010 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 - -import grails.util.GrailsNameUtils -import org.grails.datastore.mapping.engine.EntityPersister -import org.grails.datastore.mapping.model.types.ToOne - -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.runtime.metaclass.ClosureStaticMetaMethod -import org.grails.datastore.gorm.finders.CountByFinder -import org.grails.datastore.gorm.finders.FindAllByBooleanFinder -import org.grails.datastore.gorm.finders.FindAllByFinder -import org.grails.datastore.gorm.finders.FindByBooleanFinder -import org.grails.datastore.gorm.finders.FindByFinder -import org.grails.datastore.gorm.finders.FindOrCreateByFinder -import org.grails.datastore.gorm.finders.FindOrSaveByFinder -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.finders.ListOrderByFinder -import org.grails.datastore.gorm.internal.InstanceMethodInvokingClosure -import org.grails.datastore.gorm.internal.StaticMethodInvokingClosure -import org.grails.datastore.gorm.query.NamedQueriesBuilder -import org.grails.datastore.gorm.validation.constraints.UniqueConstraintFactory -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.model.types.Basic -import org.grails.datastore.mapping.model.types.EmbeddedCollection -import org.grails.datastore.mapping.model.types.ManyToMany -import org.grails.datastore.mapping.model.types.OneToMany -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher -import org.springframework.transaction.PlatformTransactionManager -import org.grails.datastore.mapping.proxy.ProxyFactory - -/** - * Enhances a class with GORM behavior - * - * @author Graeme Rocher - */ -class GormEnhancer { - - Datastore datastore - PlatformTransactionManager transactionManager - List finders - boolean failOnError - - GormEnhancer(Datastore datastore) { - this(datastore, null) - } - - GormEnhancer(Datastore datastore, PlatformTransactionManager transactionManager) { - this.datastore = datastore - this.transactionManager = transactionManager - registerConstraints(datastore) - } - - protected void registerConstraints(Datastore datastore) { - ConstrainedProperty.registerNewConstraint("unique", new UniqueConstraintFactory(datastore)) - } - - List getFinders() { - if (finders == null) { - finders = Collections.unmodifiableList(createDynamicFinders()) - } - finders - } - - /** - * Enhances all persistent entities. - * - * @param onlyExtendedMethods If only to add additional methods provides by subclasses of the GORM APIs - */ - void enhance(boolean onlyExtendedMethods = false) { - for (PersistentEntity e in datastore.mappingContext.persistentEntities) { - enhance e, onlyExtendedMethods - } - } - - /** - * Enhance and individual entity - * - * @param e The entity - * @param onlyExtendedMethods If only to add additional methods provides by subclasses of the GORM APIs - */ - void enhance(PersistentEntity e, boolean onlyExtendedMethods = false) { - def cls = e.javaClass - def cpf = ClassPropertyFetcher.forClass(cls) - def staticMethods = getStaticApi(cls) - staticMethods.transactionManager = transactionManager - def instanceMethods = [getInstanceApi(cls), getValidationApi(cls)] - def tm = transactionManager - - List namedQueries = cpf.getStaticPropertyValuesFromInheritanceHierarchy('namedQueries', Closure) - for (int i = namedQueries.size(); i > 0; i--) { - Closure closure = namedQueries.get(i - 1) - registerNamedQueries(e, closure) - } - - ExpandoMetaClass mc = GrailsMetaClassUtils.getExpandoMetaClass(cls) - for (currentInstanceMethods in instanceMethods) { - def apiProvider = currentInstanceMethods - if (GormInstanceApi.isInstance(apiProvider)) { - mc.static.currentGormInstanceApi = {-> apiProvider } - } - else { - mc.static.currentGormValidationApi = {-> apiProvider } - } - - for (Method method in (onlyExtendedMethods ? apiProvider.extendedMethods : apiProvider.methods)) { - def methodName = method.name - Class[] parameterTypes = method.parameterTypes - - if (parameterTypes) { - parameterTypes = parameterTypes.length == 1 ? [] : parameterTypes[1..-1] - - // use fake object just so we have the right method signature - - final tooCall = new InstanceMethodInvokingClosure(apiProvider, methodName, parameterTypes) - def pt = parameterTypes - // Hack to workaround http://jira.codehaus.org/browse/GROOVY-4720 - final closureMethod = new ClosureStaticMetaMethod(methodName, cls, tooCall, pt) { - @Override - int getModifiers() { Modifier.PUBLIC } - } - mc.registerInstanceMethod(closureMethod) - } - } - } - - final proxyFactory = datastore.mappingContext.proxyFactory - for (p in e.associations) { - def prop = p - def isBasic = prop instanceof Basic - if(prop instanceof ToOne) { - registerAssociationIdentifierGetter(proxyFactory, mc, prop) - } - else if ((prop instanceof OneToMany) || (prop instanceof ManyToMany) || isBasic || (prop instanceof EmbeddedCollection)) { - def associatedEntity = prop.associatedEntity - def javaClass = associatedEntity?.javaClass - if(javaClass || isBasic) { - mc."addTo${prop.capitilizedName}" = { arg -> - def obj - if (delegate[prop.name] == null) { - delegate[prop.name] = [].asType(prop.type) - } - if (arg instanceof Map) { - obj = javaClass.newInstance(arg) - delegate[prop.name].add(obj) - } - else if (isBasic) { - delegate[prop.name].add(arg) - return delegate - } - else if (javaClass.isInstance(arg)) { - obj = arg - delegate[prop.name].add(obj) - } - else { - throw new MissingMethodException("addTo${prop.capitilizedName}", e.javaClass, [arg] as Object[]) - } - if (prop.bidirectional && prop.inverseSide) { - def otherSide = prop.inverseSide - String name = otherSide.name - if (otherSide instanceof OneToMany || otherSide instanceof ManyToMany) { - if (obj[name] == null) { - obj[name] = [].asType(otherSide.type) - } - obj[name].add(delegate) - } - else { - obj[name] = delegate - } - } - delegate - } - mc."removeFrom${prop.capitilizedName}" = { arg -> - if (javaClass.isInstance(arg)) { - delegate[prop.name]?.remove(arg) - if (prop.bidirectional) { - def otherSide = prop.inverseSide - if (otherSide instanceof ManyToMany) { - String name = otherSide.name - arg[name]?.remove(delegate) - } - else { - arg[otherSide.name] = null - } - } - } - else { - throw new MissingMethodException("removeFrom${prop.capitilizedName}", e.javaClass, [arg] as Object[]) - } - delegate - } - } - } - } - - def staticScope = mc.static - staticScope.currentGormStaticApi = {-> staticMethods } - for (Method m in (onlyExtendedMethods ? staticMethods.extendedMethods : staticMethods.methods)) { - def method = m - if (method != null) { - def methodName = method.name - def parameterTypes = method.parameterTypes - if (parameterTypes != null) { - def callable = new StaticMethodInvokingClosure(staticMethods, methodName, parameterTypes) - staticScope."$methodName" = callable - } - } - } - } - - protected void registerAssociationIdentifierGetter(ProxyFactory proxyFactory, MetaClass metaClass, ToOne association) { - final propName = association.name - final getterName = GrailsNameUtils.getGetterName(propName) - metaClass."${getterName}Id" = {-> - final associationInstance = delegate.getProperty(propName) - if (associationInstance != null) { - if (proxyFactory.isProxy(associationInstance)) { - return proxyFactory.getIdentifier(associationInstance) - } - else { - return datastore.currentSession.getObjectIdentifier(associationInstance) - } - } - } - } - - protected void registerNamedQueries(PersistentEntity entity, namedQueries) { - new NamedQueriesBuilder(entity, getFinders()).evaluate namedQueries - } - - protected GormStaticApi getStaticApi(Class cls) { - new GormStaticApi(cls, datastore, getFinders()) - } - - protected GormInstanceApi getInstanceApi(Class cls) { - def instanceApi = new GormInstanceApi(cls, datastore) - instanceApi.failOnError = failOnError - return instanceApi - } - - protected GormValidationApi getValidationApi(Class cls) { - new GormValidationApi(cls, datastore) - } - - protected List createDynamicFinders() { - [new FindOrCreateByFinder(datastore), - new FindOrSaveByFinder(datastore), - new FindByFinder(datastore), - new FindAllByFinder(datastore), - new FindAllByBooleanFinder(datastore), - new FindByBooleanFinder(datastore), - new CountByFinder(datastore), - new ListOrderByFinder(datastore)] - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormInstanceApi.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormInstanceApi.groovy deleted file mode 100644 index 5d09b318a..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormInstanceApi.groovy +++ /dev/null @@ -1,308 +0,0 @@ -/* Copyright (C) 2010 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 - -import grails.validation.ValidationException -import groovy.transform.CompileStatic - -import org.codehaus.groovy.runtime.InvokerHelper -import org.grails.datastore.mapping.dirty.checking.DirtyCheckingSupport -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.core.SessionCallback -import org.grails.datastore.mapping.dirty.checking.DirtyCheckable -import org.grails.datastore.mapping.proxy.EntityProxy - -/** - * Instance methods of the GORM API. - * - * @author Graeme Rocher - * @param the entity/domain class - */ -@CompileStatic -class GormInstanceApi extends AbstractGormApi { - - Class validationException = ValidationException - boolean failOnError = false - - GormInstanceApi(Class persistentClass, Datastore datastore) { - super(persistentClass, datastore) - } - - /** - * Proxy aware instanceOf implementation. - */ - boolean instanceOf(D o, Class cls) { - if (o instanceof EntityProxy) { - o = (D)((EntityProxy)o).getTarget() - } - return o in cls - } - - /** - * Upgrades an existing persistence instance to a write lock - * @return The instance - */ - D lock(D instance) { - execute({ Session session -> - session.lock(instance) - return instance - } as SessionCallback) - } - - /** - * Locks the instance for updates for the scope of the passed closure - * - * @param callable The closure - * @return The result of the closure - */ - def mutex(D instance, Closure callable) { - execute({ Session session -> - try { - session.lock(instance) - callable?.call() - } - finally { - session.unlock(instance) - } - } as SessionCallback) - } - - /** - * Refreshes the state of the current instance - * @param instance The instance - * @return The instance - */ - D refresh(D instance) { - execute({ Session session -> - session.refresh instance - return instance - } as SessionCallback) - } - - /** - * Saves an object the datastore - * @param instance The instance - * @return Returns the instance - */ - D save(D instance) { - save(instance, Collections.emptyMap()) - } - - /** - * Forces an insert of an object to the datastore - * @param instance The instance - * @return Returns the instance - */ - D insert(D instance) { - insert(instance, Collections.emptyMap()) - } - - /** - * Forces an insert of an object to the datastore - * @param instance The instance - * @return Returns the instance - */ - D insert(D instance, Map params) { - execute({ Session session -> - doSave instance, params, session, true - } as SessionCallback) - } - - /** - * Saves an object the datastore - * @param instance The instance - * @return Returns the instance - */ - D merge(D instance) { - save(instance, Collections.emptyMap()) - } - - /** - * Saves an object the datastore - * @param instance The instance - * @return Returns the instance - */ - D merge(D instance, Map params) { - save(instance, params) - } - - /** - * Save method that takes a boolean which indicates whether to perform validation or not - * - * @param instance The instance - * @param validate Whether to perform validation - * - * @return The instance or null if validation fails - */ - D save(D instance, boolean validate) { - save(instance, [validate: validate]) - } - - /** - * Saves an object with the given parameters - * @param instance The instance - * @param params The parameters - * @return The instance - */ - D save(D instance, Map params) { - execute({ Session session -> - doSave instance, params, session - } as SessionCallback) - } - - protected D doSave(D instance, Map params, Session session, boolean isInsert = false) { - boolean hasErrors = false - boolean validate = params?.containsKey("validate") ? params.validate : true - if (instance.respondsTo('validate') && validate) { - session.datastore.setSkipValidation(instance, false) - hasErrors = !InvokerHelper.invokeMethod(instance, "validate", null) - } - else { - session.datastore.setSkipValidation(instance, true) - InvokerHelper.invokeMethod(instance, "clearErrors", null) - } - - if (hasErrors) { - boolean failOnErrorEnabled = params?.containsKey("failOnError") ? params.failOnError : failOnError - if (failOnErrorEnabled) { - throw validationException.newInstance("Validation error occurred during call to save()", InvokerHelper.getProperty(instance, "errors")) - } - return null - } - if (isInsert) { - session.insert(instance) - } - else { - session.persist(instance) - } - if (params?.flush) { - session.flush() - } - return instance - } - - /** - * Returns the objects identifier - */ - Serializable ident(D instance) { - (Serializable)instance[persistentEntity.getIdentity().name] - } - - /** - * Attaches an instance to an existing session. Requries a session-based model - * @param instance The instance - * @return - */ - D attach(D instance) { - execute({ Session session -> - session.attach(instance) - instance - } as SessionCallback) - } - - /** - * No concept of session-based model so defaults to true - */ - boolean isAttached(D instance) { - execute({ Session session -> - session.contains(instance) - } as SessionCallback) - } - - /** - * Discards any pending changes. Requires a session-based model. - */ - void discard(D instance) { - execute({ Session session -> - session.clear(instance) - } as SessionCallback) - } - - /** - * Deletes an instance from the datastore - * @param instance The instance to delete - */ - void delete(D instance) { - delete(instance, Collections.emptyMap()) - } - - /** - * Deletes an instance from the datastore - * @param instance The instance to delete - */ - void delete(D instance, Map params) { - execute({ Session session -> - session.delete(instance) - if (params?.flush) { - session.flush() - } - } as SessionCallback) - } - - /** - * Checks whether a field is dirty - * - * @param instance The instance - * @param fieldName The name of the field - * - * @return true if the field is dirty - */ - boolean isDirty(D instance, String fieldName) { - if(instance instanceof DirtyCheckable) { - return ((DirtyCheckable)instance).hasChanged(fieldName) - } - return true - } - - /** - * Checks whether an entity is dirty - * - * @param instance The instance - * @return true if it is dirty - */ - boolean isDirty(D instance) { - if(instance instanceof DirtyCheckable) { - return ((DirtyCheckable)instance).hasChanged() || (datastore.hasCurrentSession() && DirtyCheckingSupport.areAssociationsDirty(datastore.currentSession, persistentEntity, instance)) - } - return true - } - - /** - * Obtains a list of property names that are dirty - * - * @param instance The instance - * @return A list of property names that are dirty - */ - List getDirtyPropertyNames(D instance) { - if(instance instanceof DirtyCheckable) { - return ((DirtyCheckable)instance).listDirtyPropertyNames() - } - return [] - } - - /** - * Gets the original persisted value of a field. - * - * @param fieldName The field name - * @return The original persisted value - */ - Object getPersistentValue(D instance, String fieldName) { - if(instance instanceof DirtyCheckable) { - return ((DirtyCheckable)instance).getOriginalValue(fieldName) - } - return null - } -} 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 deleted file mode 100644 index e34d68690..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormStaticApi.groovy +++ /dev/null @@ -1,857 +0,0 @@ -/* Copyright (C) 2010 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 - -import grails.gorm.CriteriaBuilder -import grails.gorm.DetachedCriteria -import grails.gorm.PagedResultList -import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode - -import org.codehaus.groovy.runtime.InvokerHelper -import org.grails.datastore.gorm.async.GormAsyncStaticApi -import org.grails.datastore.gorm.finders.DynamicFinder -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.core.AbstractDatastore -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.core.DatastoreUtils -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.core.SessionCallback -import org.grails.datastore.mapping.core.VoidSessionCallback -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.query.Query -import org.grails.datastore.mapping.query.api.Criteria -import org.springframework.beans.PropertyAccessorFactory -import org.springframework.beans.factory.config.AutowireCapableBeanFactory -import org.springframework.transaction.PlatformTransactionManager -import org.springframework.transaction.TransactionDefinition -import org.springframework.transaction.support.DefaultTransactionDefinition -import org.springframework.transaction.support.TransactionCallback -import org.springframework.transaction.support.TransactionTemplate -import org.springframework.util.Assert -import org.springframework.validation.Errors - -/** - * Static methods of the GORM API. - * - * @author Graeme Rocher - * @param the entity/domain class - */ -@CompileStatic -class GormStaticApi extends AbstractGormApi { - - List gormDynamicFinders - - PlatformTransactionManager transactionManager - - GormStaticApi(Class persistentClass, Datastore datastore, List finders) { - this(persistentClass, datastore, finders, null) - } - - GormStaticApi(Class persistentClass, Datastore datastore, List finders, PlatformTransactionManager transactionManager) { - super(persistentClass, datastore) - gormDynamicFinders = finders - this.transactionManager = transactionManager - } - - /** - * @return The PersistentEntity for this class - */ - PersistentEntity getGormPersistentEntity() { - persistentEntity - } - - /** - * Method missing handler that deals with the invocation of dynamic finders - * - * @param methodName The method name - * @param args The arguments - * @return The result of the method call - */ - @CompileStatic(TypeCheckingMode.SKIP) - def methodMissing(String methodName, Object args) { - FinderMethod method = gormDynamicFinders.find { FinderMethod f -> f.isMethodMatch(methodName) } - if (!method) { - throw new MissingMethodException(methodName, persistentClass, args) - } - - def mc = persistentClass.getMetaClass() - - // register the method invocation for next time - mc.static."$methodName" = { Object[] varArgs -> - // FYI... This is relevant to http://jira.grails.org/browse/GRAILS-3463 and may - // become problematic if http://jira.codehaus.org/browse/GROOVY-5876 is addressed... - def argumentsForMethod = varArgs?.length == 1 && varArgs[0].getClass().isArray() ? varArgs[0] : varArgs - method.invoke(delegate, methodName, argumentsForMethod) - } - - return method.invoke(persistentClass, methodName, args) - } - - /** - * - * @param callable Callable closure containing detached criteria definition - * @return The DetachedCriteria instance - */ - DetachedCriteria where(Closure callable) { - new DetachedCriteria(persistentClass).build(callable) - } - - /** - * - * @param callable Callable closure containing detached criteria definition - * @return The DetachedCriteria instance that is lazily initialized - */ - DetachedCriteria whereLazy(Closure callable) { - new DetachedCriteria(persistentClass).buildLazy(callable) - } - /** - * - * @param callable Callable closure containing detached criteria definition - * @return The DetachedCriteria instance - */ - DetachedCriteria whereAny(Closure callable) { - (DetachedCriteria)new DetachedCriteria(persistentClass).or(callable) - } - - /** - * Uses detached criteria to build a query and then execute it returning a list - * - * @param callable The callable - * @return A List of entities - */ - List findAll(Closure callable) { - def criteria = new DetachedCriteria(persistentClass).build(callable) - return criteria.list() - } - - /** - * Uses detached criteria to build a query and then execute it returning a list - * - * @param args pagination parameters - * @param callable The callable - * @return A List of entities - */ - List findAll(Map args, Closure callable) { - def criteria = new DetachedCriteria(persistentClass).build(callable) - return criteria.list(args) - } - - /** - * Uses detached criteria to build a query and then execute it returning a list - * - * @param callable The callable - * @return A single entity - */ - D find(Closure callable) { - def criteria = new DetachedCriteria(persistentClass).build(callable) - return criteria.find() - } - - /** - * Saves a list of objects in one go - * @param objectsToSave The objects to save - * @return A list of object identifiers - */ - List saveAll(Object... objectsToSave) { - (List)execute({ Session session -> - session.persist Arrays.asList(objectsToSave) - } as SessionCallback) - } - - /** - * Saves a list of objects in one go - * @param objectToSave Collection of objects to save - * @return A list of object identifiers - */ - List saveAll(Iterable objectsToSave) { - (List)execute({ Session session -> - session.persist objectsToSave - } as SessionCallback) - } - - /** - * Deletes a list of objects in one go - * @param objectsToDelete The objects to delete - */ - void deleteAll(Object... objectsToDelete) { - execute({ Session session -> - session.delete Arrays.asList(objectsToDelete) - } as SessionCallback) - } - - /** - * Deletes a list of objects in one go - * @param objectsToDelete Collection of objects to delete - */ - void deleteAll(Iterable objectToDelete) { - execute({ Session session -> - session.delete objectToDelete - } as SessionCallback) - } - - /** - * Creates an instance of this class - * @return The created instance - */ - @CompileStatic(TypeCheckingMode.SKIP) - D create() { - D d = persistentClass.newInstance() - datastore.applicationContext.autowireCapableBeanFactory.autowireBeanProperties( - d, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false) - d - } - - /** - * Retrieves and object from the datastore. eg. Book.get(1) - */ - D get(Serializable id) { - (D)execute({ Session session -> - session.retrieve((Class)persistentClass, id) - } as SessionCallback) - } - - /** - * Retrieves and object from the datastore. eg. Book.read(1) - * - * Since the datastore abstraction doesn't support dirty checking yet this - * just delegates to {@link #get(Serializable)} - */ - D read(Serializable id) { - (D)execute ({ Session session -> - session.retrieve((Class)persistentClass, id) - } as SessionCallback) - } - - /** - * Retrieves and object from the datastore as a proxy. eg. Book.load(1) - */ - D load(Serializable id) { - (D)execute ({ Session session -> - session.proxy((Class)persistentClass, id) - } as SessionCallback) - } - - /** - * Retrieves and object from the datastore as a proxy. eg. Book.proxy(1) - */ - D proxy(Serializable id) { - load(id) - } - - /** - * Retrieve all the objects for the given identifiers - * @param ids The identifiers to operate against - * @return A list of identifiers - */ - List getAll(Serializable... ids) { - (List)execute ({ Session session -> - session.retrieveAll(persistentClass, ids.flatten()) - } as SessionCallback) - } - - /** - * @return The async version of the GORM static API - */ - GormAsyncStaticApi getAsync() { - return new GormAsyncStaticApi(this) - } - - /** - * @return Synonym for {@link #list()} - */ - List getAll() { - list() - } - - /** - * Creates a criteria builder instance - */ - Criteria createCriteria() { - new CriteriaBuilder(persistentClass, datastore.currentSession) - } - - /** - * Creates a criteria builder instance - */ - def withCriteria(Closure callable) { - return InvokerHelper.invokeMethod(createCriteria(), 'call', callable) - } - - /** - * Creates a criteria builder instance - */ - def withCriteria(Map builderArgs, Closure callable) { - def criteriaBuilder = createCriteria() - def builderBean = PropertyAccessorFactory.forBeanPropertyAccess(criteriaBuilder) - for (entry in builderArgs.entrySet()) { - String propertyName = entry.key.toString() - if (builderBean.isWritableProperty(propertyName)) { - builderBean.setPropertyValue(propertyName, entry.value) - } - } - - return criteriaBuilder.list(callable) - } - - /** - * Locks an instance for an update - * @param id The identifier - * @return The instance - */ - D lock(Serializable id) { - (D)execute ({ Session session -> - session.lock((Class)persistentClass, id) - } as SessionCallback) - } - - /** - * Merges an instance with the current session - * @param d The object to merge - * @return The instance - */ - D merge(D d) { - execute ({ Session session -> - session.persist(d) - return d - } as SessionCallback) - } - - /** - * Counts the number of persisted entities - * @return The number of persisted entities - */ - Integer count() { - (Integer)execute ({ Session session -> - - def q = session.createQuery(persistentClass) - q.projections().count() - def result = q.singleResult() - if (!(result instanceof Number)) { - result = result.toString() - } - try { - return result as Integer - } - catch (NumberFormatException e) { - return 0 - } - } as SessionCallback) - } - - /** - * Same as {@link #count()} but allows property-style syntax (Foo.count) - */ - Integer getCount() { - count() - } - - /** - * Checks whether an entity exists - */ - boolean exists(Serializable id) { - get(id) != null - } - - /** - * Lists objects in the datastore. eg. Book.list(max:10) - * - * @param params Any parameters such as offset, max etc. - * @return A list of results - */ - List list(Map params) { - (List)execute ({ Session session -> - Query q = session.createQuery(persistentClass) - DynamicFinder.populateArgumentsForCriteria(persistentClass, q, params) - if (params?.max) { - return new PagedResultList(q) - } - return q.list() - } as SessionCallback) - } - - /** - * List all entities - * - * @return The list of all entities - */ - List list() { - (List)execute ({ Session session -> - session.createQuery(persistentClass).list() - } as SessionCallback) - } - - /** - * The same as {@link #list()} - * - * @return The list of all entities - */ - List findAll() { - list() - } - - /** - * Finds an object by example - * - * @param example The example - * @return A list of matching results - */ - List findAll(D example) { - findAll(example, Collections.emptyMap()) - } - - /** - * Finds an object by example using the given arguments for pagination - * - * @param example The example - * @param args The arguments - * - * @return A list of matching results - */ - List findAll(D example, Map args) { - if (!persistentEntity.isInstance(example)) { - return Collections.emptyList() - } - - def queryMap = createQueryMapForExample(persistentEntity, example) - return findAllWhere(queryMap, args) - } - - /** - * Finds the first object using the natural sort order - * - * @return the first object in the datastore, null if none exist - */ - D first() { - first([:]) - } - - /** - * Finds the first object sorted by propertyName - * - * @param propertyName the name of the property to sort by - * - * @return the first object in the datastore sorted by propertyName, null if none exist - */ - D first(String propertyName) { - first(sort: propertyName) - } - - /** - * Finds the first object. If queryParams includes 'sort', that will - * dictate the sort order, otherwise natural sort order will be used. - * queryParams may include any of the same parameters that might be passed - * to the list(Map) method. This method will ignore 'order' and 'max' as - * those are always 'asc' and 1, respectively. - * - * @return the first object in the datastore, null if none exist - */ - D first(Map queryParams) { - queryParams.max = 1 - queryParams.order = 'asc' - if (!queryParams.containsKey('sort')) { - def idPropertyName = persistentEntity.identity?.name - if (idPropertyName) { - queryParams.sort = idPropertyName - } - } - def resultList = list(queryParams) - resultList ? resultList[0] : null - } - - /** - * Finds the last object using the natural sort order - * - * @return the last object in the datastore, null if none exist - */ - D last() { - last([:]) - } - - /** - * Finds the last object sorted by propertyName - * - * @param propertyName the name of the property to sort by - * - * @return the last object in the datastore sorted by propertyName, null if none exist - */ - D last(String propertyName) { - last(sort: propertyName) - } - - /** - * Finds the last object. If queryParams includes 'sort', that will - * dictate the sort order, otherwise natural sort order will be used. - * queryParams may include any of the same parameters that might be passed - * to the list(Map) method. This method will ignore 'order' and 'max' as - * those are always 'asc' and 1, respectively. - * - * @return the last object in the datastore, null if none exist - */ - D last(Map queryParams) { - queryParams.max = 1 - queryParams.order = 'desc' - if (!queryParams.containsKey('sort')) { - def idPropertyName = persistentEntity.identity?.name - if (idPropertyName) { - queryParams.sort = idPropertyName - } - } - def resultList = list(queryParams) - resultList ? resultList[0] : null - } - - private Map createQueryMapForExample(PersistentEntity persistentEntity, D example) { - def props = persistentEntity.persistentProperties.findAll { PersistentProperty prop -> - !(prop instanceof Association) - } - - def queryMap = [:] - for (PersistentProperty prop in props) { - def val = example[prop.name] - if (val != null) { - queryMap[prop.name] = val - } - } - return queryMap - } - - /** - * Finds all results matching all of the given conditions. Eg. Book.findAllWhere(author:"Stephen King", title:"The Stand") - * - * @param queryMap The map of conditions - * @return A list of results - */ - List findAllWhere(Map queryMap) { - findAllWhere(queryMap, Collections.emptyMap()) - } - - /** - * Finds all results matching all of the given conditions. Eg. Book.findAllWhere(author:"Stephen King", title:"The Stand") - * - * @param queryMap The map of conditions - * @param args The Query arguments - * - * @return A list of results - */ - List findAllWhere(Map queryMap, Map args) { - (List)execute ({ Session session -> - Query q = session.createQuery(persistentClass) - q.allEq(queryMap) - DynamicFinder.populateArgumentsForCriteria persistentClass, q, args - q.list() - } as SessionCallback) - } - - /** - * Finds an object by example - * - * @param example The example - * @return A list of matching results - */ - D find(D example) { - find(example, Collections.emptyMap()) - } - - /** - * Finds an object by example using the given arguments for pagination - * - * @param example The example - * @param args The arguments - * - * @return A list of matching results - */ - D find(D example, Map args) { - if (persistentEntity.isInstance(example)) { - def queryMap = createQueryMapForExample(persistentEntity, example) - return findWhere(queryMap, args) - } - return null - } - - /** - * Finds a single result matching all of the given conditions. Eg. Book.findWhere(author:"Stephen King", title:"The Stand") - * - * @param queryMap The map of conditions - * @return A single result - */ - D findWhere(Map queryMap) { - findWhere(queryMap, Collections.emptyMap()) - } - - /** - * Finds a single result matching all of the given conditions. Eg. Book.findWhere(author:"Stephen King", title:"The Stand") - * - * @param queryMap The map of conditions - * @param args The Query arguments - * - * @return A single result - */ - D findWhere(Map queryMap, Map args) { - execute({ Session session -> - Query q = session.createQuery(persistentClass) - if (queryMap) { - q.allEq(queryMap) - } - DynamicFinder.populateArgumentsForCriteria persistentClass, q, args - q.singleResult() - } as SessionCallback) - } - - /** - * Finds a single result matching all of the given conditions. Eg. Book.findWhere(author:"Stephen King", title:"The Stand"). If - * a matching persistent entity is not found a new entity is created and returned. - * - * @param queryMap The map of conditions - * @return A single result - */ - D findOrCreateWhere(Map queryMap) { - internalFindOrCreate(queryMap, false) - } - - /** - * Finds a single result matching all of the given conditions. Eg. Book.findWhere(author:"Stephen King", title:"The Stand"). If - * a matching persistent entity is not found a new entity is created, saved and returned. - * - * @param queryMap The map of conditions - * @return A single result - */ - D findOrSaveWhere(Map queryMap) { - internalFindOrCreate(queryMap, true) - } - - private D internalFindOrCreate(Map queryMap, boolean shouldSave) { - D result = findWhere(queryMap) - if (!result) { - def persistentMetaClass = GroovySystem.metaClassRegistry.getMetaClass(persistentClass) - result = persistentMetaClass.invokeConstructor(queryMap) - if (shouldSave) { - InvokerHelper.invokeMethod(result, "save", null) - } - } - result - } - - /** - * Execute a closure whose first argument is a reference to the current session. - * - * @param callable the closure - * @return The result of the closure - */ - def withSession(Closure callable) { - execute ({ Session session -> - callable.call session - } as SessionCallback) - } - - /** - * Same as withSession, but present for the case where withSession is overridden to use the Hibernate session - * - * @param callable the closure - * @return The result of the closure - */ - def withDatastoreSession(Closure callable) { - execute ({ Session session -> - callable.call session - } as SessionCallback) - } - - /** - * Executes the closure within the context of a transaction, creating one if none is present or joining - * an existing transaction if one is already present. - * - * @param callable The closure to call - * @return The result of the closure execution - */ - def withTransaction(Closure callable) { - Assert.notNull transactionManager, "No transactionManager bean configured" - - if (!callable) { - return - } - - new TransactionTemplate(transactionManager).execute(callable as TransactionCallback) - } - - /** - * Executes the closure within the context of a new transaction - * - * @param callable The closure to call - * @return The result of the closure execution - */ - def withNewTransaction(Closure callable) { - Assert.notNull transactionManager, "No transactionManager bean configured" - - if (!callable) { - return - } - - def transactionTemplate = new TransactionTemplate(transactionManager, - new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW)) - transactionTemplate.execute(callable as TransactionCallback) - } - - /** - * Executes the closure within the context of a transaction for the given {@link TransactionDefinition} - * - * @param callable The closure to call - * @return The result of the closure execution - */ - def withTransaction(TransactionDefinition definition, Closure callable) { - Assert.notNull transactionManager, "No transactionManager bean configured" - - if (!callable) { - return - } - - new TransactionTemplate(transactionManager, definition).execute(callable as TransactionCallback) - } - - /** - * Creates and binds a new session for the scope of the given closure - */ - def withNewSession(Closure callable) { - def session = datastore.connect() - try { - DatastoreUtils.bindNewSession session - return callable?.call(session) - } - finally { - DatastoreUtils.unbindSession session - } - } - - /** - * Creates and binds a new session for the scope of the given closure - */ - def withStatelessSession(Closure callable) { - if(datastore instanceof org.grails.datastore.mapping.core.StatelessDatastore) { - def session = datastore.connectStateless() - try { - DatastoreUtils.bindNewSession session - return callable?.call(session) - } - finally { - DatastoreUtils.unbindSession session - } - } - else { - throw new UnsupportedOperationException("Stateless sessions not supported by implementation") - } - } - - /** - * Get the thread-local map used to store Errors when validating. - * @return the map - */ - Map getValidationErrorsMap() { - AbstractDatastore.getValidationErrorsMap() - } - - /** - * Get the thread-local map used to store whether to skip validation. - * @return the map - */ - Map getValidationSkipMap() { - AbstractDatastore.getValidationSkipMap() - } - - // TODO: In the first version no support will exist for String-based queries - List executeQuery(String query) { - unsupported("executeQuery") - } - - List executeQuery(String query, Map args) { - unsupported("executeQuery") - } - - List executeQuery(String query, Map params, Map args) { - unsupported("executeQuery") - } - - List executeQuery(String query, Collection params) { - unsupported("executeQuery") - } - - List executeQuery(String query, Collection params, Map args) { - unsupported("executeQuery") - } - - Integer executeUpdate(String query) { - unsupported("executeUpdate") - } - - Integer executeUpdate(String query, Map args) { - unsupported("executeUpdate") - } - - Integer executeUpdate(String query, Map params, Map args) { - unsupported("executeUpdate") - } - - Integer executeUpdate(String query, Collection params) { - unsupported("executeUpdate") - } - - Integer executeUpdate(String query, Collection params, Map args) { - unsupported("executeUpdate") - } - - D find(String query) { - unsupported("find") - } - - D find(String query, Map args) { - unsupported("find") - } - - D find(String query, Map params, Map args) { - unsupported("find") - } - - D find(String query, Collection params) { - unsupported("find") - } - - D find(String query, Collection params, Map args) { - unsupported("find") - } - - List findAll(String query) { - unsupported("findAll") - } - - List findAll(String query, Map args) { - unsupported("findAll") - } - - List findAll(String query, Map params, Map args) { - unsupported("findAll") - } - - List findAll(String query, Collection params) { - unsupported("find") - } - - List findAll(String query, Collection params, Map args) { - unsupported("findAll") - } - - protected void unsupported(method) { - throw new UnsupportedOperationException("String-based queries like [$method] are currently not supported in this implementation of GORM. Use criteria instead.") - } -} 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 deleted file mode 100644 index 6f2f3403a..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormValidationApi.groovy +++ /dev/null @@ -1,204 +0,0 @@ -/* Copyright (C) 2010 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 - -import org.codehaus.groovy.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 -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.validation.ValidationErrors -import org.springframework.validation.Errors -import org.springframework.validation.FieldError -import org.springframework.validation.ObjectError -import org.springframework.validation.Validator - -/** - * Methods used for validating GORM instances. - * - * @author Graeme Rocher - * @param the entity/domain class - * @since 1.0 - */ -class GormValidationApi extends AbstractGormApi { - - Validator validator - BeforeValidateHelper beforeValidateHelper - - GormValidationApi(Class persistentClass, Datastore datastore) { - super(persistentClass, datastore) - MappingContext context = datastore.mappingContext - def entity = context.getPersistentEntity(persistentClass.name) - validator = context.getEntityValidator(entity) - beforeValidateHelper = new BeforeValidateHelper() - } - - private boolean doValidate(D instance, Map arguments, List fields) { - beforeValidateHelper.invokeBeforeValidate instance, fields - fireEvent(instance, fields) - - if (!validator) { - validator = datastore.mappingContext.getEntityValidator(persistentEntity) - if (!validator) { - return true - } - } - - def localErrors = new ValidationErrors(instance) - - Errors errors = instance.errors - - if (validator instanceof CascadingValidator) { - validator.validate instance, localErrors, arguments?.deepValidate != false - } else { - validator.validate instance, localErrors - } - - if (fields) { - localErrors = filterErrors(localErrors, fields as Set, instance) - } - - for (error in errors.allErrors) { - if (error instanceof FieldError) { - if (error.bindingFailure) { - localErrors.addError error - } - } else { - localErrors.addError error - } - } - - instance.errors = localErrors - - return !instance.errors.hasErrors() - } - - /** - * Validates an instance for the given arguments - * - * @param instance The instance to validate - * @param arguments The arguments to use - * @return True if the instance is valid - */ - boolean validate(D instance, Map arguments) { - doValidate instance, arguments, (List)null - } - - /** - * Validates an instance - * - * @param instance The instance to validate - * @param fields The list of fields to validate - * @return True if the instance is valid - */ - boolean validate(D instance, List fields) { - doValidate instance, (Map)null, fields - } - - private Errors filterErrors(Errors errors, Set validatedFields, Object target) { - if (!validatedFields) return errors - - Errors result = new ValidationErrors(target) - - for (ObjectError error : errors.getAllErrors()) { - - if (error instanceof FieldError) { - if (!validatedFields.contains(error.getField())) continue - } - - result.addError(error) - } - - return result - } - - /** - * Fire the validation event. - * @param target The target instance. - * @param fields The list of fields being validated, or null. - */ - private void fireEvent(target, List fields) { - ValidationEvent event = new ValidationEvent(datastore, target) - event.validatedFields = fields - datastore.applicationEventPublisher?.publishEvent(event) - } - - /** - * Validates an instance - * - * @param instance The instance to validate - * @return True if the instance is valid - */ - boolean validate(D instance) { - 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 - * @param instance The instance to obtain errors for - * @return The {@link Errors} instance - */ - Errors getErrors(D instance) { - def errors = datastore.getObjectErrors(instance) - if (errors == null) { - errors = resetErrors(instance) - } - return errors - } - - private Errors resetErrors(D instance) { - def errors = new ValidationErrors(instance) - instance.errors = errors - return errors - } - - /** - * Sets the errors for an instance - * @param instance The instance - * @param errors The errors - */ - void setErrors(D instance, Errors errors) { - datastore.setObjectErrors instance, errors - } - - /** - * Clears any errors that exist on an instance - * @param instance The instance - */ - void clearErrors(D instance) { - resetErrors(instance) - } - - /** - * Tests whether an instance has any errors - * @param instance The instance - * @return True if errors exist - */ - boolean hasErrors(D instance) { - datastore.getObjectErrors(instance)?.hasErrors() - } -} 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 deleted file mode 100644 index 701ed91bc..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/async/AsyncQuery.groovy +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (C) 2013 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.async - -import grails.async.DelegateAsync -import org.grails.async.decorator.PromiseDecorator -import org.grails.async.decorator.PromiseDecoratorProvider -import org.grails.datastore.gorm.query.GormOperations - -/** - * Exposes all methods from the {@link GormOperations} interface asynchronously - * - * @author Graeme Rocher - * @since 2.3 - */ -class AsyncQuery implements PromiseDecoratorProvider{ - - @DelegateAsync GormOperations gormOperations - - /** - * Wraps each promise in a new persistence session - */ - private List decorators = [ { Closure callable -> - return { args -> - gormOperations.persistentClass.withNewSession { - callable.call(*args) - } - } - } as PromiseDecorator ] - - - AsyncQuery(GormOperations gormOperations) { - this.gormOperations = gormOperations - } - - @Override - List getDecorators() { - return decorators - } -} 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 deleted file mode 100644 index 1e02cbbed..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/async/GormAsyncStaticApi.groovy +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (C) 2013 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.async - -import grails.async.Promise -import grails.async.Promises -import groovy.transform.CompileStatic -import org.grails.async.decorator.PromiseDecorator -import org.grails.async.decorator.PromiseDecoratorProvider -import org.grails.datastore.gorm.GormStaticApi - -/** - * Transforms the GormStaticApi into an asynchronous API - * - * @author Graeme Rocher - * @since 2.3 - */ -class GormAsyncStaticApi implements PromiseDecoratorProvider{ - @grails.async.DelegateAsync GormStaticApi staticApi - - /** - * Wraps each promise in a new persistence session - */ - private List decorators = [ { Closure callable -> - return { args -> staticApi.withNewSession{ callable.call(*args) } } - } as PromiseDecorator ] - - GormAsyncStaticApi(GormStaticApi staticApi) { - this.staticApi = staticApi - } - - @Override - @CompileStatic - List getDecorators() { - this.decorators - } - - /** - * Used to perform a sequence of operations asynchronously - * @param callable The callable - * @return The promise - */ - @CompileStatic - public Promise task(Closure callable) { - callable.delegate = staticApi.gormPersistentEntity.javaClass - (Promise)Promises.createPromise(callable, decorators) - } -} \ No newline at end of file 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 deleted file mode 100644 index a97fd1a9e..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/bean/factory/AbstractMappingContextFactoryBean.groovy +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2010 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.bean.factory - -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.GrailsPluginManager -import org.codehaus.groovy.grails.plugins.support.aware.GrailsApplicationAware -import org.grails.datastore.gorm.proxy.GroovyProxyFactory -import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.springframework.beans.factory.FactoryBean -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware - -/** - * An abstract factory bean for constructing MappingContext instances - * - * @author Graeme Rocher - * @since 1.0 - */ -abstract class AbstractMappingContextFactoryBean implements FactoryBean, GrailsApplicationAware, ApplicationContextAware { - - private static final Log LOG = LogFactory.getLog(AbstractMappingContextFactoryBean) - - GrailsApplication grailsApplication - GrailsPluginManager pluginManager - ApplicationContext applicationContext - String mappingStrategy - boolean defaultExternal - - MappingContext getObject() { - def mappingContext = createMappingContext() - mappingContext.proxyFactory = new GroovyProxyFactory() - - registerCustomTypeMarshallers(mappingContext) - - if (mappingStrategy == null) { - mappingStrategy = (getClass().simpleName - 'MappingContextFactoryBean').toLowerCase() - } - - if (grailsApplication) { - for (GrailsDomainClass domainClass in grailsApplication.domainClasses) { - def domainMappingStrategy = domainClass.mappingStrategy - PersistentEntity entity - - if (mappingStrategy == domainMappingStrategy || (domainMappingStrategy == 'GORM' && !defaultExternal)) { - entity = mappingContext.addPersistentEntity(domainClass.clazz) - } - else { - entity = mappingContext.addExternalPersistentEntity(domainClass.clazz) - } - if (entity) { - final validatorBeanName = "${domainClass.fullName}Validator" - def validator = applicationContext.containsBean(validatorBeanName) ? applicationContext.getBean(validatorBeanName) : null - - if (validator) { - mappingContext.addEntityValidator(entity, validator) - } - } - } - } - return mappingContext - } - - protected void registerCustomTypeMarshallers(MappingContext mappingContext) { - try { - final typeMarshallers = applicationContext.getBeansOfType(org.grails.datastore.mapping.engine.types.CustomTypeMarshaller) - final mappingFactory = mappingContext.mappingFactory - for (marshaller in typeMarshallers.values()) { - mappingFactory.registerCustomType(marshaller) - } - } catch (e) { - LOG.error("Error configuring custom type marshallers: " + e.getMessage(), e) - } - } - - protected abstract MappingContext createMappingContext() - - Class getObjectType() { MappingContext } - - boolean isSingleton() { true } -} 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 deleted file mode 100644 index b6c511f6a..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassMappingContext.java +++ /dev/null @@ -1,65 +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.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 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; - -/** - * A MappingContext that adapts the Grails domain model to the Mapping API. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class GrailsDomainClassMappingContext extends AbstractMappingContext { - - private GrailsApplication grailsApplication; - - public GrailsDomainClassMappingContext(GrailsApplication grailsApplication) { - this.grailsApplication = grailsApplication; - - final GrailsClass[] artefacts = grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE); - for (GrailsClass grailsClass : artefacts) { - addPersistentEntity(grailsClass.getClazz()); - } - } - - public GrailsApplication getGrailsApplication() { - return grailsApplication; - } - - public MappingConfigurationStrategy getMappingSyntaxStrategy() { - throw new UnsupportedOperationException("MappingConfigurationStrategy not supported by implementation. Defined by Grails itself."); - } - - @Override - public MappingFactory getMappingFactory() { - throw new UnsupportedOperationException("MappingFactory not supported by implementation. Defined by Grails itself."); - } - - @Override - protected PersistentEntity createPersistentEntity(Class javaClass) { - GrailsDomainClass domainClass = (GrailsDomainClass) grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, javaClass.getName()); - return new GrailsDomainClassPersistentEntity(domainClass, this); - } -} 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 deleted file mode 100644 index ff274c2ce..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassPersistentEntity.java +++ /dev/null @@ -1,287 +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.config; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.codehaus.groovy.grails.commons.GrailsDomainClass; -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.grails.datastore.mapping.model.ClassMapping; -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.PropertyMapping; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.model.types.Embedded; -import org.grails.datastore.mapping.model.types.ManyToMany; -import org.grails.datastore.mapping.model.types.ManyToOne; -import org.grails.datastore.mapping.model.types.OneToMany; -import org.grails.datastore.mapping.model.types.OneToOne; - -/** - * Bridges the {@link GrailsDomainClass} interface into the {@link PersistentEntity} interface - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class GrailsDomainClassPersistentEntity implements PersistentEntity { - - private GrailsDomainClass domainClass; - private GrailsDomainClassMappingContext mappingContext; - private GrailsDomainClassPersistentProperty identifier; - private GrailsDomainClassPersistentProperty version; - private Map propertiesByName = new HashMap(); - private List properties = new ArrayList(); - private List associations = new ArrayList(); - private boolean initialized; - - public GrailsDomainClassPersistentEntity(GrailsDomainClass domainClass, - GrailsDomainClassMappingContext mappingContext) { - this.domainClass = domainClass; - this.mappingContext = mappingContext; - } - - /** - * @return The wrapped GrailsDomainClass instance - */ - public GrailsDomainClass getDomainClass() { - return domainClass; - } - - public boolean isInitialized() { - return initialized; - } - - public void initialize() { - identifier = new GrailsDomainClassPersistentProperty(this, domainClass.getIdentifier()); - version = new GrailsDomainClassPersistentProperty(this, domainClass.getVersion()); - - mappingContext.addEntityValidator(this, domainClass.getValidator()); - - final GrailsDomainClassProperty[] persistentProperties = domainClass.getPersistentProperties(); - for (GrailsDomainClassProperty grailsDomainClassProperty : persistentProperties) { - PersistentProperty persistentProperty; - if (grailsDomainClassProperty.isAssociation()) { - if (grailsDomainClassProperty.isEmbedded()) { - persistentProperty = createEmbedded(mappingContext,grailsDomainClassProperty); - } - else if (grailsDomainClassProperty.isOneToMany()) { - persistentProperty = createOneToMany(mappingContext, grailsDomainClassProperty); - } - else if (grailsDomainClassProperty.isHasOne()) { - persistentProperty = createOneToOne(mappingContext, grailsDomainClassProperty); - } - else if (grailsDomainClassProperty.isOneToOne()) { - persistentProperty = createOneToOne(mappingContext, grailsDomainClassProperty); - } - else if (grailsDomainClassProperty.isManyToOne()) { - persistentProperty = createManyToOne(mappingContext, grailsDomainClassProperty); - } - else if (grailsDomainClassProperty.isManyToMany()) { - persistentProperty = createManyToMany(mappingContext, grailsDomainClassProperty); - } - else { - persistentProperty = new GrailsDomainClassPersistentProperty(this, grailsDomainClassProperty); - } - } - else { - persistentProperty = new GrailsDomainClassPersistentProperty(this, grailsDomainClassProperty); - } - propertiesByName.put(grailsDomainClassProperty.getName(), persistentProperty); - properties.add(persistentProperty); - } - initialized = true; - } - - public String getName() { - return domainClass.getFullName(); - } - - public PersistentProperty getIdentity() { - return identifier; - } - - public PersistentProperty getVersion() { - return version; - } - - public boolean isVersioned() { - // TODO - return version != null; - } - - public List getPersistentProperties() { - return properties; - } - - public List getAssociations() { - return associations; - } - - public PersistentProperty getPropertyByName(String name) { - return propertiesByName.get(name); - } - - public Class getJavaClass() { - return domainClass.getClazz(); - } - - public boolean isInstance(Object obj) { - return domainClass.getClazz().isInstance(obj); - } - - public ClassMapping getMapping() { - return null; - } - - public Object newInstance() { - return domainClass.newInstance(); - } - - public List getPersistentPropertyNames() { - return new ArrayList( propertiesByName.keySet() ); - } - - public String getDecapitalizedName() { - return domainClass.getLogicalPropertyName(); - } - - public boolean isOwningEntity(PersistentEntity owner) { - return domainClass.isOwningClass(owner.getJavaClass()); - } - - public PersistentEntity getParentEntity() { - if (!isRoot()) { - return getMappingContext().getPersistentEntity( - getJavaClass().getSuperclass().getName()); - } - return null; - } - - public PersistentEntity getRootEntity() { - if (isRoot() || getParentEntity() == null) { - return this; - } - PersistentEntity parent = getParentEntity(); - while (!parent.isRoot()) { - parent = parent.getParentEntity(); - } - return parent; - } - - public boolean isRoot() { - return domainClass.isRoot(); - } - - public String getDiscriminator() { - return getName(); - } - - public MappingContext getMappingContext() { - return mappingContext; - } - - public boolean hasProperty(String name, Class type) { - return domainClass.hasProperty(name); - } - - public boolean isIdentityName(String propertyName) { - return domainClass.getIdentifier().getName().equals(propertyName); - } - - private PersistentProperty createManyToOne( - GrailsDomainClassMappingContext ctx, - GrailsDomainClassProperty grailsDomainClassProperty) { - final ManyToOne oneToOne = new ManyToOne(this, ctx, grailsDomainClassProperty.getName(), grailsDomainClassProperty.getType()) { - public PropertyMapping getMapping() { - return null; - } - }; - configureAssociation(grailsDomainClassProperty, oneToOne); - return oneToOne; - } - - private PersistentProperty createManyToMany( - GrailsDomainClassMappingContext ctx, - GrailsDomainClassProperty grailsDomainClassProperty) { - final ManyToMany manyToMany = new ManyToMany(this, ctx, grailsDomainClassProperty.getName(), grailsDomainClassProperty.getType()) { - public PropertyMapping getMapping() { - return null; - } - }; - configureAssociation(grailsDomainClassProperty, manyToMany); - return manyToMany; - } - - private PersistentProperty createOneToOne( - GrailsDomainClassMappingContext ctx, - GrailsDomainClassProperty grailsDomainClassProperty) { - final OneToOne oneToOne = new OneToOne(this, ctx, grailsDomainClassProperty.getName(), grailsDomainClassProperty.getType()) { - public PropertyMapping getMapping() { - return null; - } - }; - configureAssociation(grailsDomainClassProperty, oneToOne); - return oneToOne; - } - - private OneToMany createOneToMany(GrailsDomainClassMappingContext mappingContext, - GrailsDomainClassProperty grailsDomainClassProperty) { - final OneToMany oneToMany = new OneToMany(this, mappingContext, grailsDomainClassProperty.getName(), grailsDomainClassProperty.getType()) { - - public PropertyMapping getMapping() { - return null; - } - }; - configureAssociation(grailsDomainClassProperty, oneToMany); - - return oneToMany; - } - - private void configureAssociation( - GrailsDomainClassProperty grailsDomainClassProperty, - final Association association) { - association.setAssociatedEntity(getMappingContext().addPersistentEntity(grailsDomainClassProperty.getReferencedPropertyType())); - association.setOwningSide(grailsDomainClassProperty.isOwningSide()); - association.setReferencedPropertyName(grailsDomainClassProperty.getReferencedPropertyName()); - } - - private PersistentProperty createEmbedded( - GrailsDomainClassMappingContext mappingContext, - GrailsDomainClassProperty grailsDomainClassProperty) { - Embedded persistentProperty = new Embedded(this, mappingContext, grailsDomainClassProperty.getName(), grailsDomainClassProperty.getClass()) { - public PropertyMapping getMapping() { - return null; - } - }; - persistentProperty.setOwningSide(grailsDomainClassProperty.isOwningSide()); - persistentProperty.setReferencedPropertyName(grailsDomainClassProperty.getReferencedPropertyName()); - - return persistentProperty; - } - - public boolean isExternal() { - return false; - } - - public void setExternal(boolean external) { - // do nothing - } -} 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 deleted file mode 100644 index fe9d65e63..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/config/GrailsDomainClassPersistentProperty.java +++ /dev/null @@ -1,65 +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.config; - -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.PropertyMapping; -import org.grails.datastore.mapping.reflect.NameUtils; - -/** - * Bridges a {@link GrailsDomainClassProperty} to the {@link PersistentProperty} interface. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class GrailsDomainClassPersistentProperty implements PersistentProperty { - - private PersistentEntity owner; - private GrailsDomainClassProperty property; - - public GrailsDomainClassPersistentProperty(PersistentEntity owner, - GrailsDomainClassProperty property) { - this.owner = owner; - this.property = property; - } - - public String getName() { - return property.getName(); - } - - public String getCapitilizedName() { - return NameUtils.capitalize(getName()); - } - - public Class getType() { - return property.getType(); - } - - public PropertyMapping getMapping() { - return null; - } - - public PersistentEntity getOwner() { - return owner; - } - - public boolean isNullable() { - return property.isOptional(); - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/events/AutoTimestampEventListener.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/events/AutoTimestampEventListener.java deleted file mode 100644 index 88b0c6d96..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/events/AutoTimestampEventListener.java +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright (C) 2010 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.events; - -import java.util.Date; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.grails.datastore.mapping.config.Entity; -import org.grails.datastore.mapping.model.ClassMapping; -import org.springframework.context.ApplicationEvent; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; -import org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener; -import org.grails.datastore.mapping.engine.event.PreInsertEvent; -import org.grails.datastore.mapping.engine.event.PreUpdateEvent; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * An event listener that adds support for GORM-style auto-timestamping - * - * @author Graeme Rocher - * @since 1.0 - */ -public class AutoTimestampEventListener extends AbstractPersistenceEventListener implements MappingContext.Listener { - - public static final String DATE_CREATED_PROPERTY = "dateCreated"; - public static final String LAST_UPDATED_PROPERTY = "lastUpdated"; - - private Map entitiesWithDateCreated = new ConcurrentHashMap(); - private Map entitiesWithLastUpdated = new ConcurrentHashMap(); - - public AutoTimestampEventListener(final Datastore datastore) { - super(datastore); - - for (PersistentEntity persistentEntity : datastore.getMappingContext().getPersistentEntities()) { - storeDateCreatedInfo(persistentEntity); - storeLastUpdatedInfo(persistentEntity); - } - - datastore.getMappingContext().addMappingContextListener(this); - } - - @Override - protected void onPersistenceEvent(final AbstractPersistenceEvent event) { - if (event instanceof PreInsertEvent) { - beforeInsert(event.getEntity(), event.getEntityAccess()); - } - else if (event instanceof PreUpdateEvent) { - beforeUpdate(event.getEntity(), event.getEntityAccess()); - } - } - - public boolean supportsEventType(Class eventType) { - return PreInsertEvent.class.isAssignableFrom(eventType) || - PreUpdateEvent.class.isAssignableFrom(eventType); - } - - public boolean beforeInsert(PersistentEntity entity, EntityAccess ea) { - if (hasDateCreated(entity)) { - final Date now = new Date(); - ea.setProperty(DATE_CREATED_PROPERTY, now); - - if (hasLastupdated(entity)) { - ea.setProperty(LAST_UPDATED_PROPERTY, now); - } - } - return true; - } - - public boolean beforeUpdate(PersistentEntity entity, EntityAccess ea) { - if (hasLastupdated(entity)) { - ea.setProperty(LAST_UPDATED_PROPERTY, new Date()); - } - return true; - } - - private boolean hasLastupdated(PersistentEntity entity) { - return entitiesWithLastUpdated.containsKey(entity) && entitiesWithLastUpdated.get(entity); - } - - private boolean hasDateCreated(PersistentEntity entity) { - return entitiesWithDateCreated.containsKey(entity)&& entitiesWithDateCreated.get(entity); - } - - private void storeLastUpdatedInfo(PersistentEntity persistentEntity) { - ClassMapping classMapping = persistentEntity.getMapping(); - Entity mappedForm = classMapping.getMappedForm(); - if(mappedForm == null || mappedForm.isAutoTimestamp()) { - entitiesWithLastUpdated.put(persistentEntity, persistentEntity.hasProperty(LAST_UPDATED_PROPERTY, Date.class)); - } - } - - private void storeDateCreatedInfo(PersistentEntity persistentEntity) { - ClassMapping classMapping = persistentEntity.getMapping(); - Entity mappedForm = classMapping.getMappedForm(); - if(mappedForm == null || mappedForm.isAutoTimestamp()) { - entitiesWithDateCreated.put(persistentEntity, persistentEntity.hasProperty(DATE_CREATED_PROPERTY, Date.class)); - } - } - - public void persistentEntityAdded(PersistentEntity entity) { - storeDateCreatedInfo(entity); - storeLastUpdatedInfo(entity); - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/events/DomainEventListener.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/events/DomainEventListener.java deleted file mode 100644 index 043d2bb2c..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/events/DomainEventListener.java +++ /dev/null @@ -1,283 +0,0 @@ -/* Copyright (C) 2010 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.events; - -import java.lang.reflect.Method; -import java.sql.Timestamp; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.dirty.checking.DirtyCheckable; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.event.*; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; -import org.springframework.context.ApplicationEvent; -import org.springframework.util.ReflectionUtils; - -/** - * An event listener that provides support for GORM domain events. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class DomainEventListener extends AbstractPersistenceEventListener - implements MappingContext.Listener { - - private Map> entityEvents = new ConcurrentHashMap>(); - - @SuppressWarnings("rawtypes") - public static final Class[] ZERO_PARAMS = {}; - public static final String EVENT_BEFORE_INSERT = "beforeInsert"; - private static final String EVENT_BEFORE_UPDATE = "beforeUpdate"; - private static final String EVENT_BEFORE_DELETE = "beforeDelete"; - private static final String EVENT_BEFORE_LOAD = "beforeLoad"; - private static final String EVENT_AFTER_INSERT = "afterInsert"; - private static final String EVENT_AFTER_UPDATE = "afterUpdate"; - private static final String EVENT_AFTER_DELETE = "afterDelete"; - private static final String EVENT_AFTER_LOAD = "afterLoad"; - - private static final List REFRESH_EVENTS = Arrays.asList( - EVENT_BEFORE_INSERT, EVENT_BEFORE_UPDATE, EVENT_BEFORE_DELETE); - - public DomainEventListener(final Datastore datastore) { - super(datastore); - - for (PersistentEntity entity : datastore.getMappingContext().getPersistentEntities()) { - createEventCaches(entity); - } - - datastore.getMappingContext().addMappingContextListener(this); - } - - @Override - protected void onPersistenceEvent(final AbstractPersistenceEvent event) { - switch(event.getEventType()) { - case PreInsert: - if( !beforeInsert(event.getEntity(), event.getEntityAccess(), (PreInsertEvent) event) ) { - event.cancel(); - } - break; - case PostInsert: - afterInsert(event.getEntity(), event.getEntityAccess(), (PostInsertEvent) event); - break; - case PreUpdate: - if( !beforeUpdate(event.getEntity(), event.getEntityAccess(), (PreUpdateEvent) event) ) { - event.cancel(); - } - break; - case PostUpdate: - afterUpdate(event.getEntity(), event.getEntityAccess(), (PostUpdateEvent) event); - break; - case PreDelete: - if( ! beforeDelete(event.getEntity(), event.getEntityAccess(), (PreDeleteEvent) event) ) { - event.cancel(); - } - break; - case PostDelete: - afterDelete(event.getEntity(), event.getEntityAccess(), (PostDeleteEvent) event); - break; - case PreLoad: - beforeLoad(event.getEntity(), event.getEntityAccess(), (PreLoadEvent) event); - break; - case PostLoad: - afterLoad(event.getEntity(), event.getEntityAccess(), (PostLoadEvent) event); - break; - case SaveOrUpdate: - break; - case Validation: - break; - default: - break; - } - } - - /** - * @deprecated Use {@link #beforeInsert(org.grails.datastore.mapping.model.PersistentEntity, org.grails.datastore.mapping.engine.EntityAccess, org.grails.datastore.mapping.engine.event.PreInsertEvent)} instead - */ - public boolean beforeInsert(final PersistentEntity entity, final EntityAccess ea) { - return beforeInsert(entity, ea, null); - } - - public boolean beforeInsert(final PersistentEntity entity, final EntityAccess ea, PreInsertEvent event) { - - if (entity.isVersioned()) { - try { - setVersion(ea); - } - catch (RuntimeException e) { - // TODO - } - } - - return invokeEvent(EVENT_BEFORE_INSERT, entity, ea, event); - } - - protected void setVersion(final EntityAccess ea) { - if (Number.class.isAssignableFrom(ea.getPropertyType("version"))) { - ea.setProperty("version", 0); - } - else if (Timestamp.class.isAssignableFrom(ea.getPropertyType("version"))) { - ea.setProperty("version", new Timestamp(System.currentTimeMillis())); - } - else if (Date.class.isAssignableFrom(ea.getPropertyType("version"))) { - ea.setProperty("version", new Date()); - } - } - - public boolean beforeUpdate(final PersistentEntity entity, final EntityAccess ea) { - return invokeEvent(EVENT_BEFORE_UPDATE, entity, ea, null); - } - - public boolean beforeUpdate(final PersistentEntity entity, final EntityAccess ea, PreUpdateEvent event) { - return invokeEvent(EVENT_BEFORE_UPDATE, entity, ea, event); - } - - public boolean beforeDelete(final PersistentEntity entity, final EntityAccess ea) { - return invokeEvent(EVENT_BEFORE_DELETE, entity, ea, null); - } - - public boolean beforeDelete(final PersistentEntity entity, final EntityAccess ea, PreDeleteEvent event) { - return invokeEvent(EVENT_BEFORE_DELETE, entity, ea, event); - } - - public void beforeLoad(final PersistentEntity entity, final EntityAccess ea) { - beforeLoad(entity, ea, null); - } - - public void beforeLoad(final PersistentEntity entity, final EntityAccess ea, PreLoadEvent event) { - invokeEvent(EVENT_BEFORE_LOAD, entity, ea, event); - } - - public void afterDelete(final PersistentEntity entity, final EntityAccess ea) { - afterDelete(entity, ea, null); - } - - public void afterDelete(final PersistentEntity entity, final EntityAccess ea, PostDeleteEvent event) { - invokeEvent(EVENT_AFTER_DELETE, entity, ea, event); - } - - public void afterInsert(final PersistentEntity entity, final EntityAccess ea) { - afterInsert(entity, ea, null); - } - - public void afterInsert(final PersistentEntity entity, final EntityAccess ea, PostInsertEvent event) { - activateDirtyChecking(ea); - invokeEvent(EVENT_AFTER_INSERT, entity, ea, event); - } - - private void activateDirtyChecking(EntityAccess ea) { - Object e = ea.getEntity(); - if(e instanceof DirtyCheckable) { - ((DirtyCheckable) e).trackChanges(); - } - } - - public void afterUpdate(final PersistentEntity entity, final EntityAccess ea) { - afterUpdate(entity, ea, null); - } - - public void afterUpdate(final PersistentEntity entity, final EntityAccess ea, PostUpdateEvent event) { - activateDirtyChecking(ea); // reset dirty checking - invokeEvent(EVENT_AFTER_UPDATE, entity, ea, event); - } - - public void afterLoad(final PersistentEntity entity, final EntityAccess ea) { - afterLoad(entity, ea, null); - } - - public void afterLoad(final PersistentEntity entity, final EntityAccess ea, PostLoadEvent event) { - activateDirtyChecking(ea); - autowireBeanProperties(ea.getEntity()); - invokeEvent(EVENT_AFTER_LOAD, entity, ea, event); - } - - protected void autowireBeanProperties(final Object entity) { - datastore.getApplicationContext().getAutowireCapableBeanFactory().autowireBeanProperties( - entity, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false); - } - - /** - * {@inheritDoc} - * @see org.grails.datastore.mapping.model.MappingContext.Listener#persistentEntityAdded( - * org.grails.datastore.mapping.model.PersistentEntity) - */ - public void persistentEntityAdded(PersistentEntity entity) { - createEventCaches(entity); - } - - /** - * {@inheritDoc} - * @see org.springframework.context.event.SmartApplicationListener#supportsEventType( - * java.lang.Class) - */ - public boolean supportsEventType(Class eventType) { - return AbstractPersistenceEvent.class.isAssignableFrom(eventType); - } - - private boolean invokeEvent(String eventName, PersistentEntity entity, EntityAccess ea, ApplicationEvent event) { - final Map events = entityEvents.get(entity); - if (events == null) { - return true; - } - - final Method eventMethod = events.get(eventName); - if (eventMethod == null) { - return true; - } - - - final Object result; - if (eventMethod.getParameterTypes().length == 1) { - result = ReflectionUtils.invokeMethod(eventMethod, ea.getEntity(), event); - } - else { - result = ReflectionUtils.invokeMethod(eventMethod, ea.getEntity()); - } - - boolean booleanResult = (result instanceof Boolean) ? (Boolean)result : true; - if (booleanResult && REFRESH_EVENTS.contains(eventName)) { - ea.refresh(); - } - return booleanResult; - } - - private void createEventCaches(PersistentEntity entity) { - Class javaClass = entity.getJavaClass(); - final ConcurrentHashMap events = new ConcurrentHashMap(); - entityEvents.put(entity, events); - - findAndCacheEvent(EVENT_BEFORE_INSERT, javaClass, events); - findAndCacheEvent(EVENT_BEFORE_UPDATE, javaClass, events); - findAndCacheEvent(EVENT_BEFORE_DELETE, javaClass, events); - findAndCacheEvent(EVENT_BEFORE_LOAD, javaClass, events); - findAndCacheEvent(EVENT_AFTER_INSERT, javaClass, events); - findAndCacheEvent(EVENT_AFTER_UPDATE, javaClass, events); - findAndCacheEvent(EVENT_AFTER_DELETE, javaClass, events); - findAndCacheEvent(EVENT_AFTER_LOAD, javaClass, events); - } - - private void findAndCacheEvent(String event, Class javaClass, Map events) { - final Method method = ReflectionUtils.findMethod(javaClass, event); - if (method != null) { - events.put(event, method); - } - } -} 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 deleted file mode 100644 index cfa1b671c..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFindByFinder.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.grails.datastore.gorm.finders; - -import java.util.List; -import java.util.regex.Pattern; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.core.SessionCallback; -import org.grails.datastore.mapping.query.Query; - -public abstract class AbstractFindByFinder extends DynamicFinder { - public static final String OPERATOR_OR = "Or"; - public static final String OPERATOR_AND = "And"; - public static final String[] OPERATORS = { OPERATOR_AND, OPERATOR_OR }; - - protected AbstractFindByFinder(Pattern pattern, Datastore datastore) { - super(pattern, OPERATORS, datastore); - } - - @Override - protected Object doInvokeInternal(final DynamicFinderInvocation invocation) { - return execute(new SessionCallback() { - public Object doInSession(final Session session) { - return invokeQuery(buildQuery(invocation, session)); - } - }); - } - - protected Object invokeQuery(Query q) { - q.max(1); - - List results = q.list(); - if (results.isEmpty()) { - return null; - } - - return results.get(0); - } - - public boolean firstExpressionIsRequiredBoolean() { - return false; - } - - public Query buildQuery(DynamicFinderInvocation invocation, Session session) { - final Class clazz = invocation.getJavaClass(); - Query q = session.createQuery(clazz); - applyAdditionalCriteria(q, invocation.getCriteria()); - applyDetachedCriteria(q, invocation.getDetachedCriteria()); - configureQueryWithArguments(clazz, q, invocation.getArguments()); - - final String operatorInUse = invocation.getOperator(); - - if (operatorInUse != null && operatorInUse.equals(OPERATOR_OR)) { - if (firstExpressionIsRequiredBoolean()) { - MethodExpression expression = invocation.getExpressions().remove(0); - q.add(expression.createCriterion()); - } - - Query.Junction disjunction = q.disjunction(); - - for (MethodExpression expression : invocation.getExpressions()) { - disjunction.add(expression.createCriterion()); - } - } - else { - for (MethodExpression expression : invocation.getExpressions()) { - q.add(expression.createCriterion()); - } - } - return q; - } - -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFinder.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFinder.java deleted file mode 100644 index fb49d9735..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFinder.java +++ /dev/null @@ -1,56 +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.finders; - -import grails.gorm.CriteriaBuilder; -import groovy.lang.Closure; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.core.DatastoreUtils; -import org.grails.datastore.mapping.core.SessionCallback; -import org.grails.datastore.mapping.core.VoidSessionCallback; -import org.grails.datastore.mapping.query.Query; - -/** - * Abstract base class for finders. - * - * @author Burt Beckwith - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractFinder implements FinderMethod { - - protected Datastore datastore; - - public AbstractFinder(final Datastore datastore) { - this.datastore = datastore; - } - - protected T execute(final SessionCallback callback) { - return DatastoreUtils.execute(datastore, callback); - } - - protected void execute(final VoidSessionCallback callback) { - DatastoreUtils.execute(datastore, callback); - } - - protected void applyAdditionalCriteria(Query query, Closure additionalCriteria) { - if (additionalCriteria == null) { - return; - } - - CriteriaBuilder builder = new CriteriaBuilder(query.getEntity().getJavaClass(), query.getSession(), query); - builder.build(additionalCriteria); - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/CountByFinder.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/CountByFinder.java deleted file mode 100644 index 9b068c2e3..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/CountByFinder.java +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import java.util.regex.Pattern; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.core.SessionCallback; -import org.grails.datastore.mapping.query.Query; - -/** - * Supports counting objects. For example Book.countByTitle("The Stand") - */ -public class CountByFinder extends DynamicFinder implements QueryBuildingFinder { - - 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 }; - - public CountByFinder(final Datastore datastore) { - super(METHOD_PATTERN, OPERATORS, datastore); - } - - @Override - protected Object doInvokeInternal(final DynamicFinderInvocation invocation) { - return execute(new SessionCallback() { - public Object doInSession(final Session session) { - Query q = buildQuery(invocation, session); - return invokeQuery(q); - } - }); - } - - protected Object invokeQuery(Query q) { - return q.singleResult(); - } - - public Query buildQuery(DynamicFinderInvocation invocation, Session session) { - final Class clazz = invocation.getJavaClass(); - Query q = session.createQuery(clazz); - applyAdditionalCriteria(q, invocation.getCriteria()); - configureQueryWithArguments(clazz, q, invocation.getArguments()); - - String operatorInUse = invocation.getOperator(); - if (operatorInUse != null && operatorInUse.equals(OPERATOR_OR)) { - Query.Junction disjunction = q.disjunction(); - - for (MethodExpression expression : invocation.getExpressions()) { - disjunction.add(expression.createCriterion()); - } - } - else { - for (MethodExpression expression : invocation.getExpressions()) { - q.add( expression.createCriterion() ); - } - } - - q.projections().count(); - return q; - } -} 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 deleted file mode 100644 index 52e45d334..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinder.java +++ /dev/null @@ -1,462 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import grails.gorm.DetachedCriteria; -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.regex.Matcher; -import java.util.regex.Pattern; - -import javax.persistence.FetchType; - -import org.codehaus.groovy.runtime.DefaultGroovyMethods; -import org.grails.datastore.gorm.finders.MethodExpression.Between; -import org.grails.datastore.gorm.finders.MethodExpression.Equal; -import org.grails.datastore.gorm.finders.MethodExpression.GreaterThan; -import org.grails.datastore.gorm.finders.MethodExpression.GreaterThanEquals; -import org.grails.datastore.gorm.finders.MethodExpression.Ilike; -import org.grails.datastore.gorm.finders.MethodExpression.InList; -import org.grails.datastore.gorm.finders.MethodExpression.InRange; -import org.grails.datastore.gorm.finders.MethodExpression.IsEmpty; -import org.grails.datastore.gorm.finders.MethodExpression.IsNotEmpty; -import org.grails.datastore.gorm.finders.MethodExpression.IsNotNull; -import org.grails.datastore.gorm.finders.MethodExpression.IsNull; -import org.grails.datastore.gorm.finders.MethodExpression.LessThan; -import org.grails.datastore.gorm.finders.MethodExpression.LessThanEquals; -import org.grails.datastore.gorm.finders.MethodExpression.Like; -import org.grails.datastore.gorm.finders.MethodExpression.NotEqual; -import org.grails.datastore.gorm.finders.MethodExpression.Rlike; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.types.Basic; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.QueryArgumentsAware; -import org.springframework.core.convert.ConversionException; -import org.springframework.core.convert.ConversionService; -import org.springframework.util.StringUtils; -/** - * Abstract base class for dynamic finders. - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class DynamicFinder extends AbstractFinder implements QueryBuildingFinder { - - public static final String ARGUMENT_MAX = "max"; - public static final String ARGUMENT_OFFSET = "offset"; - public static final String ARGUMENT_ORDER = "order"; - public static final String ARGUMENT_SORT = "sort"; - public static final String ORDER_DESC = "desc"; - public static final String ORDER_ASC = "asc"; - public static final String ARGUMENT_FETCH = "fetch"; - public static final String ARGUMENT_IGNORE_CASE = "ignoreCase"; - public static final String ARGUMENT_CACHE = "cache"; - public static final String ARGUMENT_LOCK = "lock"; - - protected Pattern pattern; - private Pattern[] operatorPatterns; - private String[] operators; - - private static Pattern methodExpressinPattern; - private static final Object[] EMPTY_OBJECT_ARRAY = {}; - - private static final String NOT = "Not"; - private static final Map methodExpressions = new LinkedHashMap(); - - static { - // populate the default method expressions - try { - Class[] classes = { - Equal.class, NotEqual.class, InList.class, InRange.class, Between.class, Like.class, Ilike.class, Rlike.class, - GreaterThanEquals.class, LessThanEquals.class, GreaterThan.class, - LessThan.class, IsNull.class, IsNotNull.class, IsEmpty.class, - IsEmpty.class, IsNotEmpty.class }; - Class[] constructorParamTypes = { Class.class, String.class }; - for (Class c : classes) { - methodExpressions.put(c.getSimpleName(), c.getConstructor(constructorParamTypes)); - } - } catch (SecurityException e) { - // ignore - } catch (NoSuchMethodException e) { - // ignore - } - - resetMethodExpressionPattern(); - } - - static void resetMethodExpressionPattern() { - String expressionPattern = DefaultGroovyMethods.join(methodExpressions.keySet(), "|"); - methodExpressinPattern = Pattern.compile("\\p{Upper}[\\p{Lower}\\d]+(" + expressionPattern + ")"); - } - - protected DynamicFinder(final Pattern pattern, final String[] operators, final Datastore datastore) { - super(datastore); - this.pattern = pattern; - this.operators = operators; - this.operatorPatterns = new Pattern[operators.length]; - for (int i = 0; i < operators.length; i++) { - operatorPatterns[i] = Pattern.compile("(\\w+)(" + operators[i] + ")(\\p{Upper})(\\w+)"); - } - } - - /** - * Registers a new method expression. The Class must extends from the class {@link MethodExpression} and provide - * a constructor that accepts a Class parameter and a String parameter. - * - * @param methodExpression A class that extends from {@link MethodExpression} - */ - public static void registerNewMethodExpression(Class methodExpression) { - try { - methodExpressions.put(methodExpression.getSimpleName(), methodExpression.getConstructor( - Class.class, String.class)); - resetMethodExpressionPattern(); - } catch (SecurityException e) { - throw new IllegalArgumentException("Class [" + methodExpression + - "] does not provide a constructor that takes parameters of type Class and String: " + - e.getMessage(), e); - } catch (NoSuchMethodException e) { - throw new IllegalArgumentException("Class [" + methodExpression + - "] does not provide a constructor that takes parameters of type Class and String: " + - e.getMessage(), e); - } - } - - public void setPattern(String pattern) { - this.pattern = Pattern.compile(pattern); - } - - public boolean isMethodMatch(String methodName) { - return pattern.matcher(methodName.subSequence(0, methodName.length())).find(); - } - - public Object invoke(final Class clazz, String methodName, Closure additionalCriteria, Object[] arguments) { - DynamicFinderInvocation invocation = createFinderInvocation(clazz, methodName, additionalCriteria, arguments); - return doInvokeInternal(invocation); - } - - public Object invoke(final Class clazz, String methodName, DetachedCriteria detachedCriteria, Object[] arguments) { - DynamicFinderInvocation invocation = createFinderInvocation(clazz, methodName, null, arguments); - if (detachedCriteria != null ) { - invocation.setDetachedCriteria(detachedCriteria); - } - return doInvokeInternal(invocation); - } - - public DynamicFinderInvocation createFinderInvocation(Class clazz, String methodName, - Closure additionalCriteria, Object[] arguments) { - - List expressions = new ArrayList(); - if (arguments == null) arguments = EMPTY_OBJECT_ARRAY; - else { - Object[] tmp = new Object[arguments.length]; - System.arraycopy(arguments,0,tmp, 0, arguments.length); - arguments = tmp; - } - Matcher match = pattern.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; - } - MethodExpression booleanExpression = findMethodExpression(clazz, booleanProperty); - 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) { - MethodExpression currentExpression = findMethodExpression(clazz, queryParameter); - final int requiredArgs = currentExpression.getArgumentsRequired(); - // populate the arguments into the GrailsExpression from the argument list - Object[] currentArguments = new Object[requiredArgs]; - if ((argumentCursor + requiredArgs) > arguments.length) { - throw new MissingMethodException(methodName, clazz, arguments); - } - - for (int k = 0; k < requiredArgs; k++, argumentCursor++) { - currentArguments[k] = arguments[argumentCursor]; - } - currentExpression = getInitializedExpression(currentExpression, currentArguments); - PersistentEntity persistentEntity = datastore.getMappingContext().getPersistentEntity(clazz.getName()); - - try { - currentExpression.convertArguments(persistentEntity); - } catch (ConversionException e) { - throw new MissingMethodException(methodName, clazz, arguments); - } - - // add to list of expressions - totalRequiredArguments += currentExpression.argumentsRequired; - expressions.add(currentExpression); - } - break; - } - } - } - // otherwise there is only one expression - if (!containsOperator && querySequence != null) { - MethodExpression solo =findMethodExpression(clazz,querySequence); - - final int requiredArguments = solo.getArgumentsRequired(); - if (requiredArguments > arguments.length) { - throw new MissingMethodException(methodName,clazz,arguments); - } - - totalRequiredArguments += requiredArguments; - Object[] soloArgs = new Object[requiredArguments]; - System.arraycopy(arguments, 0, soloArgs, 0, requiredArguments); - solo = getInitializedExpression(solo, arguments); - PersistentEntity persistentEntity = datastore.getMappingContext().getPersistentEntity(clazz.getName()); - try { - solo.convertArguments(persistentEntity); - } catch (ConversionException e) { - if (!(persistentEntity.getPropertyByName(solo.propertyName) instanceof Basic)) { - 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]; - } - } - - return new DynamicFinderInvocation(clazz, methodName, remainingArguments, - expressions, additionalCriteria, operatorInUse); - } - - /** - * Initializes the arguments of the specified expression with the specified arguments. If the - * expression is an Equal expression and the argument is null then a new expression is created - * and returned of type IsNull. - * - * @param expression expression to initialize - * @param arguments arguments to the expression - * @return the initialized expression - */ - private MethodExpression getInitializedExpression(MethodExpression expression, Object[] arguments) { - if (expression instanceof Equal && arguments.length == 1 && arguments[0] == null) { - expression = new IsNull(expression.targetClass, expression.propertyName); - } else { - expression.setArguments(arguments); - } - return expression; - } - - protected MethodExpression findMethodExpression(Class clazz, String expression) { - MethodExpression me = null; - final Matcher matcher = methodExpressinPattern.matcher(expression); - - if (matcher.find()) { - Constructor constructor = methodExpressions.get(matcher.group(1)); - try { - me = (MethodExpression) constructor.newInstance(clazz, - calcPropertyName(expression, constructor.getDeclaringClass().getSimpleName())); - } catch (Exception e) { - // ignore - } - } - if (me == null) { - me = new Equal(clazz, calcPropertyName(expression, Equal.class.getSimpleName())); - } - - return me; - } - - private static String calcPropertyName(String queryParameter, String clause) { - String propName; - if (clause != null && !clause.equals(Equal.class.getSimpleName())) { - 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); - } - - if (!StringUtils.hasLength(propName)) { - throw new IllegalArgumentException("No property name specified in clause: " + clause); - } - - return propName.substring(0,1).toLowerCase(Locale.ENGLISH) + propName.substring(1); - } - - protected abstract Object doInvokeInternal(DynamicFinderInvocation invocation); - - public Object invoke(final Class clazz, String methodName, Object[] arguments) { - return invoke(clazz, methodName, (Closure)null, arguments); - } - - public static void populateArgumentsForCriteria(Class targetClass, Query q, Map argMap) { - if (argMap == null) { - return; - } - - Integer maxParam = null; - Integer offsetParam = null; - final ConversionService conversionService = q.getSession().getMappingContext().getConversionService(); - if (argMap.containsKey(ARGUMENT_MAX)) { - maxParam = conversionService.convert(argMap.get(ARGUMENT_MAX), Integer.class); - } - if (argMap.containsKey(ARGUMENT_OFFSET)) { - offsetParam = conversionService.convert(argMap.get(ARGUMENT_OFFSET), Integer.class); - } - String orderParam = (String)argMap.get(ARGUMENT_ORDER); - - Object fetchObj = argMap.get(ARGUMENT_FETCH); - if (fetchObj instanceof Map) { - Map fetch = (Map)fetchObj; - for (Object o : fetch.keySet()) { - String associationName = (String) o; - FetchType fetchType = getFetchMode(fetch.get(associationName)); - switch(fetchType) { - case LAZY: - q.select(associationName); - break; - case EAGER: - q.join(associationName); - } - } - } - - final String sort = (String)argMap.get(ARGUMENT_SORT); - final String order = ORDER_DESC.equalsIgnoreCase(orderParam) ? ORDER_DESC : ORDER_ASC; - final int max = maxParam == null ? -1 : maxParam; - final int offset = offsetParam == null ? -1 : offsetParam; - if (max > -1) { - q.max(max); - } - if (offset > -1) { - q.offset(offset); - } - if (sort != null) { - if (ORDER_DESC.equals(order)) { - q.order(Query.Order.desc(sort)); - } - else { - q.order(Query.Order.asc(sort)); - } - } - if (q instanceof QueryArgumentsAware) { - ((QueryArgumentsAware)q).setArguments(argMap); - } - } - - /** - * 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 FetchType getFetchMode(Object object) { - String name = object != null ? object.toString() : "default"; - if (name.equalsIgnoreCase(FetchType.EAGER.toString()) || name.equalsIgnoreCase("join")) { - return FetchType.EAGER; - } - if (name.equalsIgnoreCase(FetchType.LAZY.toString()) || name.equalsIgnoreCase("select")) { - return FetchType.LAZY; - } - return FetchType.LAZY; - } - - protected void configureQueryWithArguments(Class clazz, Query query, Object[] arguments) { - if (arguments.length == 0 || !(arguments[0] instanceof Map)) { - return; - } - - Map argMap = (Map)arguments[0]; - populateArgumentsForCriteria(clazz, query, argMap); - } - - public static void applyDetachedCriteria(Query q, DetachedCriteria detachedCriteria) { - if (detachedCriteria != null) { - List criteria = detachedCriteria.getCriteria(); - for (Query.Criterion criterion : criteria) { - q.add(criterion); - } - List projections = detachedCriteria.getProjections(); - for (Query.Projection projection : projections) { - q.projections().add(projection); - } - List orders = detachedCriteria.getOrders(); - for (Query.Order order : orders) { - q.order(order); - } - - Map fetchStrategies = detachedCriteria.getFetchStrategies(); - for (Map.Entry entry : fetchStrategies.entrySet()) { - switch(entry.getValue()) { - case EAGER: - q.join(entry.getKey()); break; - case LAZY: - q.select(entry.getKey()); - } - } - } - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinderInvocation.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinderInvocation.java deleted file mode 100644 index 95f487841..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinderInvocation.java +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import grails.gorm.DetachedCriteria; -import groovy.lang.Closure; - -import java.util.List; - -/** - * Value object used to construct all the information necessary to invoke a dynamic finder. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class DynamicFinderInvocation { - - private Class javaClass; - private String methodName; - private Object[] arguments; - private List expressions; - private Closure criteria; - private String operator; - private DetachedCriteria detachedCriteria; - - public DynamicFinderInvocation(Class javaClass, String methodName, Object[] arguments, - List expressions, Closure criteria, String operator) { - this.javaClass = javaClass; - this.methodName = methodName; - this.arguments = arguments; - this.expressions = expressions; - this.criteria = criteria; - this.operator = operator; - } - - public Class getJavaClass() { - return javaClass; - } - - public String getMethodName() { - return methodName; - } - - public Object[] getArguments() { - return arguments; - } - - public List getExpressions() { - return expressions; - } - - public Closure getCriteria() { - return criteria; - } - - public String getOperator() { - return operator; - } - - public DetachedCriteria getDetachedCriteria() { - return detachedCriteria; - } - - public void setDetachedCriteria(DetachedCriteria detachedCriteria) { - this.detachedCriteria = detachedCriteria; - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByBooleanFinder.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByBooleanFinder.java deleted file mode 100644 index 5e009f70f..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByBooleanFinder.java +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import org.grails.datastore.mapping.core.Datastore; - -/** - * The "findAllBy*" 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 - * @author Graeme Rocher - */ -public class FindAllByBooleanFinder extends FindAllByFinder{ - private static final String METHOD_PATTERN = "(findAll)((\\w+)(By)([A-Z]\\w*)|(\\w+))"; - public FindAllByBooleanFinder(Datastore datastore) { - super(datastore); - setPattern(METHOD_PATTERN); - } - - @Override - public boolean firstExpressionIsRequiredBoolean() { - return true; - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByFinder.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByFinder.java deleted file mode 100644 index afd3e54de..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByFinder.java +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import java.util.regex.Pattern; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.core.SessionCallback; -import org.grails.datastore.mapping.query.Query; - -/** - * Finder used to return multiple results. Eg. Book.findAllBy..(..) - */ -public class FindAllByFinder extends DynamicFinder { - - 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 }; - - public FindAllByFinder(final Datastore datastore) { - super(Pattern.compile(METHOD_PATTERN), OPERATORS, datastore); - } - - @Override - protected Object doInvokeInternal(final DynamicFinderInvocation invocation) { - return execute(new SessionCallback() { - public Object doInSession(final Session session) { - Query q = buildQuery(invocation, session); - return invokeQuery(q); - } - }); - } - - protected Object invokeQuery(Query q) { - return q.list(); - } - - public boolean firstExpressionIsRequiredBoolean() { - return false; - } - - public Query buildQuery(DynamicFinderInvocation invocation, Session session) { - final Class clazz = invocation.getJavaClass(); - Query q = session.createQuery(clazz); - applyAdditionalCriteria(q, invocation.getCriteria()); - applyDetachedCriteria(q, invocation.getDetachedCriteria()); - configureQueryWithArguments(clazz, q, invocation.getArguments()); - - final String operatorInUse = invocation.getOperator(); - if (operatorInUse != null && operatorInUse.equals(OPERATOR_OR)) { - if (firstExpressionIsRequiredBoolean()) { - MethodExpression expression = invocation.getExpressions().remove(0); - q.add(expression.createCriterion()); - } - Query.Junction disjunction = q.disjunction(); - - for (MethodExpression expression : invocation.getExpressions()) { - disjunction.add(expression.createCriterion()); - } - } - else { - for (MethodExpression expression : invocation.getExpressions()) { - q.add( expression.createCriterion() ); - } - } - q.projections().distinct(); - return q; - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindByBooleanFinder.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindByBooleanFinder.java deleted file mode 100644 index 14bada040..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindByBooleanFinder.java +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import org.grails.datastore.mapping.core.Datastore; - -/** - *

    The "findBy*" 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 Graeme Rocher - * @author Jeff Brown - */ -public class FindByBooleanFinder extends FindByFinder{ - private static final String METHOD_PATTERN = "(find)((\\w+)(By)([A-Z]\\w*)|(\\w++))"; - - public FindByBooleanFinder(Datastore datastore) { - super(datastore); - setPattern(METHOD_PATTERN); - } - - @Override - public boolean firstExpressionIsRequiredBoolean() { - return true; - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindByFinder.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindByFinder.java deleted file mode 100644 index bd6f542b9..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindByFinder.java +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import java.util.regex.Pattern; - -import org.grails.datastore.mapping.core.Datastore; - -/** - * Finder used to return a single result - */ -public class FindByFinder extends AbstractFindByFinder { - - private static final String METHOD_PATTERN = "(findBy)([A-Z]\\w*)"; - - public FindByFinder(final Datastore datastore) { - super(Pattern.compile(METHOD_PATTERN), datastore); - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindOrCreateByFinder.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindOrCreateByFinder.java deleted file mode 100644 index 5eec92f7d..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindOrCreateByFinder.java +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; -import groovy.lang.MissingMethodException; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.grails.datastore.mapping.core.Datastore; -import org.springframework.core.convert.ConversionException; - -/** - * Finder used to return a single result - */ -public class FindOrCreateByFinder extends AbstractFindByFinder { - - private static final String METHOD_PATTERN = "(findOrCreateBy)([A-Z]\\w*)"; - - public FindOrCreateByFinder(final String methodPattern, final Datastore datastore) { - super(Pattern.compile(methodPattern), datastore); - } - - public FindOrCreateByFinder(final Datastore datastore) { - this(METHOD_PATTERN, datastore); - } - - @Override - @SuppressWarnings({"rawtypes", "unchecked"}) - protected Object doInvokeInternal(final DynamicFinderInvocation invocation) { - - if (OPERATOR_OR.equals(invocation.getOperator())) { - throw new MissingMethodException(invocation.getMethodName(), invocation.getJavaClass(), invocation.getArguments()); - } - - Object result = null; - try { - result = super.doInvokeInternal(invocation); - } catch (ConversionException e) { // TODO this is not the right place to deal with this... - throw new MissingMethodException(invocation.getMethodName(), invocation.getJavaClass(), invocation.getArguments()); - } - if (result == null) { - Map m = new HashMap(); - List expressions = invocation.getExpressions(); - for (MethodExpression me : expressions) { - if (!(me instanceof MethodExpression.Equal)) { - throw new MissingMethodException(invocation.getMethodName(), invocation.getJavaClass(), invocation.getArguments()); - } - String propertyName = me.propertyName; - Object[] arguments = me.getArguments(); - m.put(propertyName, arguments[0]); - } - MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(invocation.getJavaClass()); - 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/src/main/groovy/org/grails/datastore/gorm/finders/FindOrSaveByFinder.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindOrSaveByFinder.java deleted file mode 100644 index e50a157a3..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FindOrSaveByFinder.java +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import groovy.lang.GroovySystem; -import groovy.lang.MetaClass; -import groovy.lang.MissingMethodException; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.grails.datastore.mapping.core.Datastore; - -public class FindOrSaveByFinder extends FindOrCreateByFinder { - - private static final String METHOD_PATTERN = "(findOrSaveBy)([A-Z]\\w*)"; - - public FindOrSaveByFinder(final Datastore datastore) { - super(METHOD_PATTERN, datastore); - } - - @Override - @SuppressWarnings({"rawtypes", "unchecked"}) - protected Object doInvokeInternal(final DynamicFinderInvocation invocation) { - if (OPERATOR_OR.equals(invocation.getOperator())) { - throw new MissingMethodException(invocation.getMethodName(), invocation.getJavaClass(), invocation.getArguments()); - } - - Object result = super.doInvokeInternal(invocation); - if (result == null) { - Map m = new HashMap(); - List expressions = invocation.getExpressions(); - for (MethodExpression me : expressions) { - if (!(me instanceof MethodExpression.Equal)) { - throw new MissingMethodException(invocation.getMethodName(), invocation.getJavaClass(), invocation.getArguments()); - } - String propertyName = me.propertyName; - Object[] arguments = me.getArguments(); - m.put(propertyName, arguments[0]); - } - MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(invocation.getJavaClass()); - result = metaClass.invokeConstructor(new Object[]{m}); - } - return result; - } - - @Override - protected boolean shouldSaveOnCreate() { - return true; - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FinderMethod.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FinderMethod.java deleted file mode 100644 index 0aeaf4ee4..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/FinderMethod.java +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import groovy.lang.Closure; - -/** - * Implementation of dynamic finders. - */ -@SuppressWarnings("rawtypes") -public interface FinderMethod { - - /** - * @param pattern A regular expression - */ - void setPattern(String pattern); - - /** - * Invokes the method - * @param clazz The class - * @param methodName The method name - * @param arguments The arguments - * @return The return value - */ - Object invoke(Class clazz, String methodName, Object[] arguments); - - /** - * Invokes the method - * @param clazz The class - * @param methodName The method name - * @param additionalCriteria additional criteria closure - * @param arguments The arguments - * @return The return value - */ - Object invoke(Class clazz, String methodName, Closure additionalCriteria, Object[] arguments); - - /** - * Whether the given method name matches this finder - * @param methodName The method name - * @return true if it does - */ - boolean isMethodMatch(String methodName); -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/ListOrderByFinder.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/ListOrderByFinder.java deleted file mode 100644 index 05088e94e..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/ListOrderByFinder.java +++ /dev/null @@ -1,87 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import groovy.lang.Closure; - -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.core.SessionCallback; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.reflect.NameUtils; - -/** - * The "listOrderBy*" static persistent method. Allows ordered listing of instances based on their properties. - * - * eg. - * Account.listOrderByHolder(); - * Account.listOrderByHolder(max); // max results - * - * @author Graeme Rocher - */ -public class ListOrderByFinder extends AbstractFinder { - private static final Pattern METHOD_PATTERN = Pattern.compile("(listOrderBy)(\\w+)"); - private Pattern pattern = METHOD_PATTERN; - - public ListOrderByFinder(Datastore datastore) { - super(datastore); - } - - public void setPattern(String pattern) { - this.pattern = Pattern.compile(pattern); - } - - @SuppressWarnings("rawtypes") - public Object invoke(final Class clazz, final String methodName, final Object[] arguments) { - return invoke(clazz, methodName, null, arguments); - } - - @SuppressWarnings("rawtypes") - public Object invoke(final Class clazz, final String methodName, final Closure additionalCriteria, final Object[] arguments) { - - Matcher match = pattern.matcher(methodName); - match.find(); - - String nameInSignature = match.group(2); - final String propertyName = NameUtils.decapitalize(nameInSignature); - - return execute(new SessionCallback() { - public Object doInSession(final Session session) { - Query q = session.createQuery(clazz); - applyAdditionalCriteria(q, additionalCriteria); - if (arguments.length > 0 && (arguments[0] instanceof Map)) { - DynamicFinder.populateArgumentsForCriteria(clazz, q, (Map) arguments[0]); - } - - q.order(Query.Order.asc(propertyName)); - q.projections().distinct(); - return invokeQuery(q); - } - }); - } - - protected Object invokeQuery(Query q) { - return q.list(); - } - - public boolean isMethodMatch(String methodName) { - return pattern.matcher(methodName.subSequence(0, methodName.length())).find(); - } - -} 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 deleted file mode 100644 index af84af028..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/MethodExpression.java +++ /dev/null @@ -1,336 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import groovy.lang.Range; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.Query.Criterion; -import org.grails.datastore.mapping.query.Restrictions; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.TypeDescriptor; -import org.springframework.util.Assert; - -/** - * Method expression used to evaluate a dynamic finder. - */ -public abstract class MethodExpression { - - protected String propertyName; - protected Object[] arguments; - protected int argumentsRequired = 1; - protected Class targetClass; - - public abstract Query.Criterion createCriterion(); - - protected MethodExpression(Class targetClass, String propertyName) { - this.propertyName = propertyName; - this.targetClass = targetClass; - } - - public int getArgumentsRequired() { - return argumentsRequired; - } - - public void convertArguments(PersistentEntity persistentEntity) { - ConversionService conversionService = persistentEntity - .getMappingContext().getConversionService(); - PersistentProperty prop = persistentEntity - .getPropertyByName(propertyName); - if (prop == null) { - if (propertyName.equals(persistentEntity.getIdentity().getName())) { - prop = persistentEntity.getIdentity(); - } - } - if (prop != null && arguments != null && argumentsRequired > 0) { - Class type = prop.getType(); - for (int i = 0; i < argumentsRequired; i++) { - Object arg = arguments[i]; - if (arg != null && !type.isAssignableFrom(arg.getClass())) { - // Add special handling for GStringImpl - if(arg instanceof CharSequence && arg.getClass() != String.class) { - arg = arg.toString(); - arguments[i] = arg; - if(type.isAssignableFrom(arg.getClass())) { - break; - } - } - TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(type); - if ((typeDescriptor.isArray() || typeDescriptor.isCollection()) && (typeDescriptor.getElementTypeDescriptor() == null || typeDescriptor.getElementTypeDescriptor().getType().isAssignableFrom(arg.getClass()))) { - // skip converting argument to collection/array type if argument is correct instance of element type - break; - } - arguments[i] = conversionService.convert(arg, type); - } - } - } - } - - public void setArguments(Object[] arguments) { - this.arguments = arguments; - } - - public Object[] getArguments() { - return Arrays.copyOf(arguments, arguments.length); - } - - public static class GreaterThan extends MethodExpression { - public GreaterThan(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Query.Criterion createCriterion() { - return Restrictions.gt(propertyName, arguments[0]); - } - } - - public static class GreaterThanEquals extends MethodExpression { - public GreaterThanEquals(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Query.Criterion createCriterion() { - return Restrictions.gte(propertyName, arguments[0]); - } - } - - public static class LessThan extends MethodExpression { - public LessThan(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Query.Criterion createCriterion() { - return Restrictions.lt(propertyName, arguments[0]); - } - } - - public static class LessThanEquals extends MethodExpression { - public LessThanEquals(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Query.Criterion createCriterion() { - return Restrictions.lte(propertyName, arguments[0]); - } - } - - public static class Like extends MethodExpression { - public Like(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Query.Criterion createCriterion() { - return Restrictions.like(propertyName, arguments[0].toString()); - } - } - - public static class Ilike extends MethodExpression { - public Ilike(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Query.Criterion createCriterion() { - return Restrictions.ilike(propertyName, arguments[0].toString()); - } - } - - public static class Rlike extends MethodExpression { - public Rlike(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Query.Criterion createCriterion() { - return Restrictions.rlike(propertyName, arguments[0].toString()); - } - } - - public static class InList extends MethodExpression { - public InList(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Query.Criterion createCriterion() { - return Restrictions.in(propertyName, (Collection) arguments[0]); - } - - @Override - public void setArguments(Object[] arguments) { - Assert.isTrue(arguments.length > 0 && arguments[0] instanceof Collection, - "Only a collection of elements is supported in an 'in' query"); - - super.setArguments(arguments); - } - - @Override - public void convertArguments(PersistentEntity persistentEntity) { - ConversionService conversionService = persistentEntity - .getMappingContext().getConversionService(); - PersistentProperty prop = persistentEntity - .getPropertyByName(propertyName); - if (prop == null) { - if (propertyName.equals(persistentEntity.getIdentity().getName())) { - prop = persistentEntity.getIdentity(); - } - } - if (prop != null) { - Class type = prop.getType(); - Collection collection = (Collection) arguments[0]; - List converted = new ArrayList(collection.size()); - for (Object o : collection) { - if (o != null && !type.isAssignableFrom(o.getClass())) { - o = conversionService.convert(o, type); - } - converted.add(o); - } - arguments[0] = converted; - } - } - } - - public static class Between extends MethodExpression { - public Between(Class targetClass, String propertyName) { - super(targetClass, propertyName); - argumentsRequired = 2; - } - - @Override - public Query.Criterion createCriterion() { - return Restrictions.between(propertyName, arguments[0], arguments[1]); - } - - @Override - public void setArguments(Object[] arguments) { - Assert.isTrue(arguments.length > 1, "A 'between' query requires at least two arguments"); - Assert.isTrue(arguments[0] instanceof Comparable && arguments[1] instanceof Comparable, - "A 'between' query requires that both arguments are comparable"); - - super.setArguments(arguments); - } - } - - public static class InRange extends MethodExpression { - public InRange(Class targetClass, String propertyName) { - super(targetClass, propertyName); - argumentsRequired = 1; - } - - @Override - public Query.Criterion createCriterion() { - Range range = (Range) arguments[0]; - return Restrictions.between(propertyName, range.getFrom(), range.getTo()); - } - - @Override - public void convertArguments(PersistentEntity persistentEntity) { - // setArguments already made sure arguments[0] is a Range... - } - - @Override - public void setArguments(Object[] arguments) { - Assert.isTrue(arguments.length == 1, "An 'inRange' query requires exactly 1 argument"); - Assert.isTrue(arguments[0] instanceof Range, - "An 'inRange' query requires a Range argument"); - - super.setArguments(arguments); - } - } - - public static class IsNull extends MethodExpression { - public IsNull(Class targetClass, String propertyName) { - super(targetClass, propertyName); - argumentsRequired = 0; - } - - @Override - public Criterion createCriterion() { - return Restrictions.isNull(propertyName); - } - } - - public static class IsNotNull extends MethodExpression { - - public IsNotNull(Class targetClass, String propertyName) { - super(targetClass, propertyName); - argumentsRequired = 0; - } - - @Override - public Criterion createCriterion() { - return Restrictions.isNotNull(propertyName); - } - } - - public static class IsEmpty extends MethodExpression { - public IsEmpty(Class targetClass, String propertyName) { - super(targetClass, propertyName); - argumentsRequired = 0; - } - - @Override - public Criterion createCriterion() { - return Restrictions.isEmpty(propertyName); - } - } - - public static class IsNotEmpty extends MethodExpression { - - public IsNotEmpty(Class targetClass, String propertyName) { - super(targetClass, propertyName); - argumentsRequired = 0; - } - - @Override - public Criterion createCriterion() { - return Restrictions.isNotEmpty(propertyName); - } - } - - public static class Equal extends MethodExpression { - public Equal(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Query.Criterion createCriterion() { - return Restrictions.eq(propertyName, arguments[0]); - } - } - - public static class NotEqual extends MethodExpression { - public NotEqual(Class targetClass, String propertyName) { - super(targetClass, propertyName); - } - - @Override - public Query.Criterion createCriterion() { - return Restrictions.ne(propertyName, arguments[0]); - } - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/QueryBuildingFinder.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/QueryBuildingFinder.java deleted file mode 100644 index 892518979..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/finders/QueryBuildingFinder.java +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2010 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.finders; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.query.Query; - -/** - * Implemented by finders that build queries. - * - * @author Graeme Rocher - * @since 1.0 - */ -public interface QueryBuildingFinder { - - /** - * Build a query from an invocation - * @param invocation The invocation - * @param session an active session - * @return The query - */ - Query buildQuery(DynamicFinderInvocation invocation, Session session); -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/internal/InstanceMethodInvokingClosure.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/internal/InstanceMethodInvokingClosure.groovy deleted file mode 100644 index 15144cb38..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/internal/InstanceMethodInvokingClosure.groovy +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (C) 2013 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.internal - -/** - * Not public API. Used by GormEnhancer - */ -@SuppressWarnings("rawtypes") -class InstanceMethodInvokingClosure extends Closure { - private String methodName - private apiDelegate - private Class[] parameterTypes - - InstanceMethodInvokingClosure(apiDelegate, String methodName, Class[] parameterTypes) { - super(apiDelegate, apiDelegate) - this.apiDelegate = apiDelegate - this.methodName = methodName - this.parameterTypes = parameterTypes - } - - @Override - Object call(Object[] args) { - apiDelegate."$methodName"(delegate, *args) - } - - Object doCall(Object[] args) { - apiDelegate."$methodName"(delegate, *args) - } - - @Override - Class[] getParameterTypes() { parameterTypes } -} \ No newline at end of file diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/internal/StaticMethodInvokingClosure.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/internal/StaticMethodInvokingClosure.groovy deleted file mode 100644 index 874762aa5..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/internal/StaticMethodInvokingClosure.groovy +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2013 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.internal - -/** - * Not public API. Used by GormEnhancer - */ -@SuppressWarnings("rawtypes") -class StaticMethodInvokingClosure extends Closure { - - private String methodName - private Object apiDelegate - private Class[] parameterTypes - - StaticMethodInvokingClosure(apiDelegate, String methodName, Class[] parameterTypes) { - super(apiDelegate, apiDelegate) - this.apiDelegate = apiDelegate - this.methodName = methodName - this.parameterTypes = parameterTypes - } - - @Override - Object call(Object[] args) { - apiDelegate."$methodName"(*args) - } - - Object doCall(Object[] args) { - apiDelegate."$methodName"(*args) - } - - @Override - Class[] getParameterTypes() { parameterTypes } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/proxy/GroovyProxyFactory.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/proxy/GroovyProxyFactory.groovy deleted file mode 100644 index daeaf9ffb..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/proxy/GroovyProxyFactory.groovy +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (C) 2010 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.proxy - -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.engine.EntityPersister -import org.grails.datastore.mapping.proxy.ProxyFactory -import org.springframework.dao.DataIntegrityViolationException - -/** - * Implements the proxy interface and creates a Groovy proxy by passing the need for javassist style proxies - * and all the problems they bring. - * - * @author Graeme Rocher - */ -@SuppressWarnings("unchecked") -class GroovyProxyFactory implements ProxyFactory { - - boolean isProxy(Object object) { - object != null && object.metaClass.getMetaMethod("isProxy", null) != null - } - - Serializable getIdentifier(Object obj) { - return obj.getId() - } - - def createProxy(Session session, Class type, Serializable key) { - EntityPersister persister = session.getPersister(type) - - def proxy = type.newInstance() - persister.setObjectIdentifier(proxy, key) - def target = null - proxy.metaClass.isProxy = {-> true} - proxy.metaClass.invokeMethod = { String name, args -> - switch(name) { - case "getId": - return key - case 'initialize': - if (target == null) target = session.retrieve(type, key) - return target - case 'isInitialized': - return target != null - case 'getTarget': - if (target == null) target = session.retrieve(type, key) - return target - default: - if (target == null) target = session.retrieve(type, key) - return target."$name"(*args) - } - } - - proxy.metaClass.getProperty = { String name -> - switch(name) { - case 'id': - return key - case 'initialized': - return target != null - case 'target': - if (target == null) target = session.retrieve(type, key) - return target - default: - if (target == null) target = session.retrieve(type, key) - - if (target == null) { - throw new DataIntegrityViolationException("Error loading association [$key] of type [$type]. Associated instance no longer exists.") - } - return target[name] - } - } - - proxy.metaClass.setProperty = { String name, value -> - if (target == null) target = session.retrieve(type, key) - if (target == null) { - throw new DataIntegrityViolationException("Error loading association [$key] of type [$type]. Associated instance no longer exists.") - } - - target[name] = value - } - return proxy - } - - @Override - boolean isInitialized(Object object) { - if (isProxy(object)) { - return object.initialized - } - return true - } - - @Override - Object unwrap(Object object) { - if (isProxy(object)) { - return object.target - } - return object - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/GormOperations.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/GormOperations.groovy deleted file mode 100644 index 03f3c925f..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/GormOperations.groovy +++ /dev/null @@ -1,153 +0,0 @@ -/* Copyright (C) 2013 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.query - -/** - * Interface defining all typical GORM operations on class - * - * @author Graeme Rocher - * @since 2.0 - */ -interface GormOperations { - - /** - * @return The class these operations apply to - */ - T getPersistentClass() - - /** - * Synonym for #get - */ - T find(Map args , Closure additionalCriteria) - - /** - * Synonym for #get - */ - T find(Map args) - - /** - * Synonym for #get - */ - T find() - - /** - * Returns a single result matching the criterion contained within this DetachedCriteria instance - * - * @param args The arguments - * @param additionalCriteria Additional criteria - * @return A single entity - */ - T get(Map args, Closure additionalCriteria) - - /** - * Returns a single result matching the criterion contained within this DetachedCriteria instance - * @param args The arguments - * @return A single entity - */ - T get(Map args) - - /** - * Returns a single result matching the criterion contained within this DetachedCriteria instance - * - * @return A single entity - */ - T get() - - /** - * Lists all records matching the criterion contained within this DetachedCriteria instance - * - * @return A list of matching instances - */ - List list() - - /** - * Lists all records matching the criterion contained within this DetachedCriteria instance - * - * @param args The arguments - * @return A list of matching instances - */ - List list(Map args) - - /** - * Lists all records matching the criterion contained within this DetachedCriteria instance - * - * @param args The arguments - * @param additionalCriteria The additional criteria - * @return A list of matching instances - */ - List list(Map args , Closure additionalCriteria) - - /** - * Counts the number of records returned by the query - * - * @return The count - */ - Number count() - - /** - * Counts the number of records returned by the query - * - * @param args The arguments - * @return The count - */ - Number count(Map args) - - /** - * Counts the number of records returned by the query - * - * @param args The arguments - * @param additionalCriteria Any additional criteria - * @return The count - */ - Number count(Map args, Closure additionalCriteria) - - /** - * Deletes all entities matching this criteria - * - * @return The total number deleted - */ - Number deleteAll() - - /** - * Updates all entities matching this criteria - * - * @return The total number deleted - */ - Number updateAll(Map properties) - - /** - * Method missing handler for dynamic finders - * - * @param methodName The method name - * @param args The arguments - * @return The return value - */ - def methodMissing(String methodName, args) - - /** - * Returns whether the record exists - * - * @param additionalCriteria The additional criteria - * @return Whether the record exists - */ - boolean exists(Closure additionalCriteria) - - /** - * Returns whether the record exists - * - * @return Whether the record exists - */ - boolean exists() -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/NamedQueriesBuilder.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/NamedQueriesBuilder.groovy deleted file mode 100644 index 9da6b5feb..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/NamedQueriesBuilder.groovy +++ /dev/null @@ -1,234 +0,0 @@ -/* Copyright (C) 2010 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.query - -import java.lang.reflect.Modifier - -import org.grails.datastore.gorm.finders.DynamicFinder -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.model.PersistentEntity - -/** - * Handles creation of named queries - * - * @author Graeme Rocher - * @author Jeff Brown - */ -class NamedQueriesBuilder { - - PersistentEntity entity - List finders - boolean initialized = false - - NamedQueriesBuilder(PersistentEntity entity, List finders) { - this.entity = entity - this.finders = finders - } - - def evaluate(Closure namedQueriesClosure) { - def closure = namedQueriesClosure.clone() - closure.resolveStrategy = Closure.DELEGATE_ONLY - closure.delegate = this - closure.call() - initialized = true - } - - private handleMethodMissing = {String name, args -> - def propertyName = name[0].toUpperCase() + name[1..-1] - def javaClass = entity.javaClass - javaClass.metaClass.static."get${propertyName}" = {-> - // creating a new proxy each time because the proxy class has - // some state that cannot be shared across requests (namedCriteriaParams) - new NamedCriteriaProxy(criteriaClosure: args[0], entity: entity, finders: finders) - } - } - - def methodMissing(String name, args) { - if (args && args[0] instanceof Closure && !initialized) { - return handleMethodMissing(name, args) - } - throw new MissingMethodException(name, NamedQueriesBuilder, args) - } -} - -class NamedCriteriaProxy { - - Closure criteriaClosure - PersistentEntity entity - List finders - private namedCriteriaParams - private previousInChain - private queryBuilder - - private invokeCriteriaClosure(additionalCriteriaClosure = null) { - def crit = getPreparedCriteriaClosure(additionalCriteriaClosure) - crit() - } - - private listInternal(Object[] params, Closure additionalCriteriaClosure, Boolean isDistinct) { - def conversionService = entity.mappingContext.conversionService - def listClosure = { - queryBuilder = delegate - invokeCriteriaClosure(additionalCriteriaClosure) - def paramsMap - if (params && params[-1] instanceof Map) { - paramsMap = params[-1] - } - if (paramsMap?.max) { - maxResults conversionService.convert(paramsMap.max, Integer) - } - if (paramsMap?.offset) { - firstResult conversionService.convert(paramsMap.offset, Integer) - } - if (paramsMap) { - DynamicFinder.populateArgumentsForCriteria(entity.javaClass, queryBuilder.query, paramsMap) - } - } - entity.javaClass.withCriteria(listClosure) - } - - def list(Object[] params, Closure additionalCriteriaClosure = null) { - listInternal params, additionalCriteriaClosure, false - } - - def listDistinct(Object[] params, Closure additionalCriteriaClosure = null) { - listInternal params, additionalCriteriaClosure, true - } - - def call(Object[] params) { - if (params && params[-1] instanceof Closure) { - def additionalCriteriaClosure = params[-1] - params = params.length > 1 ? params[0..-2] : [:] - if (params) { - if (params[-1] instanceof Map) { - if (params.length > 1) { - namedCriteriaParams = params[0..-2] as Object[] - } - } else { - namedCriteriaParams = params - } - } - list(params, additionalCriteriaClosure) - } - else { - namedCriteriaParams = params - this - } - } - - def get(id) { - id = entity.mappingContext.conversionService.convert(id, entity.identity.type) - def getClosure = { - queryBuilder = delegate - invokeCriteriaClosure() - eq 'id', id - uniqueResult = true - } - entity.javaClass.createCriteria().get(getClosure) - } - - def count(Closure additionalCriteriaClosure = null) { - def countClosure = { - queryBuilder = delegate - invokeCriteriaClosure(additionalCriteriaClosure) - } - entity.javaClass.createCriteria().count(countClosure) - } - - def findWhere(params) { - findAllWhere(params, true) - } - - def findAllWhere(Map params, Boolean uniq = false) { - def queryClosure = { - queryBuilder = delegate - invokeCriteriaClosure() - params.each {key, val -> - eq key, val - } - if (uniq) { - maxResults 1 - uniqueResult = true - } - } - entity.javaClass.withCriteria(queryClosure) - } - - def propertyMissing(String propertyName) { - def javaClass = entity.javaClass - if (javaClass.metaClass.getMetaProperty(propertyName)) { - def nextInChain = javaClass.metaClass.getMetaProperty(propertyName).getProperty(javaClass) - nextInChain.previousInChain = this - return nextInChain - } - throw new MissingPropertyException(propertyName, NamedCriteriaProxy) - } - - void propertyMissing(String propName, val) { - queryBuilder?."${propName}" = val - } - - def methodMissing(String methodName, args) { - - def javaClass = entity.javaClass - FinderMethod method = finders.find { FinderMethod f -> f.isMethodMatch(methodName) } - - if (method) { - def preparedClosure = getPreparedCriteriaClosure() - return method.invoke(javaClass, methodName, preparedClosure, args) - } - - if (!queryBuilder && javaClass.metaClass.getMetaProperty(methodName)) { - def nextInChain = javaClass.metaClass.getMetaProperty(methodName).getProperty(entity) - nextInChain.previousInChain = this - return nextInChain(args) - } - - def metaProperty = javaClass.metaClass.getMetaProperty(methodName) - if (metaProperty && Modifier.isStatic(metaProperty.modifiers)) { - def staticProperty = metaProperty.getProperty(javaClass) - if (staticProperty instanceof NamedCriteriaProxy) { - def nestedCriteria = staticProperty.criteriaClosure.clone() - nestedCriteria.delegate = queryBuilder - return nestedCriteria(*args) - } - } - queryBuilder."${methodName}"(*args) - } - - private getPreparedCriteriaClosure(additionalCriteriaClosure = null) { - Closure closureClone = criteriaClosure.clone() - closureClone.resolveStrategy = Closure.DELEGATE_FIRST - if (namedCriteriaParams) { - closureClone = closureClone.curry(*namedCriteriaParams) - } - def c = { - closureClone.delegate = delegate - if (previousInChain) { - def previousClosure = previousInChain.getPreparedCriteriaClosure() - previousClosure.delegate = delegate - previousClosure() - } - closureClone() - if (additionalCriteriaClosure) { - additionalCriteriaClosure = additionalCriteriaClosure.clone() - additionalCriteriaClosure.delegate = delegate - additionalCriteriaClosure() - } - } - c - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/criteria/DetachedAssociationCriteria.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/criteria/DetachedAssociationCriteria.groovy deleted file mode 100644 index 50c4dc4a5..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/criteria/DetachedAssociationCriteria.groovy +++ /dev/null @@ -1,38 +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.query.criteria - -import grails.gorm.DetachedCriteria - -import org.grails.datastore.mapping.model.types.Association -import org.grails.datastore.mapping.query.Query.Criterion -import org.grails.datastore.mapping.query.api.AssociationCriteria - -/** - * Criterion related to an association - * - * @author Graeme Rocher - * @since 1.0 - */ -class DetachedAssociationCriteria extends DetachedCriteria implements Criterion, AssociationCriteria { - - Association association - - DetachedAssociationCriteria(Class targetClass, Association association) { - super(targetClass) - this.association = association - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/ApplyDetachedCriteriaTransform.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/ApplyDetachedCriteriaTransform.java deleted file mode 100644 index d57e5f755..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/ApplyDetachedCriteriaTransform.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.grails.datastore.gorm.query.transform; - -import org.codehaus.groovy.transform.GroovyASTTransformationClass; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Used only for testing - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE}) -@GroovyASTTransformationClass("org.grails.datastore.gorm.query.transform.DetachedCriteriaASTTransformation") -public @interface ApplyDetachedCriteriaTransform { -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaASTTransformation.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaASTTransformation.java deleted file mode 100644 index 0824e7687..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaASTTransformation.java +++ /dev/null @@ -1,48 +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.query.transform; - -import org.codehaus.groovy.ast.ASTNode; -import org.codehaus.groovy.ast.AnnotatedNode; -import org.codehaus.groovy.ast.ClassNode; -import org.codehaus.groovy.control.CompilePhase; -import org.codehaus.groovy.control.SourceUnit; -import org.codehaus.groovy.transform.ASTTransformation; -import org.codehaus.groovy.transform.GroovyASTTransformation; - -/** - * Transforms regular Groovy-style finders into detached criteria - */ -@GroovyASTTransformation(phase= CompilePhase.CANONICALIZATION) -public class DetachedCriteriaASTTransformation implements ASTTransformation{ - - /** - * The method is invoked when an AST Transformation is active. For local transformations, it is invoked once - * each time the local annotation is encountered. For global transformations, it is invoked once for every source - * unit, which is typically a source file. - * - * @param nodes The ASTnodes when the call was triggered. Element 0 is the AnnotationNode that triggered this - * annotation to be activated. Element 1 is the AnnotatedNode decorated, such as a MethodNode or ClassNode. For - * global transformations it is usually safe to ignore this parameter. - * @param source The source unit being compiled. The source unit may contain several classes. For global transformations, - * information about the AST can be retrieved from this object. - */ - public void visit(ASTNode[] nodes, SourceUnit source) { - DetachedCriteriaTransformer transformer = new DetachedCriteriaTransformer(source); - AnnotatedNode parent = (AnnotatedNode) nodes[1]; - ClassNode cNode = (ClassNode) parent; - transformer.visitClass(cNode); - } -} 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 deleted file mode 100644 index d1e3f525b..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaTransformer.java +++ /dev/null @@ -1,1350 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.query.transform; - -import grails.gorm.DetachedCriteria; -import grails.persistence.Entity; -import grails.util.GrailsNameUtils; - -import java.io.File; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.codehaus.groovy.ast.ASTNode; -import org.codehaus.groovy.ast.AnnotationNode; -import org.codehaus.groovy.ast.ClassCodeVisitorSupport; -import org.codehaus.groovy.ast.ClassHelper; -import org.codehaus.groovy.ast.ClassNode; -import org.codehaus.groovy.ast.FieldNode; -import org.codehaus.groovy.ast.GenericsType; -import org.codehaus.groovy.ast.MethodNode; -import org.codehaus.groovy.ast.Parameter; -import org.codehaus.groovy.ast.PropertyNode; -import org.codehaus.groovy.ast.Variable; -import org.codehaus.groovy.ast.VariableScope; -import org.codehaus.groovy.ast.expr.ArgumentListExpression; -import org.codehaus.groovy.ast.expr.BinaryExpression; -import org.codehaus.groovy.ast.expr.BitwiseNegationExpression; -import org.codehaus.groovy.ast.expr.CastExpression; -import org.codehaus.groovy.ast.expr.ClassExpression; -import org.codehaus.groovy.ast.expr.ClosureExpression; -import org.codehaus.groovy.ast.expr.ConstantExpression; -import org.codehaus.groovy.ast.expr.ConstructorCallExpression; -import org.codehaus.groovy.ast.expr.DeclarationExpression; -import org.codehaus.groovy.ast.expr.Expression; -import org.codehaus.groovy.ast.expr.MapEntryExpression; -import org.codehaus.groovy.ast.expr.MapExpression; -import org.codehaus.groovy.ast.expr.MethodCallExpression; -import org.codehaus.groovy.ast.expr.NotExpression; -import org.codehaus.groovy.ast.expr.PropertyExpression; -import org.codehaus.groovy.ast.expr.RangeExpression; -import org.codehaus.groovy.ast.expr.StaticMethodCallExpression; -import org.codehaus.groovy.ast.expr.VariableExpression; -import org.codehaus.groovy.ast.stmt.BlockStatement; -import org.codehaus.groovy.ast.stmt.CaseStatement; -import org.codehaus.groovy.ast.stmt.CatchStatement; -import org.codehaus.groovy.ast.stmt.ExpressionStatement; -import org.codehaus.groovy.ast.stmt.ForStatement; -import org.codehaus.groovy.ast.stmt.IfStatement; -import org.codehaus.groovy.ast.stmt.Statement; -import org.codehaus.groovy.ast.stmt.SwitchStatement; -import org.codehaus.groovy.ast.stmt.TryCatchStatement; -import org.codehaus.groovy.ast.stmt.WhileStatement; -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.codehaus.groovy.syntax.Token; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.criteria.FunctionCallingCriterion; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.grails.datastore.mapping.reflect.NameUtils; - -/** - * ClassCodeVisitorSupport that transforms where methods into detached criteria queries - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("unchecked") -public class DetachedCriteriaTransformer extends ClassCodeVisitorSupport { - - private static final Class[] EMPTY_JAVA_CLASS_ARRAY = {}; - private static final VariableExpression THIS_EXPRESSION = new VariableExpression("this"); - private static final VariableExpression DELEGATE_EXPRESSION = new VariableExpression("delegate"); - public static final String AND_OPERATOR = "&"; - public static final String OR_OPERATOR = "|"; - public static final ClassNode DETACHED_CRITERIA_CLASS_NODE = ClassHelper.make(DetachedCriteria.class); - public static final Set CANDIDATE_METHODS_WHERE_ONLY = newSet("where"); - public static final ClassNode FUNCTION_CALL_CRITERION = new ClassNode(FunctionCallingCriterion.class); - public static final String EQUALS_OPERATOR = "=="; - public static final String IS_NULL_CRITERION = "isNull"; - public static final ConstantExpression WHERE_LAZY = new ConstantExpression("whereLazy"); - - private SourceUnit sourceUnit; - private static final Set CANDIDATE_METHODS = newSet("where", "whereLazy", "whereAny", "findAll", "find"); - - private static final Set SUPPORTED_FUNCTIONS = newSet( - "lower", "upper", "trim", "length", "second", - "hour", "minute", "day", "month", "year"); - - private static final Map OPERATOR_TO_CRITERIA_METHOD_MAP = (Map)newMap( - "==", "eq", - "!=", "ne", - ">", "gt", - "<", "lt", - ">=", "ge", - "<=", "le", - "==~", "like", - "=~", "ilike", - "in", "inList"); - - private static final Map OPERATOR_TO_CRITERION_METHOD_MAP = (Map)newMap( - "==", new ClassNode(Query.Equals.class), - "!=", new ClassNode(Query.NotEquals.class), - ">", new ClassNode(Query.GreaterThan.class), - "<", new ClassNode(Query.LessThan.class), - ">=", new ClassNode(Query.GreaterThanEquals.class), - "<=", new ClassNode(Query.LessThanEquals.class), - "==~", new ClassNode(Query.Like.class), - "=~", new ClassNode(Query.ILike.class), - "in", new ClassNode(Query.In.class)); - - private static final Map PROPERTY_COMPARISON_OPERATOR_TO_CRITERIA_METHOD_MAP = (Map)newMap( - "==", "eqProperty", - "!=", "neProperty", - ">", "gtProperty", - "<", "ltProperty", - ">=", "geProperty", - "<=", "leProperty"); - - private static final Map SIZE_OPERATOR_TO_CRITERIA_METHOD_MAP = (Map)newMap( - "==", "sizeEq", - "!=", "sizeNe", - ">", "sizeGt", - "<", "sizeLt", - ">=", "sizeGe", - "<=", "sizeLe"); - - private static final Map AGGREGATE_FUNCTIONS = (Map)newMap( - "avg", "avg", - "max", "max", - "min", "min", - "sum", "sum", - "property", "property", - "count", "countDistinct"); - - private Map detachedCriteriaVariables = new HashMap(); - private Map staticDetachedCriteriaVariables = new HashMap(); - private Map> cachedClassProperties = new HashMap>(); - private Set transformedExpressions = new HashSet(); - private ClassNode currentClassNode; - - DetachedCriteriaTransformer(SourceUnit sourceUnit) { - this.sourceUnit = sourceUnit; - } - - @Override - public void visitClass(ClassNode node) { - try { - this.currentClassNode = node; - super.visitClass(node); - } catch(Exception e) { - logTransformationError(node, e); - } finally { - currentClassNode = null; - detachedCriteriaVariables.clear(); - transformedExpressions.clear(); - } - } - - @Override - public void visitMethod(MethodNode node) { - try { - super.visitMethod(node); - } finally { - detachedCriteriaVariables.clear(); - } - } - - @Override - public void visitField(FieldNode node) { - ClassNode classNode = node.getOwner(); - if (node.isStatic() && isDomainClass(classNode)) { - Expression initialExpression = node.getInitialExpression(); - if (initialExpression instanceof MethodCallExpression) { - MethodCallExpression mce = (MethodCallExpression) initialExpression; - - if (isCandidateWhereMethod(mce.getMethod(), mce.getArguments())) { - ArgumentListExpression args = (ArgumentListExpression) mce.getArguments(); - List argsExpressions = args.getExpressions(); - int totalExpressions = argsExpressions.size(); - if (totalExpressions > 0) { - Expression expression = argsExpressions.get(totalExpressions - 1); - if (expression instanceof ClosureExpression) { - ClosureExpression closureExpression = (ClosureExpression) expression; - transformClosureExpression(classNode, closureExpression); - - String buildMethod = mce.getMethodAsString().equals("whereLazy") ? "buildLazy" : "build"; - - ClassNode detachedCriteriaClassNode = getParameterizedDetachedCriteriaClassNode(classNode); - - MethodCallExpression newInitialExpression = new MethodCallExpression(new ConstructorCallExpression(detachedCriteriaClassNode, new ArgumentListExpression(new ClassExpression(classNode))), buildMethod, new ArgumentListExpression(closureExpression)); - node.setInitialValueExpression(newInitialExpression); - node.setType(detachedCriteriaClassNode); - staticDetachedCriteriaVariables.put(node.getName(), classNode); - } - } - } - } - } - else { - try { - Expression initialExpression = node.getInitialExpression(); - ClosureExpression newClosureExpression = handleDetachedCriteriaCast(initialExpression); - - if (newClosureExpression != null) { - node.setInitialValueExpression(newClosureExpression); - } - } catch (Exception e) { - logTransformationError(node, e); - } - } - - super.visitField(node); - } - - protected ClassNode getParameterizedDetachedCriteriaClassNode(ClassNode classNode) { - ClassNode detachedCriteriaClassNode = DETACHED_CRITERIA_CLASS_NODE.getPlainNodeReference(); - if(classNode != null) { - detachedCriteriaClassNode.setGenericsTypes(new GenericsType[]{new GenericsType(GrailsASTUtils.nonGeneric(classNode))}); - } - return detachedCriteriaClassNode; - } - - @Override - public void visitDeclarationExpression(DeclarationExpression expression) { - Expression initializationExpression = expression.getRightExpression(); - if (initializationExpression instanceof MethodCallExpression) { - MethodCallExpression call = (MethodCallExpression) initializationExpression; - Expression objectExpression = call.getObjectExpression(); - Expression method = call.getMethod(); - Expression arguments = call.getArguments(); - if (isCandidateMethod(method.getText(), arguments, CANDIDATE_METHODS_WHERE_ONLY)) { - ClassNode classNode = new ClassNode(DetachedCriteria.class); - ClassNode targetType = objectExpression.getType(); - if (isDomainClass(targetType)) { - classNode.setGenericsTypes(new GenericsType[]{new GenericsType(targetType)}); - - VariableExpression variableExpression = expression.getVariableExpression(); - if (variableExpression.isClosureSharedVariable()) { - Variable accessedVariable = variableExpression.getAccessedVariable(); - if (accessedVariable instanceof VariableExpression) { - ((VariableExpression)accessedVariable).setType(classNode); - } - } - else { - variableExpression.setType(classNode); - } - String variableName = expression.getVariableExpression().getName(); - detachedCriteriaVariables.put(variableName, targetType); - } - } - } - else if (initializationExpression instanceof ConstructorCallExpression) { - String variableName = expression.getVariableExpression().getName(); - ConstructorCallExpression cce = (ConstructorCallExpression) initializationExpression; - - ClassNode type = cce.getType(); - if (DETACHED_CRITERIA_CLASS_NODE.getName().equals(type.getName())) { - Expression arguments = cce.getArguments(); - if (arguments instanceof ArgumentListExpression) { - ArgumentListExpression ale = (ArgumentListExpression) arguments; - if (ale.getExpressions().size() == 1) { - Expression exp = ale.getExpression(0); - if (exp instanceof ClassExpression) { - ClassExpression clse = (ClassExpression) exp; - detachedCriteriaVariables.put(variableName, clse.getType()); - } - } - } - } - } - else { - try { - ClosureExpression newClosureExpression = handleDetachedCriteriaCast(initializationExpression); - if (newClosureExpression != null) { - expression.setRightExpression(newClosureExpression); - } - } catch (Exception e) { - logTransformationError(initializationExpression, e); - } - } - super.visitDeclarationExpression(expression); - } - - private void logTransformationError(ASTNode astNode, Exception e) { - StringBuilder message = new StringBuilder("Fatal error occurred applying query transformations [ " + e.getMessage() + "] to source [" + sourceUnit.getName() + "]. Please report an issue."); - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - message.append(System.getProperty("line.separator")); - message.append(sw.toString()); - sourceUnit.getErrorCollector().addError(new LocatedMessage(message.toString(), Token.newString(astNode.getText(), astNode.getLineNumber(), astNode.getColumnNumber()), sourceUnit)); - } - - private ClosureExpression handleDetachedCriteriaCast(Expression initializationExpression) { - ClosureExpression newClosureExpression = null; - if ((initializationExpression instanceof CastExpression) && ((CastExpression) initializationExpression).getExpression() instanceof ClosureExpression) { - CastExpression ce = (CastExpression) initializationExpression; - Expression castTarget = ce.getExpression(); - ClosureExpression cle = (ClosureExpression) castTarget; - ClassNode targetCastType = ce.getType(); - if (targetCastType.getName().equals(DetachedCriteria.class.getName())) { - GenericsType[] genericsTypes = targetCastType.getGenericsTypes(); - if (genericsTypes.length > 0) { - ClassNode genericType = genericsTypes[0].getType(); - transformClosureExpression(genericType, cle); - newClosureExpression = cle; - } - } - } - return newClosureExpression; - } - - @Override - public void visitMethodCallExpression(MethodCallExpression call) { - Expression objectExpression = call.getObjectExpression(); - Expression method = call.getMethod(); - Expression arguments = call.getArguments(); - try { - if (isCandidateMethodCallForTransform(objectExpression, method, arguments)) { - ClassExpression ce = getTargetClassExpresssion(objectExpression); - if (ce != null) { - ClassNode classNode = ce.getType(); - this.currentClassNode = classNode; - visitMethodCall(classNode, arguments); - } - } - else if (objectExpression instanceof VariableExpression) { - VariableExpression var = (VariableExpression) objectExpression; - String varName = var.getName(); - - ClassNode varType = detachedCriteriaVariables.get(varName); - if (varType != null && isCandidateWhereMethod(method, arguments)) { - this.currentClassNode = varType; - visitMethodCall(varType, arguments); - } - else if (THIS_EXPRESSION.getName().equals(varName) && currentClassNode != null && isCandidateWhereMethod(method.getText(), arguments)) { - if(isDomainClass(currentClassNode)) { - visitMethodCall(this.currentClassNode, arguments); - call.setMethod(WHERE_LAZY); - } - } - } - else if (objectExpression instanceof PropertyExpression) { - PropertyExpression pe = (PropertyExpression) objectExpression; - String propName = pe.getPropertyAsString(); - ClassNode classNode = pe.getObjectExpression().getType(); - if (isDomainClass(classNode)) { - ClassNode propertyType = getPropertyType(classNode, propName); - if (propertyType != null && DETACHED_CRITERIA_CLASS_NODE.equals(propertyType)) { - visitMethodCall(classNode, arguments); - } - } - } - } catch (Exception e) { - logTransformationError(call, e); - } - super.visitMethodCallExpression(call); - } - - private ClassExpression getTargetClassExpresssion(Expression objectExpression) { - if (objectExpression instanceof ClassExpression) { - return (ClassExpression) objectExpression; - } - if (objectExpression instanceof MethodCallExpression) { - MethodCallExpression mce = (MethodCallExpression) objectExpression; - - Expression oe = mce.getObjectExpression(); - if (oe instanceof ClassExpression) { - return (ClassExpression) oe; - } - } - return null; - } - - private boolean isCandidateMethodCallForTransform(Expression objectExpression, Expression method, Expression arguments) { - return ((objectExpression instanceof ClassExpression) || isObjectExpressionWhereCall(objectExpression)) && - isCandidateWhereMethod(method, arguments); - } - - private boolean isObjectExpressionWhereCall(Expression objectExpression) { - if (objectExpression instanceof MethodCallExpression) { - MethodCallExpression mce = (MethodCallExpression) objectExpression; - return isCandidateWhereMethod(mce.getMethodAsString(),mce.getArguments()); - } - return false; - } - - private void visitMethodCall(ClassNode classNode, Expression arguments) { - if (isDomainClass(classNode) && (arguments instanceof ArgumentListExpression)) { - visitMethodCallOnDetachedCriteria(classNode, (ArgumentListExpression)arguments); - } - } - - private void visitMethodCallOnDetachedCriteria(ClassNode classNode, ArgumentListExpression arguments) { - if (arguments.getExpressions().size() > 0) { - Expression expression = arguments.getExpression(arguments.getExpressions().size()-1); - if (expression instanceof ClosureExpression) { - ClosureExpression closureExpression = (ClosureExpression) expression; - transformClosureExpression(classNode, closureExpression); - } - } - } - - private boolean isCandidateWhereMethod(Expression method, Expression arguments) { - String methodName = method.getText(); - return ((method instanceof ConstantExpression) && isCandidateWhereMethod(methodName, arguments)); - } - - private boolean isCandidateWhereMethod(String methodName, Expression arguments) { - return isCandidateMethod(methodName, arguments, CANDIDATE_METHODS); - } - - private boolean isCandidateMethod(String methodName, Expression arguments, Set candidateMethods) { - if(candidateMethods.contains(methodName)) { - if(arguments instanceof ArgumentListExpression) { - ArgumentListExpression ale = (ArgumentListExpression) arguments; - List expressions = ale.getExpressions(); - if(expressions.size()>0) { - Expression expression = expressions.get(expressions.size()-1); - if(expression instanceof ClosureExpression) { - return true; - } - else if(expression instanceof VariableExpression) { - VariableExpression ve = (VariableExpression) expression; - if(detachedCriteriaVariables.containsKey(ve.getName()) || DETACHED_CRITERIA_CLASS_NODE.getName().equals(ve.getType().getName())) { - return true; - } - } - } - } - } - - return false; - } - - @Override - public void visitStaticMethodCallExpression(StaticMethodCallExpression call) { - String method = call.getMethod(); - Expression arguments = call.getArguments(); - if (isCandidateWhereMethod(method,arguments)) { - ClassNode classNode = call.getOwnerType(); - visitMethodCall(classNode, arguments); - } - super.visitStaticMethodCallExpression(call); - } - - protected void transformClosureExpression(ClassNode classNode, ClosureExpression closureExpression) { - if (transformedExpressions.contains(closureExpression)) return; - ClassNode previousClassNode = this.currentClassNode; - try { - this.currentClassNode = classNode; - List propertyNames = getPropertyNames(classNode); - Statement code = closureExpression.getCode(); - BlockStatement newCode = new BlockStatement(); - boolean addAll = false; - - if (code instanceof BlockStatement) { - BlockStatement bs = (BlockStatement) code; - - addBlockStatementToNewQuery(bs, newCode, addAll, propertyNames, closureExpression.getVariableScope()); - newCode.setVariableScope(bs.getVariableScope()); - } - - if (!newCode.getStatements().isEmpty()) { - transformedExpressions.add(closureExpression); - closureExpression.setCode(newCode); - } - } finally { - this.currentClassNode = previousClassNode; - } - } - - private List getPropertyNames(ClassNode classNode) { - String className = classNode.getName(); - Map cachedProperties = cachedClassProperties.get(className); - if (cachedProperties == null) { - cachedProperties = new HashMap(); - cachedProperties.put(GrailsDomainClassProperty.IDENTITY, new ClassNode(Long.class)); - cachedProperties.put(GrailsDomainClassProperty.VERSION, new ClassNode(Long.class)); - cachedClassProperties.put(className, cachedProperties); - ClassNode currentNode = classNode; - while(currentNode != null && !currentNode.equals(ClassHelper.OBJECT_TYPE)) { - populatePropertiesForClassNode(currentNode, cachedProperties); - currentNode = currentNode.getSuperClass(); - } - } - return new ArrayList(cachedProperties.keySet()); - } - - private void populatePropertiesForClassNode(ClassNode classNode, Map cachedProperties) { - List methods = classNode.getMethods(); - for (MethodNode method : methods) { - String methodName = method.getName(); - if (!method.isAbstract() && isGetter(methodName, method)) { - String propertyName = NameUtils.getPropertyNameForGetterOrSetter(methodName); - if (GrailsDomainClassProperty.HAS_MANY.equals(propertyName) || GrailsDomainClassProperty.BELONGS_TO.equals(propertyName) || GrailsDomainClassProperty.HAS_ONE.equals(propertyName)) { - FieldNode field = classNode.getField(propertyName); - if(field != null) { - populatePropertiesForInitialExpression(cachedProperties, field.getInitialExpression()); - } - } - else if(!method.isStatic()) { - cachedProperties.put(propertyName, method.getReturnType()); - } - } - } - List properties = classNode.getProperties(); - for (PropertyNode property : properties) { - - String propertyName = property.getName(); - if (GrailsDomainClassProperty.HAS_MANY.equals(propertyName) || GrailsDomainClassProperty.BELONGS_TO.equals(propertyName) || GrailsDomainClassProperty.HAS_ONE.equals(propertyName)) { - Expression initialExpression = property.getInitialExpression(); - populatePropertiesForInitialExpression(cachedProperties, initialExpression); - } - else { - cachedProperties.put(propertyName, property.getType()); - } - } - - if(classNode.isResolved()) { - ClassPropertyFetcher propertyFetcher = ClassPropertyFetcher.forClass(classNode.getTypeClass()); - cachePropertiesForAssociationMetadata(cachedProperties, propertyFetcher, GrailsDomainClassProperty.HAS_MANY); - cachePropertiesForAssociationMetadata(cachedProperties, propertyFetcher, GrailsDomainClassProperty.BELONGS_TO); - cachePropertiesForAssociationMetadata(cachedProperties, propertyFetcher, GrailsDomainClassProperty.HAS_ONE); - } - - } - - private void cachePropertiesForAssociationMetadata(Map cachedProperties, ClassPropertyFetcher propertyFetcher, String associationMetadataName) { - if(propertyFetcher.isReadableProperty(associationMetadataName)) { - Object propertyValue = propertyFetcher.getPropertyValue(associationMetadataName); - if(propertyValue instanceof Map) { - Map hasManyMap = (Map) propertyValue; - for (Object propertyName : hasManyMap.keySet()) { - Object val = hasManyMap.get(propertyName); - if(val instanceof Class) { - cachedProperties.put(propertyName.toString(), ClassHelper.make((Class) val).getPlainNodeReference()); - } - } - } - } - } - - private void populatePropertiesForInitialExpression(Map cachedProperties, Expression initialExpression) { - if (initialExpression instanceof MapExpression) { - MapExpression me = (MapExpression) initialExpression; - List mapEntryExpressions = me.getMapEntryExpressions(); - for (MapEntryExpression mapEntryExpression : mapEntryExpressions) { - Expression keyExpression = mapEntryExpression.getKeyExpression(); - Expression valueExpression = mapEntryExpression.getValueExpression(); - if (valueExpression instanceof ClassExpression) { - cachedProperties.put(keyExpression.getText(), valueExpression.getType()); - } - } - } - } - - private void addBlockStatementToNewQuery(BlockStatement blockStatement, BlockStatement newCode, boolean addAll, List propertyNames, VariableScope variableScope) { - List statements = blockStatement.getStatements(); - for (Statement statement : statements) { - addStatementToNewQuery(statement, newCode, addAll, propertyNames, variableScope); - } - } - - private void addStatementToNewQuery(Statement statement, BlockStatement newCode, boolean addAll, List propertyNames, VariableScope variableScope) { - if (statement instanceof BlockStatement) { - addBlockStatementToNewQuery((BlockStatement)statement, newCode, addAll, propertyNames, variableScope); - } - else if (statement instanceof ExpressionStatement) { - ExpressionStatement es = (ExpressionStatement) statement; - - Expression expression = es.getExpression(); - if (expression instanceof DeclarationExpression) { - newCode.addStatement(es); - } - else if (expression instanceof BinaryExpression) { - BinaryExpression be = (BinaryExpression) expression; - addBinaryExpressionToNewBody(propertyNames, newCode, be, addAll, variableScope); - } else if (expression instanceof NotExpression) { - NotExpression not = (NotExpression) expression; - - handleNegation(propertyNames, newCode, not, variableScope); - } else if (expression instanceof MethodCallExpression) { - MethodCallExpression methodCall = (MethodCallExpression) expression; - - handleAssociationMethodCallExpression(newCode, methodCall, propertyNames, variableScope); - } - } - else { - if (statement instanceof IfStatement) { - IfStatement ifs = (IfStatement) statement; - Statement ifb = ifs.getIfBlock(); - BlockStatement newIfBlock = new BlockStatement(); - addStatementToNewQuery(ifb, newIfBlock, addAll, propertyNames, variableScope); - ifs.setIfBlock(flattenStatementIfNecessary(newIfBlock)); - - Statement elseBlock = ifs.getElseBlock(); - if (elseBlock != null) { - BlockStatement newElseBlock = new BlockStatement(); - addStatementToNewQuery(elseBlock, newElseBlock, addAll, propertyNames, variableScope); - ifs.setElseBlock(flattenStatementIfNecessary(newElseBlock)); - } - newCode.addStatement(ifs); - } - else if (statement instanceof SwitchStatement) { - SwitchStatement sw = (SwitchStatement) statement; - - List caseStatements = sw.getCaseStatements(); - for (CaseStatement caseStatement : caseStatements) { - Statement existingCode = caseStatement.getCode(); - BlockStatement newCaseCode = new BlockStatement(); - addStatementToNewQuery(existingCode, newCaseCode, addAll, propertyNames, variableScope); - caseStatement.setCode(flattenStatementIfNecessary(newCaseCode)); - } - - newCode.addStatement(sw); - } - else if (statement instanceof ForStatement) { - ForStatement fs = (ForStatement) statement; - Statement loopBlock = fs.getLoopBlock(); - BlockStatement newLoopBlock = new BlockStatement(); - addStatementToNewQuery(loopBlock, newLoopBlock, addAll, propertyNames, variableScope); - fs.setLoopBlock(flattenStatementIfNecessary(newLoopBlock)); - newCode.addStatement(fs); - } - else if (statement instanceof WhileStatement) { - WhileStatement ws = (WhileStatement) statement; - Statement loopBlock = ws.getLoopBlock(); - BlockStatement newLoopBlock = new BlockStatement(); - addStatementToNewQuery(loopBlock, newLoopBlock, addAll, propertyNames, variableScope); - ws.setLoopBlock(flattenStatementIfNecessary(newLoopBlock)); - newCode.addStatement(ws); - } - else if (statement instanceof TryCatchStatement) { - TryCatchStatement tcs = (TryCatchStatement) statement; - Statement tryStatement = tcs.getTryStatement(); - - BlockStatement newTryStatement = new BlockStatement(); - addStatementToNewQuery(tryStatement, newTryStatement, addAll, propertyNames, variableScope); - tcs.setTryStatement(flattenStatementIfNecessary(newTryStatement)); - - List catchStatements = tcs.getCatchStatements(); - - for (CatchStatement catchStatement : catchStatements) { - BlockStatement newCatchStatement = new BlockStatement(); - Statement code = catchStatement.getCode(); - addStatementToNewQuery(code, newCatchStatement, addAll, propertyNames, variableScope); - catchStatement.setCode(flattenStatementIfNecessary(newCatchStatement)); - } - - Statement finallyStatement = tcs.getFinallyStatement(); - if (finallyStatement != null) { - BlockStatement newFinallyStatement = new BlockStatement(); - addStatementToNewQuery(finallyStatement, newFinallyStatement, addAll, propertyNames, variableScope); - tcs.setFinallyStatement(flattenStatementIfNecessary(newFinallyStatement)); - } - newCode.addStatement(tcs); - } - else { - newCode.addStatement(statement); - } - } - } - - private Statement flattenStatementIfNecessary(BlockStatement blockStatement) { - if (blockStatement.getStatements().size() == 1) { - return blockStatement.getStatements().get(0); - } - return blockStatement; - } - - private void handleAssociationMethodCallExpression(BlockStatement newCode, MethodCallExpression methodCall, List propertyNames, VariableScope variableScope) { - Expression method = methodCall.getMethod(); - String methodName = method.getText(); - ArgumentListExpression arguments = methodCall.getArguments() instanceof ArgumentListExpression ? (ArgumentListExpression) methodCall.getArguments() : null; - - if (methodName.equals("call") && hasClosureArgument(arguments)) { - methodName = methodCall.getObjectExpression().getText(); - } - if (isAssociationMethodCall(propertyNames, methodName, arguments)) { - ClosureAndArguments closureAndArguments = new ClosureAndArguments(variableScope); - ClosureExpression associationQuery = (ClosureExpression) arguments.getExpression(0); - BlockStatement currentBody = closureAndArguments.getCurrentBody(); - ArgumentListExpression argList = closureAndArguments.getArguments(); - newCode.addStatement(new ExpressionStatement(new MethodCallExpression(DELEGATE_EXPRESSION, methodName, argList))); - Statement associationCode = associationQuery.getCode(); - if (associationCode instanceof BlockStatement) { - - List associationPropertyNames = null; - ClassNode type = getPropertyType(methodName); - if (!isDomainClass(type)) { - ClassNode associationTypeFromGenerics = getAssociationTypeFromGenerics(type); - if (associationTypeFromGenerics != null) { - type = associationTypeFromGenerics; - associationPropertyNames = getPropertyNamesForAssociation(associationTypeFromGenerics); - } - } - if (associationPropertyNames == null) { - associationPropertyNames = getPropertyNames(type); - } - - ClassNode existing = currentClassNode; - try { - if (!associationPropertyNames.isEmpty() && !isDomainClass(type)) { - - type = getAssociationTypeFromGenerics(type); - if (type != null) { - associationPropertyNames = getPropertyNames(type); - } - } - if(type != null) { - currentClassNode = type; - addBlockStatementToNewQuery((BlockStatement) associationCode, currentBody, associationPropertyNames.isEmpty(), associationPropertyNames,variableScope); - } - - } finally { - currentClassNode = existing; - } - } - } -// else { -// sourceUnit.getErrorCollector().addError(new LocatedMessage("Method call ["+methodName+"] is invalid. Only binary expressions are allowed in queries.", Token.newString(methodName,methodCall.getLineNumber(), methodCall.getColumnNumber()), sourceUnit)); -// } - } - - private List getPropertyNamesForAssociation(ClassNode type) { - List associationPropertyNames = Collections.emptyList(); - if (type != null) { - if (isDomainClass(type)) { - associationPropertyNames = getPropertyNames(type); - } - else { - ClassNode associationType = getAssociationTypeFromGenerics(type); - if (associationType != null) { - associationPropertyNames = getPropertyNames(associationType); - } - } - } - return associationPropertyNames; - } - - private ClassNode getAssociationTypeFromGenerics(ClassNode type) { - GenericsType[] genericsTypes = type.getGenericsTypes(); - ClassNode associationType = null; - if (genericsTypes != null && genericsTypes.length == 1) { - GenericsType genericType = genericsTypes[0]; - associationType = genericType.getType(); - } - return associationType; - } - - private ClassNode getPropertyType(String prop) { - ClassNode classNode = this.currentClassNode; - return getPropertyType(classNode, prop); - } - - private ClassNode getPropertyType(ClassNode classNode, String prop) { - Map cachedProperties = cachedClassProperties.get(classNode.getName()); - if (cachedProperties != null && cachedProperties.containsKey(prop)) { - return cachedProperties.get(prop); - } - ClassNode type = null; - PropertyNode property = classNode.getProperty(prop); - if (property != null) { - type = property.getType(); - } else { - MethodNode methodNode = currentClassNode.getMethod(GrailsNameUtils.getGetterName(prop), new Parameter[0]); - if (methodNode != null) { - type = methodNode.getReturnType(); - } - else { - FieldNode fieldNode = classNode.getDeclaredField(prop); - if (fieldNode != null) { - type = fieldNode.getType(); - } - } - } - return type; - } - - private boolean isAssociationMethodCall(List propertyNames, String methodName, ArgumentListExpression arguments) { - return propertyNames.contains(methodName) && hasClosureArgument(arguments); - } - - private boolean hasClosureArgument(ArgumentListExpression arguments) { - return arguments != null && arguments.getExpressions().size() == 1 && (arguments.getExpression(0) instanceof ClosureExpression); - } - - private void handleNegation(List propertyNames, BlockStatement newCode, NotExpression not, VariableScope variableScope) { - Expression subExpression = not.getExpression(); - if (subExpression instanceof BinaryExpression) { - ArgumentListExpression arguments = new ArgumentListExpression(); - BlockStatement currentBody = new BlockStatement(); - ClosureExpression newClosureExpression = new ClosureExpression(new Parameter[0], currentBody); - newClosureExpression.setVariableScope(new VariableScope()); - arguments.addExpression(newClosureExpression); - addBinaryExpressionToNewBody(propertyNames, currentBody, (BinaryExpression) subExpression, false, variableScope); - - newCode.addStatement(new ExpressionStatement(new MethodCallExpression(THIS_EXPRESSION, "not", arguments))); - } - else { - sourceUnit.getErrorCollector().addError(new LocatedMessage("You can only negate a binary expressions in queries.", Token.newString(not.getText(),not.getLineNumber(), not.getColumnNumber()), sourceUnit)); - } - } - - private void addBinaryExpressionToNewBody(List propertyNames, BlockStatement newCode, BinaryExpression be, boolean addAll, VariableScope variableScope) { - Token operation = be.getOperation(); - - String operator = operation.getRootText(); - - Expression leftExpression = be.getLeftExpression(); - Expression rightExpression = be.getRightExpression(); - if (leftExpression instanceof VariableExpression) { - VariableExpression leftVariable = (VariableExpression) leftExpression; - String propertyName = leftVariable.getText(); - if (propertyNames.contains(propertyName) || addAll) { - if (OPERATOR_TO_CRITERIA_METHOD_MAP.containsKey(operator)) { - addCriteriaCallMethodExpression(newCode, operator, rightExpression, propertyName, propertyNames, addAll, variableScope); - } - else { - sourceUnit.getErrorCollector().addError(new LocatedMessage("Unsupported operator ["+operator+"] used in query", operation, sourceUnit)); - } - } - else { - if(sourceUnit != null) { - sourceUnit.getErrorCollector().addError(new LocatedMessage("Cannot query on property \""+propertyName+"\" - no such property on class "+ currentClassNode.getName() +" exists.", Token.newString(propertyName,leftExpression.getLineNumber(), leftExpression.getColumnNumber()), sourceUnit)); - } - } - } - else { - - if (leftExpression instanceof MethodCallExpression) { - MethodCallExpression mce = (MethodCallExpression) leftExpression; - String methodName = mce.getMethodAsString(); - Expression objectExpression = mce.getObjectExpression(); - if ("size".equals(methodName) && (objectExpression instanceof VariableExpression)) { - String propertyName = objectExpression.getText(); - if (propertyNames.contains(propertyName)) { - String sizeOperator = SIZE_OPERATOR_TO_CRITERIA_METHOD_MAP.get(operator); - if (sizeOperator != null) { - addCriteriaCall(newCode,operator,rightExpression, propertyName, propertyNames, addAll, sizeOperator, variableScope); - } - else { - sourceUnit.getErrorCollector().addError(new LocatedMessage("Unsupported operator ["+operator+"] used in size() query", operation, sourceUnit)); - } - } - else { - sourceUnit.getErrorCollector().addError(new LocatedMessage("Cannot query size of property \""+propertyName+"\" - no such property on class "+currentClassNode.getName()+" exists.", Token.newString(propertyName,leftExpression.getLineNumber(), leftExpression.getColumnNumber()), sourceUnit)); - } - - return; - } - else { - boolean isFunctionCall = isFunctionCall(mce, methodName, objectExpression); - if (isFunctionCall) { - String functionName = methodName; - ArgumentListExpression existingArgs = (ArgumentListExpression) mce.getArguments(); - Expression propertyNameExpression = existingArgs.getExpression(0); - if (propertyNameExpression instanceof PropertyExpression) { - handleAssociationQueryViaPropertyExpression((PropertyExpression) propertyNameExpression, rightExpression,operator,newCode,propertyNames,functionName, variableScope); - } - else { - handleFunctionCall(newCode, operator, rightExpression, functionName, propertyNameExpression); - } - return; - } - } - } - - String methodNameToCall = null; - if (operator.contains(AND_OPERATOR)) { - methodNameToCall = "and"; - } else if (operator.contains(OR_OPERATOR)) { - methodNameToCall = "or"; - } - ArgumentListExpression arguments = new ArgumentListExpression(); - BlockStatement currentBody = new BlockStatement(); - handleBinaryExpressionSide(leftExpression,rightExpression, operator, currentBody, addAll, propertyNames, variableScope); - handleBinaryExpressionSide(rightExpression, rightExpression, operator,currentBody, addAll, propertyNames, variableScope); - - ClosureExpression newClosureExpression = new ClosureExpression(new Parameter[0], currentBody); - newClosureExpression.setVariableScope(variableScope); - arguments.addExpression(newClosureExpression); - if (methodNameToCall != null) { - newCode.addStatement(new ExpressionStatement(new MethodCallExpression(THIS_EXPRESSION, methodNameToCall, arguments))); - } - else { - List statements = currentBody.getStatements(); - for (Statement statement : statements) { - newCode.addStatement(statement); - } - } - } - } - - private boolean isFunctionCall(MethodCallExpression mce) { - boolean isThis = "this".equals(mce.getObjectExpression().getText()); - Expression arguments = mce.getArguments(); - boolean hasOneArg = arguments instanceof ArgumentListExpression ? ((ArgumentListExpression)arguments).getExpressions().size() == 1 : false; - return isThis && hasOneArg && SUPPORTED_FUNCTIONS.contains(mce.getMethodAsString()); - } - - private boolean isFunctionCall(MethodCallExpression mce, String methodName, Expression objectExpression) { - boolean isThis = "this".equals(objectExpression.getText()); - Expression arguments = mce.getArguments(); - boolean hasOneArg = arguments instanceof ArgumentListExpression ? ((ArgumentListExpression)arguments).getExpressions().size() == 1 : false; - return isThis && hasOneArg && SUPPORTED_FUNCTIONS.contains(methodName); - } - - private void handleFunctionCall(BlockStatement newCode,String operator, Expression rightExpression, String functionName, Expression propertyNameExpression) { - ArgumentListExpression newArgs = new ArgumentListExpression(); - ArgumentListExpression constructorArgs = new ArgumentListExpression(); - constructorArgs.addExpression(new ConstantExpression(functionName)); - ClassNode criterionClassNode = OPERATOR_TO_CRITERION_METHOD_MAP.get(operator); - if (criterionClassNode != null) { - ArgumentListExpression criterionConstructorArguments = new ArgumentListExpression(); - if (!(propertyNameExpression instanceof ConstantExpression)) { - propertyNameExpression = new ConstantExpression(propertyNameExpression.getText()); - } - criterionConstructorArguments.addExpression(propertyNameExpression); - criterionConstructorArguments.addExpression(rightExpression); - constructorArgs.addExpression(new ConstructorCallExpression(criterionClassNode, criterionConstructorArguments)); - ConstructorCallExpression constructorCallExpression = new ConstructorCallExpression(FUNCTION_CALL_CRITERION, constructorArgs); - newArgs.addExpression(constructorCallExpression ); - newCode.addStatement(new ExpressionStatement(new MethodCallExpression(THIS_EXPRESSION, "add", newArgs))); - } - else { - sourceUnit.getErrorCollector().addError(new LocatedMessage("Unsupported operator ["+operator+"] used with function call ["+functionName+"] in query", Token.newString(functionName,rightExpression.getLineNumber(), rightExpression.getColumnNumber()), sourceUnit)); - } - } - - private void handleBinaryExpressionSide(Expression expressionSide, Expression oppositeSide, String operator, BlockStatement newCode, boolean addAll, List propertyNames, VariableScope variableScope) { - if (expressionSide instanceof BinaryExpression) { - addBinaryExpressionToNewBody(propertyNames, newCode, (BinaryExpression) expressionSide, addAll, variableScope); - } else if (expressionSide instanceof NotExpression) { - handleNegation(propertyNames, newCode, (NotExpression) expressionSide, variableScope); - } - else if (expressionSide instanceof MethodCallExpression) { - MethodCallExpression methodCallExpression = (MethodCallExpression) expressionSide; - handleAssociationMethodCallExpression(newCode, methodCallExpression, propertyNames, variableScope); - } - else if (expressionSide instanceof PropertyExpression) { - PropertyExpression pe = (PropertyExpression) expressionSide; - handleAssociationQueryViaPropertyExpression(pe, oppositeSide, operator, newCode, propertyNames, null, variableScope); - } - else { - // TODO: compilation error? - } - } - - private void handleAssociationQueryViaPropertyExpression(PropertyExpression pe, Expression oppositeSide, String operator, BlockStatement newCode, List propertyNames, String functionName, VariableScope variableScope) { - Expression objectExpression = pe.getObjectExpression(); - if (objectExpression instanceof PropertyExpression) { - // nested property expression, we have to find the root variable expression and walk backwards through all the properties involved - List associationMethodCalls = new ArrayList(); - - while(objectExpression instanceof PropertyExpression) { - PropertyExpression currentPe = (PropertyExpression) objectExpression; - associationMethodCalls.add(currentPe.getPropertyAsString()); - objectExpression = currentPe.getObjectExpression(); - } - - if (objectExpression instanceof VariableExpression) { - VariableExpression ve = (VariableExpression) objectExpression; - - associationMethodCalls.add(ve.getName()); - - Collections.reverse(associationMethodCalls); - - ClassNode currentType = currentClassNode; - BlockStatement currentBody = newCode; - - for (Iterator iterator = associationMethodCalls.iterator(); iterator.hasNext(); ) { - String associationMethodCall = iterator.next(); - - ClosureAndArguments closureAndArguments = new ClosureAndArguments(variableScope); - - ArgumentListExpression arguments = closureAndArguments.getArguments(); - ClassNode type = getPropertyTypeFromGenerics(associationMethodCall, currentType); - - if (type == null) break; - - currentType = type; - currentBody.addStatement(new ExpressionStatement(new MethodCallExpression(DELEGATE_EXPRESSION, associationMethodCall, arguments))); - currentBody = closureAndArguments.getCurrentBody(); - - if (!iterator.hasNext()) { - String associationProperty = pe.getPropertyAsString(); - List associationPropertyNames = getPropertyNamesForAssociation(type); - ClassNode existing = this.currentClassNode; - try { - - this.currentClassNode = type; - boolean hasNoProperties = associationPropertyNames.isEmpty(); - if (functionName != null) { - handleFunctionCall(currentBody, operator, oppositeSide, functionName, new ConstantExpression(associationProperty)); - } - else { - addCriteriaCallMethodExpression(currentBody, operator, oppositeSide, associationProperty, associationPropertyNames, hasNoProperties, variableScope); - } - } finally { - this.currentClassNode = existing; - } - } - } - } - } - else if (objectExpression instanceof VariableExpression) { - String propertyName = objectExpression.getText(); - if (propertyNames.contains(propertyName)) { - String associationProperty = pe.getPropertyAsString(); - - ClassNode classNode = currentClassNode; - ClassNode type = getPropertyTypeFromGenerics(propertyName, classNode); - List associationPropertyNames = getPropertyNamesForAssociation(type); - if (associationPropertyNames == null) { - associationPropertyNames = getPropertyNamesForAssociation(classNode); - } - - ClosureAndArguments closureAndArguments = new ClosureAndArguments(variableScope); - BlockStatement currentBody = closureAndArguments.getCurrentBody(); - ArgumentListExpression arguments = closureAndArguments.getArguments(); - - boolean hasNoProperties = associationPropertyNames.isEmpty(); - if (!hasNoProperties && !associationPropertyNames.contains(associationProperty)) { - sourceUnit.getErrorCollector().addError(new LocatedMessage("Cannot query property \""+associationProperty+"\" - no such property on class "+type.getName()+" exists.", Token.newString(propertyName, pe.getLineNumber(), pe.getColumnNumber()), sourceUnit)); - } - ClassNode existing = this.currentClassNode; - try { - this.currentClassNode = type; - if (functionName != null) { - handleFunctionCall(currentBody, operator, oppositeSide, functionName, new ConstantExpression(associationProperty)); - } - else { - addCriteriaCallMethodExpression(currentBody, operator, oppositeSide, associationProperty, associationPropertyNames, hasNoProperties, variableScope); - } - } finally { - this.currentClassNode = existing; - } - newCode.addStatement(new ExpressionStatement(new MethodCallExpression(DELEGATE_EXPRESSION, propertyName, arguments))); - } - else if (!variableScope.isReferencedLocalVariable(propertyName)) { - sourceUnit.getErrorCollector().addError(new LocatedMessage("Cannot query property \""+propertyName+"\" - no such property on class "+this.currentClassNode.getName()+" exists.", Token.newString(propertyName, pe.getLineNumber(), pe.getColumnNumber()), sourceUnit)); - } - } - } - - private ClassNode getPropertyTypeFromGenerics(String propertyName, ClassNode classNode) { - ClassNode type = getPropertyType(classNode, propertyName); - if (type != null && !isDomainClass(type)) { - ClassNode associationTypeFromGenerics = getAssociationTypeFromGenerics(type); - if (associationTypeFromGenerics != null && isDomainClass(associationTypeFromGenerics)) { - type = associationTypeFromGenerics; - } - } - return type; - } - - private void addCriteriaCallMethodExpression(BlockStatement newCode, String operator, Expression rightExpression, String propertyName, List propertyNames, boolean addAll, VariableScope variableScope) { - String methodToCall = OPERATOR_TO_CRITERIA_METHOD_MAP.get(operator); - if (methodToCall == null) { - sourceUnit.getErrorCollector().addError(new LocatedMessage("Unsupported operator ["+operator+"] used in query", Token.newString(rightExpression.getText(), rightExpression.getLineNumber(),rightExpression.getColumnNumber()), sourceUnit)); - } - addCriteriaCall(newCode, operator, rightExpression, propertyName, propertyNames, addAll, methodToCall, variableScope); - } - - private void addCriteriaCall(BlockStatement newCode, String operator, Expression rightExpression, String propertyName, List propertyNames, boolean addAll, String methodToCall, VariableScope variableScope) { - if (rightExpression instanceof VariableExpression) { - String rightPropertyName = rightExpression.getText(); - if (!variableScope.isReferencedLocalVariable(rightPropertyName)) { - if ((propertyNames.contains(rightPropertyName) || addAll) && PROPERTY_COMPARISON_OPERATOR_TO_CRITERIA_METHOD_MAP.containsKey(operator)) { - methodToCall = PROPERTY_COMPARISON_OPERATOR_TO_CRITERIA_METHOD_MAP.get(operator); - rightExpression = new ConstantExpression(rightPropertyName); - } - } - } else if (rightExpression instanceof MethodCallExpression) { - // potential aggregation - MethodCallExpression aggregateMethodCall = (MethodCallExpression) rightExpression; - String methodName = aggregateMethodCall.getMethodAsString(); - String aggregateFunctionName = AGGREGATE_FUNCTIONS.get(methodName); - if ("of".equals(methodName) && aggregateMethodCall.getObjectExpression() instanceof MethodCallExpression) { - ArgumentListExpression arguments = (ArgumentListExpression)aggregateMethodCall.getArguments(); - if (arguments.getExpressions().size() == 1 && arguments.getExpression(0) instanceof ClosureExpression) { - ClosureExpression ce = (ClosureExpression) arguments.getExpression(0); - transformClosureExpression(this.currentClassNode,ce); - aggregateMethodCall = (MethodCallExpression) aggregateMethodCall.getObjectExpression(); - - aggregateFunctionName = AGGREGATE_FUNCTIONS.get(aggregateMethodCall.getMethodAsString()); - ArgumentListExpression aggregateMethodCallArguments = (ArgumentListExpression)aggregateMethodCall.getArguments(); - if (aggregateFunctionName != null && aggregateMethodCallArguments.getExpressions().size() == 1) { - Expression expression = aggregateMethodCallArguments.getExpression(0); - String aggregatePropertyName = null; - if (expression instanceof VariableExpression || expression instanceof ConstantExpression) { - aggregatePropertyName = expression.getText(); - } - - boolean validProperty = aggregatePropertyName != null && propertyNames.contains(aggregatePropertyName); - if (validProperty) { - BlockStatement bs = (BlockStatement) ce.getCode(); - addProjectionToCurrentBody(bs, aggregateFunctionName, aggregatePropertyName, variableScope); - rightExpression = new MethodCallExpression(new ConstructorCallExpression(getParameterizedDetachedCriteriaClassNode(null), new ArgumentListExpression(new ClassExpression(this.currentClassNode))), "build", new ArgumentListExpression(ce)); - } - } - } - } - else if (aggregateFunctionName != null) { - Expression arguments = aggregateMethodCall.getArguments(); - if (arguments instanceof ArgumentListExpression) { - ArgumentListExpression argList = (ArgumentListExpression) arguments; - List expressions = argList.getExpressions(); - int argCount = expressions.size(); - if (argCount == 1) { - Expression expression = expressions.get(0); - String aggregatePropertyName = null; - if (expression instanceof VariableExpression || expression instanceof ConstantExpression) { - aggregatePropertyName = expression.getText(); - } - else { - sourceUnit.getErrorCollector().addError(new LocatedMessage("Cannot use aggregate function "+aggregateFunctionName+" on expressions \""+expression.getText()+"\".", Token.newString(propertyName,aggregateMethodCall.getLineNumber(), aggregateMethodCall.getColumnNumber()), sourceUnit)); - return; - } - - boolean validProperty = aggregatePropertyName != null && propertyNames.contains(aggregatePropertyName); - if (validProperty) { - ClosureAndArguments closureAndArguments = new ClosureAndArguments(variableScope); - BlockStatement currentBody = closureAndArguments.getCurrentBody(); - - addProjectionToCurrentBody(currentBody, aggregateFunctionName, aggregatePropertyName, variableScope); - - rightExpression = closureAndArguments.getClosureExpression(); - - if ("property".equals(aggregateFunctionName)) { - methodToCall = methodToCall + "All"; - } - } - else { - sourceUnit.getErrorCollector().addError(new LocatedMessage("Cannot use aggregate function "+aggregateFunctionName+" on property \""+aggregatePropertyName+"\" - no such property on class "+this.currentClassNode.getName()+" exists.", Token.newString(propertyName,aggregateMethodCall.getLineNumber(), aggregateMethodCall.getColumnNumber()), sourceUnit)); - } - } - } - } - else if (isFunctionCall(aggregateMethodCall)) { - // TODO: Allow function calls on right hand arguments - ArgumentListExpression existingArgs = (ArgumentListExpression) aggregateMethodCall.getArguments(); - Expression propertyNameExpression = existingArgs.getExpression(0); - sourceUnit.getErrorCollector().addError(new LocatedMessage("Function call "+aggregateFunctionName+" not allowed on property \""+propertyNameExpression.getText()+"\". Function calls can currently only be used on the left-hand side of expressions", Token.newString(propertyName,aggregateMethodCall.getLineNumber(), aggregateMethodCall.getColumnNumber()), sourceUnit)); - return ; -// -// ArgumentListExpression newArgs = new ArgumentListExpression(); -// ArgumentListExpression constructorArgs = new ArgumentListExpression(); -// constructorArgs.addExpression(new ConstantExpression(methodName)); -// ClassNode criterionClassNode = OPERATOR_TO_PROPERTY_CRITERION_METHOD_MAP.get(operator); -// if (criterionClassNode != null) { -// ArgumentListExpression criterionConstructorArguments = new ArgumentListExpression(); -// if (!(propertyNameExpression instanceof ConstantExpression)) { -// propertyNameExpression = new ConstantExpression(propertyNameExpression.getText()); -// } -// criterionConstructorArguments.addExpression(new ConstantExpression(propertyName)); -// criterionConstructorArguments.addExpression(propertyNameExpression); -// -// constructorArgs.addExpression(new ConstructorCallExpression(criterionClassNode, criterionConstructorArguments)); -// constructorArgs.addExpression(new ConstantExpression(true)); -// ConstructorCallExpression constructorCallExpression = new ConstructorCallExpression(FUNCTION_CALL_CRITERION, constructorArgs); -// newArgs.addExpression(constructorCallExpression ); -// -// newCode.addStatement(new ExpressionStatement(new MethodCallExpression(THIS_EXPRESSION, "add", newArgs))); -// } -// else { -// sourceUnit.getErrorCollector().addError(new LocatedMessage("Function call "+aggregateFunctionName+" not allowed on property \""+propertyNameExpression.getText()+"\".", Token.newString(propertyName,aggregateMethodCall.getLineNumber(), aggregateMethodCall.getColumnNumber()), sourceUnit)); -// } -// return; - } - } else { - if ("like".equals(methodToCall) && rightExpression instanceof BitwiseNegationExpression) { - methodToCall = "rlike"; - BitwiseNegationExpression bne = (BitwiseNegationExpression) rightExpression; - rightExpression = bne.getExpression(); - } - else if ("inList".equals(methodToCall) && rightExpression instanceof RangeExpression) { - methodToCall = "between"; - RangeExpression re = (RangeExpression) rightExpression; - ArgumentListExpression betweenArgs = new ArgumentListExpression(); - betweenArgs.addExpression(new ConstantExpression(propertyName)) - .addExpression(re.getFrom()) - .addExpression(re.getTo()); - rightExpression = betweenArgs; - } - } - ArgumentListExpression arguments; - - if (rightExpression instanceof ArgumentListExpression) { - arguments = (ArgumentListExpression) rightExpression; - } - else if (rightExpression instanceof ConstantExpression) { - ConstantExpression constant = (ConstantExpression) rightExpression; - if (constant.getValue() == null) { - boolean singleArg = false; - if (operator.equals(EQUALS_OPERATOR)) { - singleArg = true; - methodToCall = IS_NULL_CRITERION; - } - else if (operator.equals("!=")) { - singleArg = true; - methodToCall = "isNotNull"; - } - - arguments = new ArgumentListExpression(); - arguments.addExpression(new ConstantExpression(propertyName)); - if (!singleArg) { - arguments.addExpression(rightExpression); - } - } - else { - arguments = new ArgumentListExpression(); - arguments.addExpression(new ConstantExpression(propertyName)) - .addExpression(rightExpression); - } - } - else { - arguments = new ArgumentListExpression(); - arguments.addExpression(new ConstantExpression(propertyName)) - .addExpression(rightExpression); - } - newCode.addStatement(new ExpressionStatement(new MethodCallExpression(THIS_EXPRESSION, methodToCall, arguments))); - } - - private void addProjectionToCurrentBody(BlockStatement currentBody, String functionName, String aggregatePropertyName, VariableScope variableScope) { - ClosureAndArguments projectionsBody = new ClosureAndArguments(variableScope); - ArgumentListExpression aggregateArgs = new ArgumentListExpression(); - aggregateArgs.addExpression(new ConstantExpression(aggregatePropertyName)); - projectionsBody.getCurrentBody().addStatement(new ExpressionStatement(new MethodCallExpression(THIS_EXPRESSION, functionName, aggregateArgs))); - currentBody.addStatement(new ExpressionStatement(new MethodCallExpression(THIS_EXPRESSION, "projections", projectionsBody.getArguments()))); - } - - protected boolean isDomainClass(ClassNode classNode) { - if (classNode == null) return false; - String filePath = classNode.getModule() != null ? classNode.getModule().getDescription() : null; - if (filePath != null) { - try { - if (org.codehaus.groovy.grails.io.support.GrailsResourceUtils.isDomainClass(new File(filePath).toURI().toURL())) { - return true; - } - } catch (MalformedURLException e) { - // ignore - } - } - List annotations = classNode.getAnnotations(); - if (annotations != null && !annotations.isEmpty()) { - for (AnnotationNode annotation : annotations) { - String className = annotation.getClassNode().getName(); - if (Entity.class.getName().equals(className)) { - return true; - } - } - } - return false; - } - - @Override - protected SourceUnit getSourceUnit() { - return this.sourceUnit; - } - - private boolean isGetter(String methodName, MethodNode declaredMethod) { - return declaredMethod.getParameters().length == 0 && GrailsClassUtils.isGetter(methodName, EMPTY_JAVA_CLASS_ARRAY); - } - - private class ClosureAndArguments { - private BlockStatement currentBody; - private ArgumentListExpression arguments; - private ClosureExpression closureExpression; - private VariableScope variableScope; - - private ClosureAndArguments(VariableScope variableScope) { - this.variableScope = variableScope; - build(); - } - - public BlockStatement getCurrentBody() { - return currentBody; - } - - public ArgumentListExpression getArguments() { - return arguments; - } - - private ClosureAndArguments build() { - currentBody = new BlockStatement(); - closureExpression = new ClosureExpression(new Parameter[0], currentBody); - closureExpression.setVariableScope(variableScope); - closureExpression.setCode(currentBody); - - arguments = new ArgumentListExpression(); - arguments.addExpression(closureExpression); - return this; - } - - public ClosureExpression getClosureExpression() { - return closureExpression; - } - } - - @SuppressWarnings("rawtypes") - private static Map newMap(Object... keysAndValues) { - if (keysAndValues == null) { - return Collections.emptyMap(); - } - if (keysAndValues.length % 2 == 1) { - throw new IllegalArgumentException("Must have an even number of keys and values"); - } - - Map map = new HashMap(); - for (int i = 0; i < keysAndValues.length; i += 2) { - map.put((K)keysAndValues[i], (V)keysAndValues[i + 1]); - } - return map; - } - - private static Set newSet(T... values) { - if (values == null) { - return Collections.emptySet(); - } - - return new HashSet(Arrays.asList(values)); - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/GlobalDetachedCriteriaASTTransformation.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/GlobalDetachedCriteriaASTTransformation.java deleted file mode 100644 index 97b93ebd2..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/query/transform/GlobalDetachedCriteriaASTTransformation.java +++ /dev/null @@ -1,54 +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.query.transform; - -import org.codehaus.groovy.ast.ASTNode; -import org.codehaus.groovy.ast.ClassNode; -import org.codehaus.groovy.ast.ModuleNode; -import org.codehaus.groovy.control.CompilePhase; -import org.codehaus.groovy.control.SourceUnit; -import org.codehaus.groovy.transform.ASTTransformation; -import org.codehaus.groovy.transform.GroovyASTTransformation; - -import java.util.List; - -/** - * Global version of the detached query transformer - * - * @author Graeme Rocher - * @since 1.0 - */ -@GroovyASTTransformation(phase= CompilePhase.CANONICALIZATION) -public class GlobalDetachedCriteriaASTTransformation implements ASTTransformation{ - /** - * The method is invoked when an AST Transformation is active. For local transformations, it is invoked once - * each time the local annotation is encountered. For global transformations, it is invoked once for every source - * unit, which is typically a source file. - * - * @param nodes The ASTnodes when the call was triggered. Element 0 is the AnnotationNode that triggered this - * annotation to be activated. Element 1 is the AnnotatedNode decorated, such as a MethodNode or ClassNode. For - * global transformations it is usually safe to ignore this parameter. - * @param source The source unit being compiled. The source unit may contain several classes. For global transformations, - * information about the AST can be retrieved from this object. - */ - public void visit(ASTNode[] nodes, SourceUnit source) { - DetachedCriteriaTransformer transformer = new DetachedCriteriaTransformer(source); - ModuleNode ast = source.getAST(); - List classes = ast.getClasses(); - for (ClassNode aClass : classes) { - transformer.visitClass(aClass); - } - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/support/BeforeValidateHelper.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/support/BeforeValidateHelper.java deleted file mode 100644 index 0a1034fb0..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/support/BeforeValidateHelper.java +++ /dev/null @@ -1,55 +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.support; - -import java.lang.reflect.Method; -import java.util.List; - -import org.springframework.util.ReflectionUtils; - -public class BeforeValidateHelper { - public static final String BEFORE_VALIDATE = "beforeValidate"; - - public void invokeBeforeValidate(final Object target, final List validatedFieldsList) { - Class domainClass = target.getClass(); - Method method = null; - if (validatedFieldsList == null) { - // prefer the no-arg version of beforeValidate() if validatedFieldsList - // is null... - method = ReflectionUtils.findMethod(domainClass, BEFORE_VALIDATE); - if (method == null) { - method = ReflectionUtils.findMethod(domainClass, BEFORE_VALIDATE, List.class); - } - } - else { - // prefer the list-arg version of beforeValidate() if - // validatedFieldsList is not null... - method = ReflectionUtils.findMethod(domainClass, BEFORE_VALIDATE, List.class); - if (method == null) { - method = ReflectionUtils.findMethod(domainClass, BEFORE_VALIDATE); - } - } - if (method != null) { - ReflectionUtils.makeAccessible(method); - Class[] parameterTypes = method.getParameterTypes(); - if (parameterTypes.length == 1) { - ReflectionUtils.invokeMethod(method, target, validatedFieldsList); - } - else { - ReflectionUtils.invokeMethod(method, target); - } - } - } -} \ No newline at end of file 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 deleted file mode 100644 index 6076d71be..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/support/DatastorePersistenceContextInterceptor.java +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright (C) 2010 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.support; - -import javax.persistence.FlushModeType; - -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; -import org.grails.datastore.mapping.transactions.SessionHolder; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -/** - * @since 1.0 - */ -public class DatastorePersistenceContextInterceptor implements PersistenceContextInterceptor { - - private static final Log LOG = LogFactory.getLog(DatastorePersistenceContextInterceptor.class); - protected Datastore datastore; - protected boolean participate; - - public DatastorePersistenceContextInterceptor(Datastore datastore) { - this.datastore = datastore; - } - - public void init() { - if (TransactionSynchronizationManager.getResource(datastore) != null) { - // Do not modify the Session: just set the participate flag. - participate = true; - } - else { - LOG.debug("Opening single Datastore session in DatastorePersistenceContextInterceptor"); - Session session = getSession(); - session.setFlushMode(FlushModeType.AUTO); - try { - DatastoreUtils.bindSession(session); - } catch (IllegalStateException e) { - // ignore, already bound - } - } - } - - protected Session getSession() { - return DatastoreUtils.getSession(datastore, true); - } - - public void destroy() { - if (participate) { - return; - } - - // single session mode - if (TransactionSynchronizationManager.getResource(datastore) != null) { - SessionHolder holder = (SessionHolder)TransactionSynchronizationManager.unbindResource(datastore); - LOG.debug("Closing single Datastore session in DatastorePersistenceContextInterceptor"); - try { - Session session = holder.getSession(); - DatastoreUtils.closeSession(session); - } - catch (RuntimeException ex) { - LOG.error("Unexpected exception on closing Datastore Session", ex); - } - } - } - - public void disconnect() { - destroy(); - } - - public void reconnect() { - init(); - } - - public void flush() { - getSession().flush(); - } - - public void clear() { - getSession().clear(); - } - - public void setReadOnly() { - getSession().setFlushMode(FlushModeType.COMMIT); - } - - public void setReadWrite() { - getSession().setFlushMode(FlushModeType.AUTO); - } - - public boolean isOpen() { - try { - return DatastoreUtils.doGetSession(datastore, false).isConnected(); - } - catch (IllegalStateException e) { - return false; - } - } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/utils/InstanceProxy.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/utils/InstanceProxy.groovy deleted file mode 100644 index aa76201b3..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/utils/InstanceProxy.groovy +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 2010 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.utils - -/** - * A proxy onto another instance - * - * @author Graeme Rocher - * @since 1.0 - */ -class InstanceProxy { - def instance - def target - - def invokeMethod(String name, args) { - target."$name"(instance, *args) - } - - void setProperty(String name, val) { - target."$name" = val - } - - def getProperty(String name) { - target."$name" - } - - void putAt(String name, val) { - target."$name" = val - } - - def getAt(String name) { - target."$name" - } -} \ No newline at end of file diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/utils/ReflectionUtils.java b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/utils/ReflectionUtils.java deleted file mode 100644 index bc5726a66..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/utils/ReflectionUtils.java +++ /dev/null @@ -1,52 +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.utils; - -import java.lang.reflect.Method; - -/** - * Utility methods for working with reflection. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class ReflectionUtils { - - /** - * Tests whether a method is overridden from the parent - * - * @param method The method to check - * @return True if it is - */ - public static boolean isMethodOverriddenFromParent(Method method) { - Class declaringClass = method.getDeclaringClass(); - - final Class superClass = declaringClass.getSuperclass(); - - if (superClass != null) { - try { - final Method superMethod = superClass.getMethod(method.getName(), method.getParameterTypes()); - if (superMethod != null) { - return true; - } - } catch (NoSuchMethodException e) { - // ignore - } - } - - return false; - } -} 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 deleted file mode 100644 index 735ce82f4..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/CascadingValidator.java +++ /dev/null @@ -1,39 +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.grails.datastore.gorm.validation; - -import org.springframework.validation.Errors; -import org.springframework.validation.Validator; - -/** - * 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 { - - /** - * An extended version of the validate(errors,obj) method that takes an additional argument specifying whether - * the Validator should cascade into associations or not. - * - * @param obj The Object to validate - * @param errors The Spring Errors instance - * @param cascade True if validation should cascade into associations - * - * @see org.springframework.validation.Errors - * @see org.springframework.validation.Validator - * @see org.springframework.validation.Validator#validate(Object, org.springframework.validation.Errors) - */ - void validate(Object obj, Errors errors, boolean cascade); -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/constraints/UniqueConstraint.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/constraints/UniqueConstraint.groovy deleted file mode 100644 index 864e4bc33..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/constraints/UniqueConstraint.groovy +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright (C) 2010 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.validation.constraints - -import grails.util.GrailsNameUtils - -import org.codehaus.groovy.grails.validation.AbstractConstraint -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.engine.EntityPersister -import org.springframework.validation.Errors - -/** - * Implementation of the unique constraint for the datastore abstraction. - */ -class UniqueConstraint extends AbstractConstraint { - - Datastore datastore - - UniqueConstraint(Datastore datastore) { - this.datastore = datastore - } - - @Override - protected void processValidate(Object target, Object propertyValue, Errors errors) { - withManualFlushMode { Session session -> - - EntityPersister persister = session.getPersister(target) - def id = getIdentifier(target, persister) - if (constraintParameter instanceof Boolean) { - if (constraintParameter) { - if (propertyValue != null) { - - final existing = constraintOwningClass."findBy${GrailsNameUtils.getClassName(constraintPropertyName, '')}"(propertyValue) - if (existing != null) { - def existingId = getIdentifier(existing, persister) - if (id != existingId) { - def args = [ constraintPropertyName, constraintOwningClass, propertyValue ] as Object[] - rejectValue(target, errors, "unique", args, getDefaultMessage("default.not.unique.message")) - } - } - } - } - } - else { - List group = [] - if (constraintParameter instanceof Collection) { - group.addAll(constraintParameter) - } - else if (constraintParameter != null) { - group.add(constraintParameter.toString()) - } - - def notIncludeNull = group.every { target[it] != null } - if (notIncludeNull) { - def existing = constraintOwningClass.createCriteria().get { - eq constraintPropertyName, propertyValue - for (prop in group) { - eq prop, target[prop] - } - } - if (existing) { - def existingId = getIdentifier(existing, persister) - if (id != existingId) { - def args = [constraintPropertyName, constraintOwningClass, propertyValue] as Object[] - rejectValue(target, errors, "unique", args, getDefaultMessage("default.not.unique.message")) - } - } - } - } - } - } - - private Serializable getIdentifier(target, EntityPersister persister) { - if (target == null) { - return - } - - if (persister == null) { - def entity = datastore.mappingContext.getPersistentEntity(target.class.name) - if (entity != null) { - return target[entity.identity.name] - } - } - else { - return persister.getObjectIdentifier(target) - } - } - - def withManualFlushMode(Closure callable) { - constraintOwningClass.withSession { Session session -> - final flushMode = session.getFlushMode() - - try { - session.setFlushMode(javax.persistence.FlushModeType.COMMIT) - callable.call(session) - } finally { - session.setFlushMode(flushMode) - } - } - } - - /** - * Return whether the constraint is valid for the owning class - * - * @return True if it is - */ - boolean isValid() { - final entity = datastore?.getMappingContext()?.getPersistentEntity(constraintOwningClass.name) - if (entity) { - return !entity.isExternal() - } - return false - } - - @Override - boolean supports(Class aClass) { true } - - @Override - String getName() { "unique" } -} diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/constraints/UniqueConstraintFactory.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/constraints/UniqueConstraintFactory.groovy deleted file mode 100644 index 6a73b2092..000000000 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/constraints/UniqueConstraintFactory.groovy +++ /dev/null @@ -1,22 +0,0 @@ -package org.grails.datastore.gorm.validation.constraints - -import org.codehaus.groovy.grails.validation.ConstraintFactory -import org.codehaus.groovy.grails.validation.Constraint -import org.grails.datastore.mapping.core.Datastore - -/** - * Factory for the unique constraint - */ -class UniqueConstraintFactory implements ConstraintFactory{ - - Datastore datastore - - UniqueConstraintFactory(Datastore datastore) { - this.datastore = datastore - } - - @Override - Constraint newInstance() { - return new UniqueConstraint(datastore) - } -} diff --git a/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/AbstractGormApiSpec.groovy b/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/AbstractGormApiSpec.groovy deleted file mode 100644 index b01db5a8c..000000000 --- a/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/AbstractGormApiSpec.groovy +++ /dev/null @@ -1,32 +0,0 @@ -package org.grails.datastore.gorm - -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.model.MappingContext - -import spock.lang.Specification - -/** - * @author graemerocher - */ -class AbstractGormApiSpec extends Specification { - - void "Test extended GORM API methods"() { - when: - def api = new TestGormStaticApi(AbstractGormApiSpec) - - then: - api.extendedMethods.size() == 1 - api.extendedMethods[0].name == 'myNewMethod' - } -} - -class TestGormStaticApi extends GormStaticApi { - - def myNewMethod() {} - - @Override D create() { super.create() } - - TestGormStaticApi(Class persistentClass) { - super(persistentClass, [getMappingContext: { -> [getPersistentEntity: { String name -> }] as MappingContext } ] as Datastore, []) - } -} diff --git a/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/dirty/checking/DirtyCheckTransformationSpec.groovy b/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/dirty/checking/DirtyCheckTransformationSpec.groovy deleted file mode 100644 index 38a87dd47..000000000 --- a/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/dirty/checking/DirtyCheckTransformationSpec.groovy +++ /dev/null @@ -1,91 +0,0 @@ -package org.grails.datastore.gorm.dirty.checking - -import grails.gorm.dirty.checking.DirtyCheck -import org.grails.datastore.mapping.dirty.checking.DirtyCheckable -import spock.lang.Specification - -/** - * @author Graeme Rocher - */ -class DirtyCheckTransformationSpec extends Specification { - - void "Test dirty check with generic types"() { - when:"A Dirty checkable class with generic types is parsed" - def gcl = new GroovyClassLoader() - Class cls = gcl.parseClass(''' -package org.grails.datastore.gorm.dirty.checking - -import grails.gorm.dirty.checking.DirtyCheck - -@DirtyCheck -class Author { - Set books -} - -''') - - then:"The generic types are retained" - cls.getMethod("getBooks").getReturnType().getGenericInterfaces() - } - - void "Test that the dirty checking transformations allows you to track changes to a class"() { - when:"A new dirty checking instance is created" - def b = new Book() - - then:"It implements the ChangeTrackable interface" - b instanceof DirtyCheckable - b.hasChanged() - b.hasChanged("title") - - when:"The title is changed" - b.title = "My Title" - - then:"No tracking started yet so return true by default" - b.hasChanged() - b.hasChanged("title") - - when:"We start tracking and change the title" - b.trackChanges() - - then:"If no changes a present then hasChanges returns false" - !b.hasChanged() - !b.hasChanged("title") - - when:"The a property is changed" - b.title = "Changed" - - then:"The changes are tracked" - b.hasChanged() - b.hasChanged("title") - b.getOriginalValue('title') == "My Title" - b.listDirtyPropertyNames() == ['title'] - !b.hasChanged("author") - - when:"A property with a getter and setter is changed" - b.title = "Some other value" - b.author = "Some Bloke" - - then:"We track that change too" - b.hasChanged("title") - b.getOriginalValue('title') == "My Title" - b.listDirtyPropertyNames() == ['title', 'author'] - b.hasChanged("author") - - } -} - -@DirtyCheck -class Book { - String title - Date releaseDate - - private String author - - void setAuthor(String author) { - this.author = author - } - String getAuthor() { - return this.author - } -} - diff --git a/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/support/BeforeValidateHelperTests.groovy b/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/support/BeforeValidateHelperTests.groovy deleted file mode 100644 index b48d204de..000000000 --- a/grails-datastore-gorm/src/test/groovy/org/grails/datastore/gorm/support/BeforeValidateHelperTests.groovy +++ /dev/null @@ -1,76 +0,0 @@ -package org.grails.datastore.gorm.support - -class BeforeValidateHelperTests extends GroovyTestCase { - - def beforeValidateHelper - - void setUp() { - super.setUp() - beforeValidateHelper = new BeforeValidateHelper() - } - - void testNoArgBeforeValidate() { - def obj = new ClassWithNoArgBeforeValidate() - assertEquals 'wrong initial counter value', 0, obj.noArgCounter - beforeValidateHelper.invokeBeforeValidate(obj, null) - assertEquals 'wrong counter value', 1, obj.noArgCounter - beforeValidateHelper.invokeBeforeValidate(obj, []) - assertEquals 'wrong counter value', 2, obj.noArgCounter - beforeValidateHelper.invokeBeforeValidate(obj, ['name', 'age', 'town']) - assertEquals 'wrong counter value', 3, obj.noArgCounter - } - - void testListArgBeforeValidate() { - def obj = new ClassWithListArgBeforeValidate() - assertEquals 'wrong initial counter value', 0, obj.listArgCounter - beforeValidateHelper.invokeBeforeValidate(obj, null) - assertEquals 'wrong counter value', 1, obj.listArgCounter - beforeValidateHelper.invokeBeforeValidate(obj, []) - assertEquals 'wrong counter value', 2, obj.listArgCounter - beforeValidateHelper.invokeBeforeValidate(obj, ['name', 'age', 'town']) - assertEquals 'wrong counter value', 3, obj.listArgCounter - } - - void testOverloadedBeforeValidate() { - def obj = new ClassWithOverloadedBeforeValidate() - assertEquals 'wrong initial list arg counter value', 0, obj.listArgCounter - assertEquals 'wrong initial no arg counter value', 0, obj.noArgCounter - - beforeValidateHelper.invokeBeforeValidate(obj, null) - assertEquals 'wrong list arg counter value', 0, obj.listArgCounter - assertEquals 'wrong no arg counter value', 1, obj.noArgCounter - - beforeValidateHelper.invokeBeforeValidate(obj, []) - assertEquals 'wrong list arg counter value', 1, obj.listArgCounter - assertEquals 'wrong no arg counter value', 1, obj.noArgCounter - - beforeValidateHelper.invokeBeforeValidate(obj, ['name', 'age', 'town']) - assertEquals 'wrong list arg counter value', 2, obj.listArgCounter - assertEquals 'wrong no arg counter value', 1, obj.noArgCounter - } -} - -class ClassWithNoArgBeforeValidate { - def noArgCounter = 0 - def beforeValidate() { - ++noArgCounter - } -} - -class ClassWithListArgBeforeValidate { - def listArgCounter = 0 - def beforeValidate(List properties) { - ++listArgCounter - } -} - -class ClassWithOverloadedBeforeValidate { - def noArgCounter = 0 - def listArgCounter = 0 - def beforeValidate() { - ++noArgCounter - } - def beforeValidate(List properties) { - ++listArgCounter - } -} diff --git a/grails-datastore-gorm/src/test/resources/cassandra-conf/log4j.properties b/grails-datastore-gorm/src/test/resources/cassandra-conf/log4j.properties deleted file mode 100644 index 013ca5387..000000000 --- a/grails-datastore-gorm/src/test/resources/cassandra-conf/log4j.properties +++ /dev/null @@ -1,27 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -# for production, you should probably set the root to INFO -# and the pattern to %c instead of %l. (%l is slower.) - -# output messages into a rolling log file as well as stdout -log4j.rootLogger=DEBUG,stdout - -# stdout -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%5p %d{HH:mm:ss,SSS} %m%n - diff --git a/grails-datastore-gorm/src/test/resources/cassandra-conf/storage-conf.xml b/grails-datastore-gorm/src/test/resources/cassandra-conf/storage-conf.xml deleted file mode 100644 index ec8c72697..000000000 --- a/grails-datastore-gorm/src/test/resources/cassandra-conf/storage-conf.xml +++ /dev/null @@ -1,395 +0,0 @@ - - - - - - - - Test Cluster - - - false - - - true - - - - - - - - - - - - - - - org.apache.cassandra.locator.RackUnawareStrategy - - - 1 - - - org.apache.cassandra.locator.EndPointSnitch - - - - - - org.apache.cassandra.auth.AllowAllAuthenticator - - - org.apache.cassandra.dht.RandomPartitioner - - - - - - build/commitlog - - build/data - - - - - - 127.0.0.1 - - - - - - - 10000 - - - - 128 - - - - - - localhost - - 7000 - - - localhost - - 9160 - - false - - - - - - - - auto - - - 512 - - - 64 - - - 32 - 8 - - - 64 - - - 64 - - 256 - - 0.3 - - 60 - - - 8 - 32 - - - periodic - - 10000 - - - - - 864000 - diff --git a/grails-datastore-jcr/build.gradle b/grails-datastore-jcr/build.gradle deleted file mode 100644 index 82ad3e3f7..000000000 --- a/grails-datastore-jcr/build.gradle +++ /dev/null @@ -1,17 +0,0 @@ -dependencies { - compile project(":grails-datastore-core") - compile 'javax.jcr:jcr:1.0' - compile 'org.springframework:se-jcr:1.0-SNAPSHOT' - compile 'org.apache.jackrabbit:jackrabbit-core:1.6.2' - compile 'org.apache.jackrabbit:jackrabbit-api:1.6.2' - compile 'org.apache.jackrabbit:jackrabbit-jcr-commons:1.6.2' - compile 'org.apache.jackrabbit:jackrabbit-spi-commons:1.6.2' - compile 'org.slf4j:slf4j-simple:1.5.8' - - // compile 'org.apache.jackrabbit:jackrabbit-ocm:1.5.3' - - //TODO: add commons-collections, concurrent, derby, jackrabbit-text, lucence core - //TODO: also add dependency libraries for spring-extensions including spring-webmvc, servlet api - - testCompile 'junit:junit:4.8.2' -} diff --git a/grails-datastore-jcr/repository.xml b/grails-datastore-jcr/repository.xml deleted file mode 100644 index 666919d28..000000000 --- a/grails-datastore-jcr/repository.xml +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/JcrDatastore.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/JcrDatastore.java deleted file mode 100644 index 363a2d14d..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/JcrDatastore.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.grails.datastore.mapping.jcr; - -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.SimpleCredentials; - -import org.apache.jackrabbit.core.TransientRepository; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.dao.DataAccessResourceFailureException; -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.node.mapping.NodeMappingContext; -import org.springframework.extensions.jcr.JcrSessionFactory; - -/** - * @author Erawat Chamanont - * @since 1.0 - */ -public class JcrDatastore extends AbstractDatastore { - - private static String REPOSITORY_CONF = "classpath:repository.xml"; - private static String REPOSITORY_HOME = "/tmp/repo"; // TODO: must change the directory to root classpath - private static String DEFAULT_WORKSPACE = "default"; - private static String DEFAULT_USERNAME = "username"; - private static String DEFAULT_PASSWORD = "password"; - - public JcrDatastore(MappingContext mappingContext, ConfigurableApplicationContext ctx) { - super(mappingContext, null, ctx); - } - - public JcrDatastore(ConfigurableApplicationContext ctx) { - this(new NodeMappingContext(), ctx); - } - - @Override - protected Session createSession(@SuppressWarnings("hiding") Map connectionDetails) { - String workspace = null; - String username = null; - String password = null; - if (connectionDetails != null) { - if (connectionDetails.get("configuration") != null) { - System.setProperty("org.apache.jackrabbit.repository.conf", - connectionDetails.get("configuration")); - } - else { - System.setProperty("org.apache.jackrabbit.repository.conf", REPOSITORY_CONF); - } - if (connectionDetails.get("homeDir") != null) { - System.setProperty("org.apache.jackrabbit.repository.home", - connectionDetails.get("homeDir")); - } - else { - System.setProperty("org.apache.jackrabbit.repository.home", REPOSITORY_HOME); - } - workspace = connectionDetails.get("workspace"); - username = connectionDetails.get("username"); - password = connectionDetails.get("password"); - } - else { - System.setProperty("org.apache.jackrabbit.repository.conf", REPOSITORY_CONF); - System.setProperty("org.apache.jackrabbit.repository.home", REPOSITORY_HOME); - workspace = DEFAULT_WORKSPACE; - username = DEFAULT_USERNAME; - password = DEFAULT_PASSWORD; - } - Repository repository = null; - JcrSessionFactory jcrSessionFactory = null; - try { - repository = new TransientRepository(); - jcrSessionFactory = new JcrSessionFactory(repository, workspace, - new SimpleCredentials(username, password.toCharArray())); - jcrSessionFactory.afterPropertiesSet(); - } - catch (Exception e) { - throw new DataAccessResourceFailureException( - "Exception occurred cannot create Session: " + e.getMessage(), e); - } - return new JcrSession(this, getMappingContext(), jcrSessionFactory, getApplicationEventPublisher()); - } -} diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/JcrSession.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/JcrSession.java deleted file mode 100644 index 7e038e3ec..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/JcrSession.java +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright (C) 2010 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.mapping.jcr; - -import java.io.Serializable; -import java.util.Date; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.jackrabbit.core.TransientRepository; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.core.convert.converter.Converter; -import org.springframework.dao.CannotAcquireLockException; -import org.springframework.dao.DataAccessResourceFailureException; -import org.grails.datastore.mapping.core.AbstractSession; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.LockableEntityPersister; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.jcr.engine.JcrEntityPersister; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.transactions.Transaction; -import org.springframework.extensions.jcr.JcrSessionFactory; -import org.springframework.extensions.jcr.JcrTemplate; -import org.springframework.extensions.jcr.support.OpenSessionInViewInterceptor; - -/** - * @author Erawat Chamanont - * @since 1.0 - */ -public class JcrSession extends AbstractSession { - - protected OpenSessionInViewInterceptor interceptor = new OpenSessionInViewInterceptor(); - - private JcrSessionFactory jcrSessionFactory; - - public JcrSession(Datastore ds, MappingContext mappingContext, JcrSessionFactory jcrSessionFactory, - ApplicationEventPublisher publisher) { - super(ds, mappingContext, publisher); - mappingContext.addTypeConverter(new LongToDateConverter()); - this.jcrSessionFactory = jcrSessionFactory; - interceptor.setSessionFactory(jcrSessionFactory); - interceptor.preHandle(null, null, null); - } - - @Override - protected Persister createPersister(Class cls, MappingContext mappingContext) { - PersistentEntity entity = mappingContext.getPersistentEntity(cls.getName()); - if (entity == null) { - return null; - } - return new JcrEntityPersister(mappingContext, entity, this, - new JcrTemplate(jcrSessionFactory), publisher); - } - - @Override - public void disconnect() { -// interceptor.afterCompletion(null, null, null, null); - try { - ((TransientRepository) jcrSessionFactory.getRepository()).shutdown(); - super.disconnect(); - } catch (Exception e) { - throw new DataAccessResourceFailureException("Failed to disconnect JCR Repository: " + e.getMessage(), e); - } finally { - super.disconnect(); - } - } - - @Override - public boolean isConnected() { - try { - return jcrSessionFactory.getSession().isLive(); - } catch (RepositoryException e) { - throw new DataAccessResourceFailureException("Repository Errors: " + e.getMessage(), e); - } - } - - @Override - protected Transaction beginTransactionInternal() { - return new JcrTransaction(jcrSessionFactory); - } - - public Session getNativeInterface() { - try { - return jcrSessionFactory.getSession(); - } catch (RepositoryException e) { - throw new DataAccessResourceFailureException("Session not found: " + e.getMessage(), e); - } - } - - @Override - public void lock(Object o) { - LockableEntityPersister ep = (LockableEntityPersister) getPersister(o); - if (ep == null) { - throw new CannotAcquireLockException("Cannot lock object [" + o + - "]. It is not a persistent instance!"); - } - - Serializable id = ep.getObjectIdentifier(o); - if (id == null) { - throw new CannotAcquireLockException("Cannot lock transient instance [" + o + "]"); - } - - ep.lock(id); - } - - @Override - public void unlock(Object o) { - if (o == null) { - return; - } - - LockableEntityPersister ep = (LockableEntityPersister) getPersister(o); - if (ep == null) { - return; - } - - ep.unlock(o); - lockedObjects.remove(o); - } - - @Override - public Object lock(Class type, Serializable key) { - LockableEntityPersister ep = (LockableEntityPersister) getPersister(type); - if (ep == null) { - throw new CannotAcquireLockException("Cannot lock key [" + key + - "]. It is not a persistent instance!"); - } - - final Object lockedObject = ep.lock(key); - if (lockedObject != null) { - cacheObject(key, lockedObject); - lockedObjects.add(lockedObject); - } - return lockedObject; - } - - protected class LongToDateConverter implements Converter { - public Date convert(Long number) { - return new Date(number); - } - } -} diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/JcrTransaction.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/JcrTransaction.java deleted file mode 100644 index bf0c8c7fa..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/JcrTransaction.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.grails.datastore.mapping.jcr; - -import org.grails.datastore.mapping.transactions.Transaction; -import org.springframework.extensions.jcr.JcrSessionFactory; -import org.springframework.extensions.jcr.jackrabbit.support.UserTxSessionHolder; -import org.springframework.transaction.IllegalTransactionStateException; -import org.springframework.transaction.TransactionSystemException; -import org.springframework.transaction.UnexpectedRollbackException; - -/** - * @author Erawat Chamanont - * @since 1.0 - */ -public class JcrTransaction implements Transaction { - private UserTxSessionHolder transaction; - private boolean rollbackCalled; - private boolean commitCalled; - - public JcrTransaction(JcrSessionFactory sessionFactory) { - try { - transaction = new UserTxSessionHolder(sessionFactory.getSession()); - transaction.getTransaction().begin(); - } - catch (Exception e) { - throw new TransactionSystemException("Exception occurred beginning JackRabbit transaction: " + e.getMessage()); - } - } - - public void commit() { - if (rollbackCalled) { - throw new IllegalTransactionStateException( - "Cannot call commit after rollback. Start another transaction first!"); - } - try { - transaction.getTransaction().commit(); - commitCalled = true; - } - catch (Exception e) { - throw new TransactionSystemException( - "Exception occurred committing back JackRabbit transaction: " + e.getMessage()); - } - } - - public boolean isActive() { - return !commitCalled && !rollbackCalled; - } - - public void setTimeout(int timeout) { - try { - transaction.getTransaction().setTransactionTimeout(timeout); - } - catch (Exception e) { - throw new TransactionSystemException( - "Exception occurred setting timeout JackRabbit transaction: " + e.getMessage()); - } - } - - public void rollback() { - if (rollbackCalled) { - throw new UnexpectedRollbackException( - "Cannot rollback JackRabbit transaction. Transaction already rolled back!"); - } - try { - transaction.getTransaction().rollback(); - rollbackCalled = true; - } - catch (Exception e) { - throw new TransactionSystemException( - "Exception occurred rolling back JackRabbit transaction: " + e.getMessage()); - } - } - - public UserTxSessionHolder getNativeTransaction() { - return transaction; - } -} \ No newline at end of file diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/engine/JcrEntityPersister.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/engine/JcrEntityPersister.java deleted file mode 100644 index dfe22b632..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/engine/JcrEntityPersister.java +++ /dev/null @@ -1,262 +0,0 @@ -package org.grails.datastore.mapping.jcr.engine; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; -import java.util.Calendar; -import java.util.Date; -import java.util.List; - -import javax.jcr.ItemNotFoundException; -import javax.jcr.Node; -import javax.jcr.PathNotFoundException; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; - -import org.springframework.beans.SimpleTypeConverter; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.dao.DataRetrievalFailureException; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.jcr.JcrSession; -import org.grails.datastore.mapping.jcr.util.JcrConstants; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.node.engine.AbstractNodeEntityPersister; -import org.grails.datastore.mapping.query.JcrQuery; -import org.springframework.extensions.jcr.JcrCallback; -import org.springframework.extensions.jcr.JcrTemplate; - -/** - * TODO: write javadoc - * - * @author Erawat Chamanont - * @since 1.0 - */ -public class JcrEntityPersister extends AbstractNodeEntityPersister { - - private JcrTemplate jcrTemplate; - private SimpleTypeConverter typeConverter; - - public JcrEntityPersister(MappingContext context, PersistentEntity entity, Session session, - JcrTemplate jcrTemplate, ApplicationEventPublisher publisher) { - super(context, entity, session, publisher); - typeConverter = new SimpleTypeConverter(); - this.jcrTemplate = jcrTemplate; - this.jcrTemplate.setAllowCreate(true); - } - - public JcrEntityPersister(MappingContext mappingContext, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher) { - super(mappingContext, entity, session, publisher); - } - - /** - * @param persistentEntity The PesistentEntity instnace - * @param id The identifer - * @param timeout The lock timeout in seconds - */ - @Override - protected void lockEntry(PersistentEntity persistentEntity, Serializable id, int timeout) { - //TODO: Implement lock timeout - Node node = jcrTemplate.getNodeByUUID(getString(id)); - try { - node.lock(true, true); - } catch (RepositoryException e) { - throw new DataAccessResourceFailureException("Exception occurred cannot lock entity: " + e.getMessage(), e); - } - } - - /** - * @param o The object - * @return True if the object is locked - */ - @Override - public boolean isLocked(Object o) { - String uuid = getString(createEntityAccess(getPersistentEntity(), o).getIdentifier()); - if (uuid == null) return false; - Node node = jcrTemplate.getNodeByUUID(uuid); - try { - return node.isLocked(); - } catch (RepositoryException e) { - throw new DataAccessResourceFailureException("Exception occurred cannot unlock entity: " + e.getMessage(), e); - } - } - - /** - * @param persistentEntity The persistent entity - * @param id The identifer - */ - @Override - protected void unlockEntry(PersistentEntity persistentEntity, Serializable id) { - Node node = jcrTemplate.getNodeByUUID(getString(id)); - try { - node.unlock(); - } catch (RepositoryException e) { - throw new DataAccessResourceFailureException("Exception occurred cannot unlock entity: " + e.getMessage(), e); - } - } - - @Override - protected String generateIdentifier(PersistentEntity persistentEntity, Node tmp) { - try { - return tmp.getUUID(); - } catch (RepositoryException e) { - throw new DataAccessResourceFailureException("Exception occurred cannot generateIdentifier by getting UUID from Node: " + e.getMessage(), e); - } - } - - @Override - protected void deleteEntry(final String key) { - Node node = jcrTemplate.getNodeByUUID(key); - try { - node.remove(); - jcrTemplate.save(); - } catch (RepositoryException e) { - throw new DataAccessResourceFailureException("Exception occurred cannot delete Node: " + e.getMessage(), e); - } - } - - @Override - protected Object getEntryValue(Node nativeEntry, String property) { - try { - Property prop = nativeEntry.getProperty(property); - if (prop.getType() == PropertyType.REFERENCE) { - String nodeUUID = prop.getString(); - return jcrTemplate.getNodeByUUID(nodeUUID); - } - switch (prop.getType()) { - case PropertyType.BINARY: - // TODO - add lazyinputstream - return prop.getString(); - case PropertyType.BOOLEAN: - return prop.getBoolean(); - case PropertyType.DATE: - return prop.getDate(); - case PropertyType.DOUBLE: - return prop.getDouble(); - case PropertyType.LONG: - return prop.getLong(); - case PropertyType.NAME: // fall through - case PropertyType.PATH: // fall through - case PropertyType.REFERENCE: // fall through - case PropertyType.STRING: // fall through - case PropertyType.UNDEFINED: // not actually expected - default: // not actually expected - return prop.getString(); - } - } catch(PathNotFoundException e) { - return null; - } catch (Exception e) { - throw new DataRetrievalFailureException("Exception occurred cannot getProperty from Node: " + e.getMessage(), e); - } - } - - @Override - protected Node retrieveEntry(final PersistentEntity persistentEntity, final Serializable key) { - if (key == null) { - return null; - } - - return (Node) jcrTemplate.execute(new JcrCallback() { - public Object doInJcr(javax.jcr.Session s) throws IOException, RepositoryException { - try { - return s.getNodeByUUID(getString(key)); - } catch (ItemNotFoundException ex) { - //Force to return null when ItemNotFoundException occurred - return null; - } - } - }); - } - - private String getString(Object key) { - return typeConverter.convertIfNecessary(key, String.class); - } - - private Long getLong(Object value) { - return typeConverter.convertIfNecessary(value, Long.class); - } - - @Override - protected Node createNewEntry(final PersistentEntity persistentEntity) { - try { - Node rootNode = jcrTemplate.getRootNode(); - Node node = rootNode.addNode(persistentEntity.getJavaClass().getSimpleName(), JcrConstants.DEFAULT_JCR_TYPE); - node.addMixin(JcrConstants.MIXIN_REFERENCEABLE); - node.addMixin(JcrConstants.MIXIN_VERSIONABLE); - node.addMixin(JcrConstants.MIXIN_LOCKABLE); - return node; - } catch (RepositoryException e) { - throw new DataAccessResourceFailureException("Exception occurred cannot create Node: " + e.getMessage(), e); - } - } - - @Override - protected void setEntryValue(Node nativeEntry, String propertyName, Object value) { - //Possible property should be only String, Boolean, Calendar, Double, InputStream and Long - if (value != null) { - try { - if (value instanceof String) - nativeEntry.setProperty(propertyName, (String) value); - else if (value instanceof Boolean) - nativeEntry.setProperty(propertyName, (Boolean) value); - else if (value instanceof Calendar) { - nativeEntry.setProperty(propertyName, (Calendar) value); - }else if (value instanceof Double) - nativeEntry.setProperty(propertyName, (Double) value); - else if (value instanceof InputStream) - nativeEntry.setProperty(propertyName, (InputStream) value); - else if (value instanceof Long) - nativeEntry.setProperty(propertyName, getLong(value)); - else if (value instanceof Integer) - nativeEntry.setProperty(propertyName, getLong(value)); - else if (value instanceof Date) { - //TODO: Solve date type problem. - nativeEntry.setProperty(propertyName, ((Date)value).getTime()); - }else{ - //Marshaling all unsupported data types into String - value = value.toString(); - nativeEntry.setProperty(propertyName, (String)value); - } - } catch (RepositoryException e) { - throw new DataAccessResourceFailureException("Exception occurred set a property value to Node: " + e.getMessage(), e); - } - } - } - - @Override - protected String storeEntry(PersistentEntity persistentEntity, String id, Node nativeEntry) { - jcrTemplate.save(); - return id; - } - - @Override - protected void updateEntry(final PersistentEntity persistentEntity, final String id, final Node entry) { - if (id != null) { - List propNames = persistentEntity.getPersistentPropertyNames(); - Node node = jcrTemplate.getNodeByUUID(id); - try { - node.checkout(); - for (String propName : propNames) { - if (node.hasProperty(propName)) { - node.setProperty(propName, entry.getProperty(propName).getValue()); - } - } - node.save(); - node.checkin(); - } catch (RepositoryException e) { - throw new DataAccessResourceFailureException("Exception occurred when updating Node: " + e.getMessage(), e); - } - } - } - - public org.grails.datastore.mapping.query.Query createQuery() { - return new JcrQuery((JcrSession) getSession(), getJcrTemplate(), getPersistentEntity(), this); - } - - public JcrTemplate getJcrTemplate() { - return jcrTemplate; - } -} diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/util/JcrConstants.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/util/JcrConstants.java deleted file mode 100644 index 955989291..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/jcr/util/JcrConstants.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.grails.datastore.mapping.jcr.util; - -/** - * @author Erawat Chamanont - * @since 1.0 - */ -public interface JcrConstants { - String DEFAULT_JCR_TYPE = "nt:unstructured"; - String MIXIN_REFERENCEABLE = "mix:referenceable"; - String MIXIN_VERSIONABLE = "mix:versionable"; - String MIXIN_LOCKABLE = "mix:lockable"; -} diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/engine/AbstractNodeEntityPersister.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/engine/AbstractNodeEntityPersister.java deleted file mode 100644 index 2d6451f2a..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/engine/AbstractNodeEntityPersister.java +++ /dev/null @@ -1,612 +0,0 @@ -package org.grails.datastore.mapping.node.engine; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.persistence.CascadeType; - -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.dao.CannotAcquireLockException; -import org.springframework.dao.DataIntegrityViolationException; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.core.SessionImplementor; -import org.grails.datastore.mapping.core.impl.PendingInsert; -import org.grails.datastore.mapping.core.impl.PendingInsertAdapter; -import org.grails.datastore.mapping.core.impl.PendingOperation; -import org.grails.datastore.mapping.core.impl.PendingOperationAdapter; -import org.grails.datastore.mapping.core.impl.PendingOperationExecution; -import org.grails.datastore.mapping.core.impl.PendingUpdate; -import org.grails.datastore.mapping.core.impl.PendingUpdateAdapter; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.LockableEntityPersister; -import org.grails.datastore.mapping.engine.event.PreDeleteEvent; -import org.grails.datastore.mapping.model.ClassMapping; -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.PropertyMapping; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.model.types.OneToMany; -import org.grails.datastore.mapping.model.types.Simple; -import org.grails.datastore.mapping.model.types.ToOne; -import org.grails.datastore.mapping.node.mapping.Node; -import org.grails.datastore.mapping.node.mapping.NodeProperty; -import org.grails.datastore.mapping.proxy.ProxyFactory; - -/** - * Abstract implementation of the EntityPersister abstract class - * for Node style stores - * - * @author Erawat Chamanont - * @since 1.0 - */ -@SuppressWarnings("unused") -public abstract class AbstractNodeEntityPersister extends LockableEntityPersister { - protected String nodeEntity; - protected Session session; - protected ClassMapping classMapping; - - public AbstractNodeEntityPersister(MappingContext mappingContext, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher) { - super(mappingContext, entity, session, publisher); - this.session = session; - this.classMapping = entity.getMapping(); - this.nodeEntity = getEntity(entity, classMapping); - } - - public String getNodeEntity() { - return nodeEntity; - } - - public void setNodeEntity(String nodeEntity) { - this.nodeEntity = nodeEntity; - } - - protected String getEntity(PersistentEntity persistentEntity, ClassMapping cm) { - String enName = null; - if (cm.getMappedForm() != null) { - enName = cm.getMappedForm().getEntityName(); - } - if (enName == null) enName = persistentEntity.getJavaClass().getSimpleName(); - return enName; - } - - @Override - protected List retrieveAllEntities(PersistentEntity persistentEntity, Serializable[] keys) { - List results = new ArrayList(); - for (Serializable key : keys) { - results.add(retrieveEntity(persistentEntity, key)); - } - return results; - } - - @Override - protected List retrieveAllEntities(PersistentEntity persistentEntity, Iterable keys) { - List results = new ArrayList(); - for (Serializable key : keys) { - results.add(retrieveEntity(persistentEntity, key)); - } - return results; - } - - /** - * This is a rather simplistic and unoptimized implementation. Subclasses can override to provide - * batch insert capabilities to optimize the insertion of multiple entities in one go - * - * @param persistentEntity The persistent entity - * @param objs The objects to persist - * @return A list of keys - */ - @Override - protected List persistEntities(PersistentEntity persistentEntity, Iterable objs) { - List keys = new ArrayList(); - for (Object obj : objs) { - keys.add(persist(obj)); - } - return keys; - } - - @Override - protected Object retrieveEntity(PersistentEntity persistentEntity, Serializable key) { - T nativeEntry = retrieveEntry(persistentEntity, key); - if (nativeEntry != null) { - return createObjectFromNativeEntry(persistentEntity, key, nativeEntry); - } - return null; - } - - protected Object createObjectFromNativeEntry(PersistentEntity persistentEntity, Serializable nativeKey, T nativeEntry) { - Object obj = newEntityInstance(persistentEntity); - refreshObjectStateFromNativeEntry(persistentEntity, obj, nativeKey, nativeEntry); - return obj; - } - - protected void refreshObjectStateFromNativeEntry(PersistentEntity persistentEntity, Object obj, Serializable nativeKey, T nativeEntry) { - EntityAccess ea = new EntityAccess(persistentEntity, obj); - ea.setConversionService(getMappingContext().getConversionService()); - String idName = ea.getIdentifierName(); - ea.setProperty(idName, nativeKey); - - final List props = persistentEntity.getPersistentProperties(); - for (final PersistentProperty prop : props) { - PropertyMapping pm = prop.getMapping(); - String propKey = null; - if (pm.getMappedForm() != null) { - propKey = pm.getMappedForm().getName(); - } - if (propKey == null) { - propKey = prop.getName(); - } - if (prop instanceof Simple) { - ea.setProperty(prop.getName(), getEntryValue(nativeEntry, propKey)); - } else if (prop instanceof ToOne) { - Serializable tmp = (Serializable) getEntryValue(nativeEntry, propKey); - PersistentEntity associatedEntity = prop.getOwner(); - final Serializable associationKey = (Serializable) getMappingContext().getConversionService().convert(tmp, associatedEntity.getIdentity().getType()); - if (associationKey != null) { - PropertyMapping associationPropertyMapping = prop.getMapping(); - //boolean isLazy = isLazyAssociation(associationPropertyMapping); - final Class propType = prop.getType(); - //if (isLazy) { - // Object proxy = getProxyFactory().createProxy(session, propType, associationKey); - // ea.setProperty(prop.getName(), proxy); - //} else { - ea.setProperty(prop.getName(), session.retrieve(propType, associationKey)); - //} - } - } else if (prop instanceof OneToMany) { - Association association = (Association) prop; - PropertyMapping associationPropertyMapping = association.getMapping(); - //boolean isLazy = isLazyAssociation(associationPropertyMapping); - //AssociationIndexer indexer = getAssociationIndexer(association); - nativeKey = (Serializable) getMappingContext().getConversionService().convert(nativeKey, getPersistentEntity().getIdentity().getType()); - //if (isLazy) { - // if (List.class.isAssignableFrom(association.getType())) { - // ea.setPropertyNoConversion(association.getName(), new PersistentList(nativeKey, session)); - // } else if (Set.class.isAssignableFrom(association.getType())) { - // ea.setPropertyNoConversion(association.getName(), new PersistentSet(nativeKey, session, indexer)); - // } - // } else { - //if (indexer != null) { - // List keys = indexer.query(nativeKey); - ea.setProperty(association.getName(), session.retrieveAll(association.getAssociatedEntity().getJavaClass(), nativeKey)); - // } - //} - } - } - } - - /*private boolean isLazyAssociation(PropertyMapping associationPropertyMapping) { - if (associationPropertyMapping != null) { - NodeProperty np = associationPropertyMapping.getMappedForm(); - if (np.getFetchStrategy() != FetchType.LAZY) { - return false; - } - } - return true; - }*/ - - - @Override - protected Serializable persistEntity(final PersistentEntity persistentEntity, Object obj) { - ClassMapping cm = persistentEntity.getMapping(); - T tmp = null; - final EntityAccess entityAccess = new EntityAccess(persistentEntity, obj); - K k = readObjectIdentifier(entityAccess, cm); - boolean isUpdate = k != null; - /* if (!isUpdate) { - tmp = createNewEntry(persistentEntity); - k = generateIdentifier(persistentEntity, tmp); - String id = entityAccess.getIdentifierName(); - entityAccess.setProperty(id, k); - } else { - SessionImplementor si = (SessionImplementor) session; - tmp = si.getCachedEntry(persistentEntity, (Serializable) k); - if (tmp == null) { - tmp = retrieveEntry(persistentEntity, (Serializable) k); - } - if (tmp == null) { - tmp = createNewEntry(persistentEntity); - } - }*/ - - PendingOperation pendingOperation; - - SessionImplementor si = (SessionImplementor) session; - if (!isUpdate) { - tmp = createNewEntry(persistentEntity); - k = generateIdentifier(persistentEntity, tmp); - - pendingOperation = new PendingInsertAdapter(persistentEntity, k, tmp, entityAccess) { - public void run() { - executeInsert(persistentEntity, entityAccess, getNativeKey(), getNativeEntry()); - } - }; - - String id = entityAccess.getIdentifierName(); - entityAccess.setProperty(id, k); - } - else { - tmp = (T) si.getCachedEntry(persistentEntity, (Serializable) k); - if (tmp == null) { - tmp = retrieveEntry(persistentEntity, (Serializable) k); - } - if (tmp == null) { - tmp = createNewEntry(persistentEntity); - } - - pendingOperation = new PendingUpdateAdapter(persistentEntity, k, tmp, entityAccess) { - public void run() { - if (cancelUpdate(persistentEntity, entityAccess)) return; - updateEntry(persistentEntity, getNativeKey(), getNativeEntry()); - firePostUpdateEvent(persistentEntity, entityAccess); - } - }; - } - - final T e = tmp; - - final List props = persistentEntity.getPersistentProperties(); - final Map> oneToManyKeys = new HashMap>(); - final Map inverseCollectionUpdates = new HashMap(); - // final Map toIndex = new HashMap(); - //final Map toUnindex = new HashMap(); - for (PersistentProperty prop : props) { - PropertyMapping pm = prop.getMapping(); - final NodeProperty nodeProperty = pm.getMappedForm(); - String propName = null; - if (nodeProperty != null) { - propName = nodeProperty.getName(); - } - //final boolean indexed = nodeProperty != null && nodeProperty.isIndex(); - if (propName == null) propName = prop.getName(); - //Single Entity - if (prop instanceof Simple) { - Object propValue = entityAccess.getProperty(prop.getName()); - /* if (indexed) { - if (isUpdate) { - final Object oldValue = getEntryValue(e, propName); - if (oldValue != null && !oldValue.equals(propValue)) - toUnindex.put(prop, oldValue); - } - - toIndex.put(prop, propValue); - }*/ - setEntryValue(e, propName, propValue); - } else if (prop instanceof OneToMany) { - final OneToMany oneToMany = (OneToMany) prop; - - Object propValue = entityAccess.getProperty(oneToMany.getName()); - - if (propValue instanceof Collection) { - Collection associatedObjects = (Collection) propValue; - List keys = session.persist(associatedObjects); - - oneToManyKeys.put(oneToMany, keys); - } - } else if (prop instanceof ToOne) { - ToOne association = (ToOne) prop; - if (association.doesCascade(CascadeType.PERSIST)) { - - if (!association.isForeignKeyInChild()) { - - final Object associatedObject = entityAccess.getProperty(prop.getName()); - if (associatedObject != null) { - @SuppressWarnings("hiding") ProxyFactory proxyFactory = getProxyFactory(); - // never cascade to proxies - if (!proxyFactory.isProxy(associatedObject)) { - Serializable associationId; - AbstractNodeEntityPersister associationPersister = (AbstractNodeEntityPersister) session.getPersister(associatedObject); - if (!session.contains(associatedObject)) { - Serializable tempId = associationPersister.getObjectIdentifier(associatedObject); - if (tempId == null) tempId = session.persist(associatedObject); - associationId = tempId; - } else { - associationId = associationPersister.getObjectIdentifier(associatedObject); - } - /* if (indexed) { - toIndex.put(prop, associationId); - if (isUpdate) { - final Object oldValue = getEntryValue(e, propName); - if (oldValue != null && !oldValue.equals(associatedObject)) - toUnindex.put(prop, oldValue); - } - }*/ - setEntryValue(e, propName, associationId); - if (association.isBidirectional()) { - Association inverse = association.getInverseSide(); - if (inverse instanceof OneToMany) { - inverseCollectionUpdates.put((OneToMany) inverse, associationId); - } - } - } - } else { - if (!association.isNullable() && !association.isCircular()) { - throw new DataIntegrityViolationException("Cannot save object [" + entityAccess.getEntity() + "] of type [" + persistentEntity + "]. The association [" + association + "] is cannot be null."); - } - } - } - } - }// End - } - - if (!isUpdate) { - // if the identifier is null at this point that means that datastore could not generated an identifer - // and the identifer is generated only upon insert of the entity - - final K updateId = k; - PendingOperation postOperation = new PendingOperationAdapter(persistentEntity, k, e) { - public void run() { - if (cancelInsert(persistentEntity, entityAccess)) { - return; - } - storeEntry(persistentEntity, updateId, e); - firePostInsertEvent(persistentEntity, entityAccess); - for (OneToMany inverseCollection : inverseCollectionUpdates.keySet()) { - final Serializable primaryKey = inverseCollectionUpdates.get(inverseCollection); - final AbstractNodeEntityPersister inversePersister = (AbstractNodeEntityPersister) session.getPersister(inverseCollection.getOwner()); - //final AssociationIndexer associationIndexer = inversePersister.getAssociationIndexer(e, inverseCollection); - //associationIndexer.index(primaryKey, updateId ); - } - } - }; - - pendingOperation.addCascadeOperation(postOperation); - - // If the key is still at this point we have to execute the pending operation now to get the key - if (k == null) { - PendingOperationExecution.executePendingOperation(pendingOperation); - } - else { - si.addPendingInsert((PendingInsert) pendingOperation); - } - } - else { - final K updateId = k; - - PendingOperation postOperation = new PendingOperationAdapter(persistentEntity, k, e) { - public void run() { - // updateOneToManyIndices(e, updateId, oneToManyKeys); - // if (doesRequirePropertyIndexing()) - // updatePropertyIndices(updateId, toIndex, toUnindex); - - if (cancelUpdate(persistentEntity, entityAccess)) { - return; - } - - updateEntry(persistentEntity, updateId, e); - firePostUpdateEvent(persistentEntity, entityAccess); - } - - }; - pendingOperation.addCascadeOperation(postOperation); - si.addPendingUpdate((PendingUpdate) pendingOperation); - } - - /* if (!isUpdate) { - SessionImplementor si = (SessionImplementor) session; - final K updateId = k; - si.getPendingInserts().add(new Runnable() { - public void run() { - for (EntityInterceptor interceptor : interceptors) { - if (!interceptor.beforeInsert(persistentEntity, entityAccess)) return; - } - storeEntry(persistentEntity, updateId, e); - } - }); - } else { - SessionImplementor si = (SessionImplementor) session; - final K updateId = k; - si.getPendingUpdates().add(new Runnable() { - public void run() { - for (EntityInterceptor interceptor : interceptors) { - if (!interceptor.beforeUpdate(persistentEntity, entityAccess)) return; - } - updateEntry(persistentEntity, updateId, e); - } - }); - }*/ - return (Serializable) k; - } - - @Override - protected void deleteEntities(PersistentEntity persistentEntity, Iterable objects) { - } - - @Override - protected void deleteEntity(PersistentEntity persistentEntity, Object obj) { - if (obj == null) { - return; - } - - EntityAccess entityAccess = createEntityAccess(persistentEntity, obj); - PreDeleteEvent event = new PreDeleteEvent(session.getDatastore(), persistentEntity, - entityAccess); - publisher.publishEvent(event); - if (event.isCancelled()) { - return; - } - - final K key = readIdentifierFromObject(obj); - if (key == null) { - return; - } - - deleteEntry(key); - firePostDeleteEvent(persistentEntity, entityAccess); - } - - private K readIdentifierFromObject(Object object) { - EntityAccess access = new EntityAccess(getPersistentEntity(), object); - access.setConversionService(getMappingContext().getConversionService()); - final Object idValue = access.getIdentifier(); - K key = null; - if (idValue != null) { - key = inferNativeKey(idValue); - } - return key; - } - - @Override - public final Object lock(Serializable id) throws CannotAcquireLockException { - return lock(id, DEFAULT_TIMEOUT); - } - - @Override - public final Object lock(Serializable id, int timeout) throws CannotAcquireLockException { - lockEntry(getPersistentEntity(), id, timeout); - return retrieve(id); - } - - /** - * Subclasses can override to provide locking semantics - * - * @param persistentEntity The PesistentEntity instnace - * @param id The identifer - * @param timeout The lock timeout in seconds - */ - protected void lockEntry(PersistentEntity persistentEntity, Serializable id, int timeout) { - // do nothing, - } - - /** - * Subclasses can override to provide locking semantics - * - * @param o The object - * @return True if the object is locked - */ - @Override - public boolean isLocked(Object o) { - return false; - } - - @Override - public final void unlock(Object o) { - unlockEntry(getPersistentEntity(), (Serializable) createEntityAccess(getPersistentEntity(), o).getIdentifier()); - } - - /** - * Subclasses to override to provide locking semantics - * - * @param persistentEntity The persistent entity - * @param id The identifer - */ - protected void unlockEntry(PersistentEntity persistentEntity, Serializable id) { - // do nothing - } - - public Serializable refresh(Object o) { - final PersistentEntity entity = getPersistentEntity(); - EntityAccess ea = createEntityAccess(entity, o); - - Serializable identifier = (Serializable) ea.getIdentifier(); - if (identifier != null) { - final T entry = retrieveEntry(entity, identifier); - refreshObjectStateFromNativeEntry(entity, o, identifier, entry); - return identifier; - } - return null; - } - - protected K readObjectIdentifier(EntityAccess entityAccess, ClassMapping cm) { - return (K) entityAccess.getIdentifier(); - } - - protected abstract K generateIdentifier(PersistentEntity persistentEntity, T tmp); - - /** - * Used to establish the native key to use from the identifier defined by the object - * - * @param identifier The identifier specified by the object - * @return The native key which may just be a cast from the identifier parameter to K - */ - protected K inferNativeKey(Object identifier) { - return (K) identifier; - } - - /** - * Deletes a single entry - * - * @param key The identity - */ - protected abstract void deleteEntry(K key); - - /** - * Reads a value for the given key from the native entry - * - * @param nativeEntry The native entry. Could be a JCR Node etc. - * @param property The property key - * @return The value - */ - protected abstract Object getEntryValue(T nativeEntry, String property); - - /** - * Reads the native form of a Node datastore entry. This could be - * a JCR Node, a Graph Nodeetc. - * - * @param persistentEntity The persistent entity - * @param key The key - * @return The native form - */ - protected abstract T retrieveEntry(PersistentEntity persistentEntity, Serializable key); - - /** - * Creates a new entry for the given Node. - * - * @param persistentEntity persistentEntity The persistent entity - * @return An entry such as a JCR Node etc. - */ - protected abstract T createNewEntry(PersistentEntity persistentEntity); - - /** - * Sets a value on an entry - * - * @param nativeEntry The native entry such as a JCR Node etc. - * @param propertyName The Property Name - * @param value The value - */ - protected abstract void setEntryValue(T nativeEntry, String propertyName, Object value); - - /** - * Stores the native form of a Node style datastore to the actual data store - * - * @param persistentEntity The persistent entity - * @param id The id of the object to store - * @param nativeEntry The native form. Could be a a JCR Node,etc. - * @return The native identitys - */ - protected abstract K storeEntry(PersistentEntity persistentEntity, K id, T nativeEntry); - - /** - * Updates an existing entry to the actual datastore - * - * @param persistentEntity The PersistentEntity - * @param id The id of the object to update - * @param entry The entry - */ - protected abstract void updateEntry(PersistentEntity persistentEntity, K id, T entry); - - /** - * Executes an insert for the given entity, entity access, identifier and native entry. - * Any before interceptors will be triggered - * - * @param persistentEntity - * @param entityAccess - * @param id - * @param e - * @return The key - */ - protected K executeInsert(final PersistentEntity persistentEntity, - final EntityAccess entityAccess, - final K id, final T e) { - if (cancelInsert(persistentEntity, entityAccess)) return null; - final K newId = storeEntry(persistentEntity, id, e); - entityAccess.setIdentifier(newId); - firePostInsertEvent(persistentEntity, entityAccess); - return newId; - } -} diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/Node.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/Node.java deleted file mode 100644 index 1fdd637d8..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/Node.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.grails.datastore.mapping.node.mapping; - -/** - * TODO: write javadoc - * - * @author Erawat Chamanont - * @since 1.0 - */ -public class Node { - - private String entityName; - - public Node() { - } - - public Node(String entityName) { - this.entityName = entityName; - } - - public String getEntityName() { - return entityName; - } - - public void setEntityName(String entityName) { - this.entityName = entityName; - } -} diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/NodeMappingContext.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/NodeMappingContext.java deleted file mode 100644 index 32b8e74d7..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/NodeMappingContext.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.grails.datastore.mapping.node.mapping; - -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; - -/** - * TODO: write javadoc - * - * @author Erawat Chamanont - * @since 1.0 - */ -public class NodeMappingContext extends AbstractMappingContext { - private MappingConfigurationStrategy syntaxStrategy; - private NodeMappingFactory mappingFactory; - - public NodeMappingContext() { - this.mappingFactory = new NodeMappingFactory(); - this.syntaxStrategy = new GormMappingConfigurationStrategy(mappingFactory); - } - - @Override - protected PersistentEntity createPersistentEntity(Class javaClass) { - return new NodePersistentEntity(javaClass, this); - } - - public MappingConfigurationStrategy getMappingSyntaxStrategy() { - return syntaxStrategy; - } - - public MappingFactory getMappingFactory() { - return mappingFactory; - } -} diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/NodeMappingFactory.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/NodeMappingFactory.java deleted file mode 100644 index 081479fe2..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/NodeMappingFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.grails.datastore.mapping.node.mapping; - -import org.grails.datastore.mapping.model.MappingFactory; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; - -/** - * TODO: write javadoc - * - * @author Erawat Chamanont - * @since 1.0 - */ -public class NodeMappingFactory extends MappingFactory { - - @Override - public Node createMappedForm(PersistentEntity entity) { - return new Node(entity.getName()); - } - - @Override - public NodeProperty createMappedForm(PersistentProperty mpp) { - return new NodeProperty(mpp.getName()); - } -} diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/NodePersistentEntity.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/NodePersistentEntity.java deleted file mode 100644 index 6516e28df..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/NodePersistentEntity.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.grails.datastore.mapping.node.mapping; - -import org.grails.datastore.mapping.model.AbstractPersistentEntity; -import org.grails.datastore.mapping.model.MappingContext; - -/** - * TODO: write javadoc - * - * @author Erawat Chamanont - * @since 1.0 - */ -public class NodePersistentEntity extends AbstractPersistentEntity { - - public NodePersistentEntity(Class javaClass, MappingContext context) { - super(javaClass, context); - } -} diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/NodeProperty.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/NodeProperty.java deleted file mode 100644 index 98c1d93a1..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/NodeProperty.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.grails.datastore.mapping.node.mapping; - -import javax.persistence.FetchType; - - -/** - * TODO: write javadoc - * - * @author Erawat Chamanont - * @since 1.0 - */ -public class NodeProperty { - - private String name; - private boolean index = false; - private FetchType fetchStrategy = FetchType.LAZY; - - public NodeProperty(){} - - public NodeProperty(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - /** - * @return Whether this property is index - */ - public boolean isIndex() { - return index; - } - - /** - * Whether this property is index - * @param index Sets whether to index the property or not - */ - public void setIndex(boolean index) { - this.index = index; - } - - public FetchType getFetchStrategy() { - return fetchStrategy; - } - - public void setFetchStrategy(FetchType fetchStrategy) { - this.fetchStrategy = fetchStrategy; - } -} diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/config/GormNodeMappingFactory.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/config/GormNodeMappingFactory.java deleted file mode 100644 index 2d467820d..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/node/mapping/config/GormNodeMappingFactory.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.grails.datastore.mapping.node.mapping.config; - -import groovy.lang.Closure; - -import java.util.HashMap; -import java.util.Map; - -import org.grails.datastore.mapping.config.groovy.MappingConfigurationBuilder; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.node.mapping.Node; -import org.grails.datastore.mapping.node.mapping.NodeMappingFactory; -import org.grails.datastore.mapping.node.mapping.NodeProperty; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; - -/** - * TODO: write javadoc - * - * @author Erawat Chamanont - * @since 1.0 - */ -public class GormNodeMappingFactory extends NodeMappingFactory { - - private Map entityToPropertyMap = new HashMap(); - - @Override - public Node createMappedForm(PersistentEntity entity) { - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass()); - final Closure value = cpf.getStaticPropertyValue(GormProperties.MAPPING, Closure.class); - if (value != null) { - Node node = new Node(); - MappingConfigurationBuilder builder = new MappingConfigurationBuilder(node, Node.class); - builder.evaluate(value); - entityToPropertyMap.put(entity, builder.getProperties()); - return node; - } - return super.createMappedForm(entity); - } - - @Override - public NodeProperty createMappedForm(PersistentProperty mpp) { - Map properties = entityToPropertyMap.get(mpp.getOwner()); - if (properties != null && properties.containsKey(mpp.getName())) { - return (NodeProperty) properties.get(mpp.getName()); - } - return super.createMappedForm(mpp); - } -} diff --git a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/query/JcrQuery.java b/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/query/JcrQuery.java deleted file mode 100644 index f39e4f3b5..000000000 --- a/grails-datastore-jcr/src/main/java/org/grails/datastore/mapping/query/JcrQuery.java +++ /dev/null @@ -1,466 +0,0 @@ -package org.grails.datastore.mapping.query; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.query.QueryResult; - -import org.springframework.beans.SimpleTypeConverter; -import org.springframework.dao.InvalidDataAccessResourceUsageException; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.jcr.JcrSession; -import org.grails.datastore.mapping.jcr.engine.JcrEntityPersister; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.query.projections.ManualProjections; -import org.springframework.extensions.jcr.JcrTemplate; - -/** - * @author Erawat Chamanont - * @since 1.0 - */ -@SuppressWarnings("hiding") -public class JcrQuery extends Query { - private JcrEntityPersister entityPersister; - private JcrTemplate jcrTemplate; - private SimpleTypeConverter typeConverter; - - private ManualProjections manualProjections; - - public static final String ROOT_NODE = "//"; - public static final String GREATER_THAN_EQUALS = " >= "; - public static final String LESS_THAN_EQUALS = " <= "; - public static final String LOGICAL_AND = " and "; - public static final String GREATER_THAN = " > "; - public static final char SPACE = ' '; - public static final char AT_SIGN = '@'; - public static final String LESS_THAN = " < "; - public static final String EQUALS = " = "; - public static final String NOT_EQUALS = " != "; - public static final String ASCENDING = "ascending"; - public static final String DESCENDING = "descending"; - public static final String LOGICAL_OR = " or "; - public static final String XS_DATE = "xs:date"; - - public JcrQuery(JcrSession session, JcrTemplate jcrTemplate, PersistentEntity persistentEntity, JcrEntityPersister entityPersister) { - super(session, persistentEntity); - this.entityPersister = entityPersister; - this.jcrTemplate = jcrTemplate; - this.manualProjections = new ManualProjections(entity); - typeConverter = new SimpleTypeConverter(); - } - - protected JcrQuery(Session session, PersistentEntity entity) { - super(session, entity); - } - - @Override - protected List executeQuery(PersistentEntity entity, Junction criteria) { - final ProjectionList projectionList = projections(); - List uuids = new ArrayList(); - List finalResults = null; - if (criteria.isEmpty() && !(max != -1)) { - final String queryString = getQueryString(); - QueryResult qr = jcrTemplate.query(queryString.toString(), javax.jcr.query.Query.XPATH); - try { - NodeIterator itr = qr.getNodes(); - while (itr.hasNext()) { - Node node = itr.nextNode(); - uuids.add(node.getUUID()); - } - } catch (RepositoryException e) { - throw new InvalidDataAccessResourceUsageException("Cannot execute query. Entity [" + getEntity() + "] does not exist in the repository"); - } - finalResults = getSession().retrieveAll(getEntity().getJavaClass(), uuids); - if (projectionList.isEmpty()) { - return finalResults; - } - - List results = new ArrayList(); - for (Projection projection : projectionList.getProjectionList()) { - if (projection instanceof CountProjection) { - results.add(finalResults.size()); - } else if (projection instanceof MinProjection) { - MinProjection min = (MinProjection) projection; - results.add(manualProjections.min(finalResults, min.getPropertyName())); - } else if (projection instanceof MaxProjection) { - MaxProjection max = (MaxProjection) projection; - results.add(manualProjections.max(finalResults, max.getPropertyName())); - } else if (projection instanceof IdProjection) { - results.add(uuids); - } else if (projection.getClass() == PropertyProjection.class) { - PropertyProjection propertyProjection = (PropertyProjection) projection; - final String propName = propertyProjection.getPropertyName(); - PersistentProperty prop = entityPersister.getPersistentEntity().getPropertyByName(propName); - Class type = prop.getType(); - List values = new ArrayList(); - for (String uuid : uuids) { - Node node = jcrTemplate.getNodeByUUID(uuid); - try { - if (node.hasProperty(propName)) { - Property nodeProp = node.getProperty(propName); - values.add(nodeProp.getString()); - } - } catch (RepositoryException e) { - throw new InvalidDataAccessResourceUsageException("Cannot execute PropertyProjection criterion on non-existent property: name[" + prop + "]"); - } - } - final PersistentEntity associatedEntity = getSession().getMappingContext().getPersistentEntity(type.getName()); - final boolean isEntityType = associatedEntity != null; - if (isEntityType) { - return getSession().retrieveAll(type, values); - } - for (Object value : values) { - results.add(typeConverter.convertIfNecessary(value, type)); - } - } - } - finalResults = results; - } else { - final List params = new ArrayList(); - final String queryString = getQueryString(params, true); - QueryResult qr = jcrTemplate.query(queryString.toString(), javax.jcr.query.Query.XPATH); - try { - NodeIterator itr = qr.getNodes(); - while (itr.hasNext()) { - Node node = itr.nextNode(); - uuids.add(node.getUUID()); - } - } catch (RepositoryException e) { - throw new InvalidDataAccessResourceUsageException("Cannot execute query. Entity [" + getEntity() + "] does not exist in the repository"); - } - if (uuids.isEmpty()) { - return Collections.emptyList(); - } - - finalResults = getSession().retrieveAll(getEntity().getJavaClass(), uuids); - IdProjection idProjection = null; - if (!projectionList.isEmpty()) { - List projectionResults = new ArrayList(); - for (Projection projection : projectionList.getProjectionList()) { - final String projectionType = projection.getClass().getSimpleName(); - if (projection instanceof CountProjection) { - projectionResults.add(finalResults.size()); - } else if (projection instanceof MaxProjection) { - MaxProjection min = (MaxProjection) projection; - finalResults.add(manualProjections.min(finalResults, min.getPropertyName())); - } else if (projection instanceof MinProjection) { - MinProjection min = (MinProjection) projection; - finalResults.add(manualProjections.min(finalResults, min.getPropertyName())); - } else { - if (projection instanceof SumProjection) { - return unsupportedProjection(projectionType); - } - if (projection instanceof AvgProjection) { - return unsupportedProjection(projectionType); - //} else if (projection instanceof PropertyProjection) { - // PropertyProjection propertyProjection = (PropertyProjection) projection; - // final String propName = propertyProjection.getPropertyName(); - // PersistentProperty prop = entityPersister.getPersistentEntity().getPropertyByName(propName); - // return unsupportedProjection(projectionType); - } - if (projection instanceof IdProjection) { - idProjection = (IdProjection) projection; - } - } - } - if (!projectionResults.isEmpty()) { - return projectionResults; - } - if (idProjection != null) { - return uuids; - } - } - - final int total = finalResults.size(); - if (offset > total) { - finalResults = Collections.emptyList(); - } else { - int from = offset; - int to = max == -1 ? -1 : (offset + max) - 1; - if (to >= total) to = -1; - if (max != -1) { - finalResults = finalResults.subList(from, max); - } - } - } - return finalResults; - - } - - @SuppressWarnings("unused") - private List applyProjections(List results, ProjectionList projections) { - List projectedResults = new ArrayList(); - for (Projection projection : projections.getProjectionList()) { - if (projection instanceof CountProjection) { - projectedResults.add(results.size()); - } else if (projection instanceof MinProjection) { - MinProjection min = (MinProjection) projection; - projectedResults.add(manualProjections.min(results, min.getPropertyName())); - } else if (projection instanceof MaxProjection) { - MaxProjection min = (MaxProjection) projection; - projectedResults.add(manualProjections.max(results, min.getPropertyName())); - } - } - if (projectedResults.isEmpty()) { - return results; - } - return projectedResults; - } - - protected String getQueryString(List params, @SuppressWarnings("unused") boolean distinct) { - final StringBuilder q = new StringBuilder(); - q.append(ROOT_NODE); - q.append(getEntity().getJavaClass().getSimpleName()); - - if (!criteria.isEmpty()) { - q.append("["); - buildCondition(entity, criteria, q, 0, params); - q.append("]"); - } - - validateQuery(q); - - for (Order order : orderBy) { - String direction = null; - if (order.getDirection().equals(Order.Direction.ASC)) { - direction = ASCENDING; - } - else { - direction = DESCENDING; - } - q.append(SPACE); - q.append("order by @"); - q.append(order.getProperty()); - q.append(SPACE); - q.append(direction); - } - return q.toString(); - } - - private StringBuilder validateQuery(StringBuilder q) { - String tmp = q.toString(); - int length = tmp.length(); - Character c = tmp.charAt(length - 2); - if (c.equals('[')) { - tmp.subSequence(0, length - 2); - q.delete(length - 2, length); - } - return q; - } - - private static int buildCondition(PersistentEntity entity, Junction criteria, StringBuilder q, int index, List params) { - final List criterionList = criteria.getCriteria(); - for (Iterator iterator = criterionList.iterator(); iterator.hasNext();) { - Criterion criterion = iterator.next(); - final String operator = criteria instanceof Conjunction ? LOGICAL_AND : LOGICAL_OR; - CriterionHandler qh = criterionHandlers.get(criterion.getClass()); - if (qh != null) { - qh.handle(entity, criterion, q, params); - } - if (iterator.hasNext()) { - q.append(operator); - } - } - return index; - } - - private static interface CriterionHandler { - void handle(PersistentEntity entity, T criterion, StringBuilder q, List params); - } - - private static final Map criterionHandlers = new HashMap() {{ - put(Like.class, new CriterionHandler() { - public void handle(PersistentEntity entity, Like criterion, StringBuilder q, List params) { - String property = criterion.getProperty(); - String pattern = criterion.getPattern(); - validateProperty(entity, property, Like.class); - q.append("jcr:like(@") - .append(property) - .append(",") - .append("'") - .append(pattern) - .append("')"); - } - }); - put(Between.class, new CriterionHandler() { - public void handle(PersistentEntity entity, Between criterion, StringBuilder q, List params) { - final String name = criterion.getProperty(); - final Object value = criterion.getValue(); - validateProperty(entity, name, Between.class); - q.append(AT_SIGN) - .append(name) - .append(GREATER_THAN_EQUALS) - .append(value); - } - }); - put(GreaterThanEquals.class, new CriterionHandler() { - public void handle(PersistentEntity entity, GreaterThanEquals criterion, StringBuilder q, List params) { - final String name = criterion.getProperty(); - final Object value = criterion.getValue(); - validateProperty(entity, name, GreaterThanEquals.class); - q.append(AT_SIGN) - .append(name) - .append(GREATER_THAN_EQUALS); - if (value instanceof Calendar || value instanceof Date) { - SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); - q.append(XS_DATE); - q.append("('"); - q.append(sdf.format((Date)value)); - q.append("')"); - }else q.append(value); - } - }); - put(GreaterThan.class, new CriterionHandler() { - public void handle(PersistentEntity entity, GreaterThan criterion, StringBuilder q, List params) { - final String name = criterion.getProperty(); - final Object value = criterion.getValue(); - validateProperty(entity, name, GreaterThan.class); - q.append(AT_SIGN) - .append(name) - .append(GREATER_THAN); - if (value instanceof Calendar || value instanceof Date) { - SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); - q.append(XS_DATE); - q.append("('"); - q.append(sdf.format((Date)value)); - q.append("')");; - }else q.append(value); - } - }); - put(LessThanEquals.class, new CriterionHandler() { - public void handle(PersistentEntity entity, LessThanEquals criterion, StringBuilder q, List params) { - final String name = criterion.getProperty(); - final Object value = criterion.getValue(); - validateProperty(entity, name, LessThanEquals.class); - q.append(AT_SIGN) - .append(name) - .append(LESS_THAN_EQUALS); - if (value instanceof Calendar || value instanceof Date) { - SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); - q.append(XS_DATE); - q.append("('"); - q.append(sdf.format((Date)value)); - q.append("')"); - }else q.append(value); - } - }); - put(LessThan.class, new CriterionHandler() { - public void handle(PersistentEntity entity, LessThan criterion, StringBuilder q, List params) { - final String name = criterion.getProperty(); - final Object value = criterion.getValue(); - validateProperty(entity, name, LessThan.class); - q.append(AT_SIGN) - .append(name) - .append(LESS_THAN); - if (value instanceof Calendar || value instanceof Date) { - SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); - q.append(XS_DATE); - q.append("('"); - q.append(sdf.format((Date)value)); - q.append("')"); - }else q.append(value); - } - }); - put(Equals.class, new CriterionHandler() { - public void handle(PersistentEntity entity, Equals eq, StringBuilder q, List params) { - final String name = eq.getProperty(); - final Object value = eq.getValue(); - validateProperty(entity, name, Equals.class); - q.append(AT_SIGN) - .append(name) - .append(EQUALS); - if (value instanceof String || value instanceof Boolean) { - q.append("'") - .append(value) - .append("'"); - } else q.append(value); - } - }); - put(NotEquals.class, new CriterionHandler() { - public void handle(PersistentEntity entity, NotEquals nqe, StringBuilder q, List params) { - final String name = nqe.getProperty(); - final Object value = nqe.getValue(); - validateProperty(entity, name, Equals.class); - q.append(AT_SIGN) - .append(name) - .append(NOT_EQUALS); - if (value instanceof String || value instanceof Boolean) { - q.append("'") - .append(value) - .append("'"); - } else q.append(value); - } - }); - put(In.class, new CriterionHandler() { - public void handle(PersistentEntity entity, In criterion, StringBuilder q, List params) { - final String name = criterion.getName(); - validateProperty(entity, name, In.class); - Disjunction dis = new Disjunction(); - for (Object value : criterion.getValues()) { - dis.add(Restrictions.eq(name, value)); - } - buildCondition(entity, dis, q, 0, params); - } - - }); - put(Conjunction.class, new CriterionHandler() { - public void handle(PersistentEntity entity, Junction criterion, StringBuilder q, List params) { - buildCondition(entity, criterion, q, 0, params); - } - }); - put(Disjunction.class, new CriterionHandler() { - public void handle(PersistentEntity entity, Junction criterion, StringBuilder q, List params) { - buildCondition(entity, criterion, q, 0, params); - - } - }); - put(Negation.class, new CriterionHandler() { - public void handle(PersistentEntity entity, Negation criterion, StringBuilder q, List params) { - List cris = criterion.getCriteria(); - Conjunction con = new Conjunction(); - for (Criterion c : cris) { - if (c instanceof Equals) { - con.add(Restrictions.ne(((Equals) c).getProperty(), ((Equals) c).getValue())); - } - if (c instanceof Conjunction) { - con.add(c); - } - } - buildCondition(entity, con, q, 0, params); - } - }); - }}; - - /** - * Obtains the query string with variables embedded within the Query - * - * @return The query string - */ - public String getQueryString() { - return getQueryString(null, false); - } - - private static void validateProperty(PersistentEntity entity, String name, Class criterionType) { - if (entity.getIdentity().getName().equals(name)) return; - PersistentProperty prop = entity.getPropertyByName(name); - if (prop == null) { - throw new InvalidDataAccessResourceUsageException("Cannot use [" + criterionType.getSimpleName() + "] criterion on non-existent property: " + name); - } - } - - private List unsupportedProjection(String projectionType) { - throw new InvalidDataAccessResourceUsageException("Cannot use [" + projectionType + "] projection. [" + projectionType + "] projections are not currently supported."); - } -} 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 c7e431bfc..000000000 --- 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-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/AbstractJcrTest.groovy b/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/AbstractJcrTest.groovy deleted file mode 100644 index 8a3d1b065..000000000 --- a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/AbstractJcrTest.groovy +++ /dev/null @@ -1,36 +0,0 @@ -package org.grails.datastore.mapping.jcr - -import org.junit.AfterClass -import org.junit.BeforeClass -import org.springframework.context.support.GenericApplicationContext - -/** - * Test harness for JCR tests - * - * @author Erawat Chamanont - * @since 1.0 - */ -class AbstractJcrTest { - - protected static conn - protected static ds - - //setup JCR Environments - @BeforeClass - static void setupJCR() { - def ctx = new GenericApplicationContext() - ctx.refresh() - ds = new JcrDatastore(ctx) - def connectionDetails = [username:"username", - password:"password", - workspace:"default", - configuration:"classpath:repository.xml", - homeDir:"/temp/repo"] - conn = ds.connect(connectionDetails) - } - - @AfterClass - static void tearDown() { - conn.disconnect() - } -} \ No newline at end of file diff --git a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/CountQueryTests.groovy b/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/CountQueryTests.groovy deleted file mode 100644 index d92d2d732..000000000 --- a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/CountQueryTests.groovy +++ /dev/null @@ -1,81 +0,0 @@ -package org.grails.datastore.mapping.jcr - -import static org.grails.datastore.mapping.query.Restrictions.eq - -import org.junit.After -import org.junit.AfterClass -import org.junit.BeforeClass -import org.junit.Test -import org.grails.datastore.mapping.query.Query - -/** - * @author Erawat Chamanont - * @since 1.0 - */ -class CountQueryTests extends AbstractJcrTest { - - @After - void clearNodes() { - def session = conn.getNativeInterface() - def wp = session.getWorkspace() - def qm = wp.getQueryManager() - - def q = qm.createQuery("//Book", javax.jcr.query.Query.XPATH) - def qr = q.execute() - def itr = qr.getNodes() - itr.each { it.remove() } - - q = qm.createQuery("//Author", javax.jcr.query.Query.XPATH) - qr = q.execute() - itr = qr.getNodes() - itr.each { it.remove() } - session.save() - } - - @Test - void testDisjunctionAndCount() { - ds.mappingContext.addPersistentEntity(Author) - - def a = new Author(name: "Stephen King") - a.books = [new Book(title: "The Stand"), - new Book(title: "It"), - new Book(title: "The Shining")] - - conn.persist(a) - - Query q = conn.createQuery(Book) - q.disjunction().add(eq("title", "The Stand")).add(eq("title", "It")) - q.projections().count() - - assert 2 == q.singleResult() - } - - @Test - void testSimpleQueryAndCount() { - ds.mappingContext.addPersistentEntity(Author) - - def a = new Author(name: "Stephen King") - a.books = [new Book(title: "The Stand"), - new Book(title: "It")] - - conn.persist(a) - - Query q = conn.createQuery(Book) - - q.eq("title", "It") - q.projections().count() - - def result = q.singleResult() - - assert 1 == result - - q = conn.createQuery(Book) - - q.eq("title", "The Stand") - q.projections().count() - - result = q.singleResult() - - assert 1 == result - } -} diff --git a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/JcrEntityPersisterTests.groovy b/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/JcrEntityPersisterTests.groovy deleted file mode 100644 index 14faa0ea6..000000000 --- a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/JcrEntityPersisterTests.groovy +++ /dev/null @@ -1,88 +0,0 @@ -package org.grails.datastore.mapping.jcr - -import org.junit.Ignore -import org.junit.Test - -/** - * @author Erawat Chamanont - * @since 1.0 - */ -class JcrEntityPersisterTests extends AbstractJcrTest { - - @Ignore - @Test - void testConnection() { - assert null != conn - assert true == conn.isConnected() - - def session = conn.getNativeInterface() - assert null != session - } - - @Test - void testPersist() { - ds.mappingContext.addPersistentEntity(TestEntity) - def t = new TestEntity(title: "foo", body: "bar") - conn.persist(t) - assert null != t.id - - t = conn.retrieve(TestEntity, t.id) - assert t != null - assert "foo" == t.title - assert "bar" == t.body - assert null != t.id - - t.title = 'blog' - conn.persist(t) - - t = conn.retrieve(TestEntity, t.id) - assert 'blog' == t.title - assert 'bar' == t.body - - def id = t.id - - conn.delete(t) - conn.flush() - - t = conn.retrieve(TestEntity, id) - assert t == null - } - - //Still doen't work - @Ignore - @Test - void testTransactions() { - ds.getMappingContext().addPersistentEntity(TestEntity) - conn.clear() - - def tx = conn.beginTransaction() - - TestEntity t = new TestEntity(title: "foo", body: "bar") - conn.persist(t) - TestEntity t2 = new TestEntity(title: "blog", body: "bar") - conn.persist(t2) - tx.commit() - - assert null != t.id - assert null != t2.id - - tx = conn.beginTransaction() - TestEntity t3 = new TestEntity(title: "curry", body: "chicken") - conn.persist(t3) - TestEntity t4 = new TestEntity(title: "salad", body: "beef") - conn.persist(t4) - tx.rollback() - - assert null == t3.id - assert null == t4.id - } -} - -class TestEntity { - //using id field as based APIs required, - //the JCR generated UUID will be assigned to the id property. - String id - - String title - String body -} diff --git a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/ListQueryTests.groovy b/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/ListQueryTests.groovy deleted file mode 100644 index 6c9e72c6e..000000000 --- a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/ListQueryTests.groovy +++ /dev/null @@ -1,142 +0,0 @@ -package org.grails.datastore.mapping.jcr - -import static org.grails.datastore.mapping.query.Restrictions.* - -import org.junit.After -import org.junit.AfterClass -import org.junit.BeforeClass -import org.junit.Test -import org.grails.datastore.mapping.query.Query - -/** - * @author Erawat Chamanont - * @since 1.0 - */ -class ListQueryTests extends AbstractJcrTest { - - @After - void clearNodes() { - def session = conn.getNativeInterface() - def wp = session.getWorkspace() - def qm = wp.getQueryManager() - - def q = qm.createQuery("//Book", javax.jcr.query.Query.XPATH) - def qr = q.execute() - def itr = qr.getNodes() - itr.each { it.remove() } - - q = qm.createQuery("//Author", javax.jcr.query.Query.XPATH) - qr = q.execute() - itr = qr.getNodes() - itr.each { it.remove() } - session.save() - } - - @Test - void testListQuery() { - ds.mappingContext.addPersistentEntity(Author) - - def a = new Author(name: "Stephen King") - a.books = [new Book(title: "The Stand"), - new Book(title: "It")] - - conn.persist(a) - - Query q = conn.createQuery(Book) - - def results = q.list() - - assert 2 == results.size() - - //assert "The Stand" == results[0].title - //assert "It" == results[1].title - - assert null != results.find { it.title == "The Stand" } - assert null != results.find { it.title == "It" } - - q.max 1 - - results = q.list() - - assert 1 == results.size() - //assert "The Stand" == results[0].title - } - - @Test - void testDisjunction() { - ds.mappingContext.addPersistentEntity(Author) - - def a = new Author(name: "Stephen King") - a.books = [new Book(title: "The Stand"), - new Book(title: "It"), - new Book(title: "The Shining")] - - conn.persist(a) - - - Query q = conn.createQuery(Book) - - q.disjunction().add(eq("title", "The Stand")) - .add(eq("title", "The Shining")) - - def results = q.list() - - assert 2 == results.size() - assert null != results.find { it.title == "The Stand" } - assert null != results.find { it.title == "The Shining" } - assert null == results.find { it.title == "It" } - } - - @Test - void testIdProjection() { - ds.mappingContext.addPersistentEntity(Author) - - def a = new Author(name: "Stephen King") - a.books = [new Book(title: "The Stand"), - new Book(title: "It"), - new Book(title: "The Shining")] - - conn.persist(a) - - - Query q = conn.createQuery(Book) - q.disjunction().add(eq("title", "The Stand")) - .add(eq("title", "It")) - q.projections().id() - - - def results = q.list() - - assert 2 == results.size() - assert results[0] instanceof String - } - - @Test - void testSimpleQuery() { - ds.mappingContext.addPersistentEntity(Author) - - def a = new Author(name: "Stephen King") - a.books = [new Book(title: "The Stand"), - new Book(title: "It")] - - conn.persist(a) - - Query q = conn.createQuery(Book) - - q.eq("title", "It") - - def results = q.list() - - assert 1 == results.size() - assert "It" == results[0].title - - q = conn.createQuery(Book) - - q.eq("title", "The Stand") - - results = q.list() - - assert 1 == results.size() - assert "The Stand" == results[0].title - } -} diff --git a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/LockTests.groovy b/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/LockTests.groovy deleted file mode 100644 index 74c3d58d6..000000000 --- a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/LockTests.groovy +++ /dev/null @@ -1,34 +0,0 @@ -package org.grails.datastore.mapping.jcr - -import javax.jcr.Session - -import org.junit.Test - -/** - * Tests for locking - * @author Erawat Chamanont - * @since 1.0 - */ -class LockTests extends AbstractJcrTest{ - - @Test - void testLock() { - ds.mappingContext.addPersistentEntity(TestEntity) - def t = new TestEntity(title: "foo", body: "bar") - conn.persist(t) - conn.flush() - - assert null != t.id - - Session session = conn.getNativeInterface() - def node = session.getNodeByUUID(t.id) - - conn.lock(t) - - assert true == node.isLocked() - - conn.unlock(t) - - assert false == node.isLocked() - } -} diff --git a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/OneTOManyAssociationTests.groovy b/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/OneTOManyAssociationTests.groovy deleted file mode 100644 index d65a16916..000000000 --- a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/OneTOManyAssociationTests.groovy +++ /dev/null @@ -1,71 +0,0 @@ -package org.grails.datastore.mapping.jcr - -import grails.persistence.Entity - -import javax.jcr.Session - -import org.junit.Test - -/** - * @author Erawat Chamanont - * @since 1.1 - */ -class OneToManyAssociationTests extends AbstractJcrTest { - - @Test - void testOneToManyAssociation() { - ds.mappingContext.addPersistentEntity(Author) - - def a = new Author(name: "Scott Davis") - a.books = [new Book(title: "Groovy Recipes"), new Book(title: "JBoss at Work")] as Set - conn.persist(a) - conn.flush() - - a = conn.retrieve(Author, a.id) - - assert null != a.id - assert "Scott Davis" == a.name - assert null != a.books - assert 2 == a.books.size() - - println a.id - - def b1 = a.books.find { it.title == 'Groovy Recipes'} - assert b1 != null - assert b1.id != null - assert "Groovy Recipes" == b1.title - - println b1.id - - def b2 = a.books.find { it.title == 'JBoss at Work'} - assert null != b2.id - assert "JBoss at Work" == b2.title - - println b2.id - - conn.delete(a) - conn.flush() - - Session session = conn.getNativeInterface() - if (session.itemExists("/Author")) { - session.getRootNode().getNode("Author").getNodes().each { - it.remove() - } - session.save() - } - } -} - -@Entity -class Author { - String id - String name - Set books - static hasMany = [books: Book] -} - -@Entity -class Book { - String id - String title -} diff --git a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/OneToOneAssociationTests.groovy b/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/OneToOneAssociationTests.groovy deleted file mode 100644 index b9d6fd446..000000000 --- a/grails-datastore-jcr/src/test/groovy/org/grails/datastore/mapping/jcr/OneToOneAssociationTests.groovy +++ /dev/null @@ -1,53 +0,0 @@ -package org.grails.datastore.mapping.jcr - -import grails.persistence.Entity - -import org.junit.Test - -/** - * @author Erawat Chamanont - * @since 1.0 - */ -class OneToOneAssociationTests extends AbstractJcrTest { - - @Test - void testPersistOneToOneAssociation() { - ds.mappingContext.addPersistentEntity(Blog) - - def b = new Blog(author: "Graeme Rocher") - b.post = new Post(title: "foo", text: "bar") - - conn.persist(b) - - b = conn.retrieve(Blog, b.id) - - assert b != null - assert "Graeme Rocher" == b.author - assert b.post != null - assert "foo" == b.post.title - assert "bar" == b.post.text - - def id = b.id - - conn.delete(b) - conn.flush() - - b = conn.retrieve(Blog, id) - - assert null == b - } -} - -@Entity -class Blog { - String id - String author - Post post -} - -@Entity -class Post { - String id - String title - String text -} diff --git a/grails-datastore-jcr/src/test/resources/log4j.properties b/grails-datastore-jcr/src/test/resources/log4j.properties deleted file mode 100644 index db03bac2f..000000000 --- a/grails-datastore-jcr/src/test/resources/log4j.properties +++ /dev/null @@ -1,27 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -# for production, you should probably list the root to INFO -# and the pattern to %c instead of %l. (%l is slower.) - -# output messages into a rolling log file as well as stdout -log4j.rootLogger=INFO,stdout - -# stdout -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%5p %d{HH:mm:ss,SSS} %m%n - diff --git a/grails-datastore-jpa/build.gradle b/grails-datastore-jpa/build.gradle deleted file mode 100644 index b21fca356..000000000 --- a/grails-datastore-jpa/build.gradle +++ /dev/null @@ -1,35 +0,0 @@ -version = "1.0.0.BUILD-SNAPSHOT" - -configurations { - grails -} - -dependencies { - compile "org.springframework:spring-orm:$springVersion", { - exclude group:'org.springframework', module:'spring-jdbc' - exclude group:'org.springframework', module:'spring-core' - } - compile "org.springframework:spring-jdbc:$springVersion", { - exclude group:'org.springframework', module:'spring-tx' - exclude group:'org.springframework', module:'spring-core' - exclude group:'org.springframework', module:'spring-beans' - } - compile "org.springframework:spring-tx:$springVersion", { - exclude group:'org.springframework', module:'spring-core' - exclude group:'org.springframework', module:'spring-beans' - } - compile project(":grails-datastore-core") - grails("org.grails:grails-core:$grailsVersion") - grails("org.grails:grails-bootstrap:$grailsVersion") { - transitive = false - } -} - -sourceSets { - main { - compileClasspath += configurations.grails - } - test { - compileClasspath += configurations.grails - } -} diff --git a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/JpaDatastore.java b/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/JpaDatastore.java deleted file mode 100644 index d741edc6a..000000000 --- a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/JpaDatastore.java +++ /dev/null @@ -1,79 +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.mapping.jpa; - -import java.util.Map; - -import javax.persistence.EntityManagerFactory; - -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.core.SessionCreationEvent; -import org.grails.datastore.mapping.model.MappingContext; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.orm.jpa.JpaTemplate; -import org.springframework.orm.jpa.JpaTransactionManager; - -/** - * Wraps a JPA EntityManagerFactory in the Datastore Abstraction - * - * @author Graeme Rocher - * @since 1.0 - */ -public class JpaDatastore extends AbstractDatastore { - - private EntityManagerFactory entityManagerFactory; - private JpaTransactionManager transactionManager; - private JpaTemplate jpaTemplate; - - public JpaDatastore(MappingContext mappingContext, - EntityManagerFactory entityManagerFactory, - JpaTransactionManager transactionManager, - ConfigurableApplicationContext applicationContext) { - super(mappingContext, null, applicationContext); - this.entityManagerFactory = entityManagerFactory; - this.transactionManager = transactionManager; - this.jpaTemplate = new JpaTemplate(entityManagerFactory); - initializeConverters(mappingContext); - } - - @Override - public JpaSession connect() { - return (JpaSession) super.connect(); - } - - public EntityManagerFactory getEntityManagerFactory() { - return entityManagerFactory; - } - - public JpaTransactionManager getTransactionManager() { - return transactionManager; - } - - public JpaTemplate getJpaTemplate() { - return jpaTemplate; - } - - @Override - protected Session createSession(Map connDetails) { - JpaSession session = new JpaSession(this, jpaTemplate, transactionManager); - ApplicationEventPublisher applicationEventPublisher = getApplicationEventPublisher(); - if(applicationEventPublisher != null) { - applicationEventPublisher.publishEvent(new SessionCreationEvent(session)); - } - return session; - } -} diff --git a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/JpaSession.java b/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/JpaSession.java deleted file mode 100644 index 57cd09626..000000000 --- a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/JpaSession.java +++ /dev/null @@ -1,347 +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.mapping.jpa; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import javax.persistence.EntityManager; -import javax.persistence.FlushModeType; -import javax.persistence.LockModeType; -import javax.persistence.PersistenceException; - -import org.grails.datastore.mapping.core.AbstractAttributeStoringSession; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.jpa.query.JpaQuery; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.grails.datastore.mapping.query.jpa.JpaQueryBuilder; -import org.grails.datastore.mapping.query.jpa.JpaQueryInfo; -import org.grails.datastore.mapping.transactions.Transaction; -import org.springframework.core.convert.ConversionService; -import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.orm.jpa.JpaCallback; -import org.springframework.orm.jpa.JpaTemplate; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.support.DefaultTransactionDefinition; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -/** - * Wraps a JPA EntityManager in the Datastore Session interface. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class JpaSession extends AbstractAttributeStoringSession { - - private JpaDatastore datastore; - private JpaTemplate jpaTemplate; - private JpaTransactionManager transactionManager; - private FlushModeType flushMode; - private TransactionStatus transaction; - - public JpaSession(JpaDatastore datastore, JpaTemplate jpaTemplate, JpaTransactionManager transactionManager) { - this.jpaTemplate = jpaTemplate; - this.datastore = datastore; - this.transactionManager = transactionManager; - } - - public JpaTemplate getJpaTemplate() { - return jpaTemplate; - } - - public Transaction beginTransaction() { - final TransactionStatus status = transactionManager.getTransaction( - new DefaultTransactionDefinition()); - return new JpaTransaction(transactionManager, status); - } - - public MappingContext getMappingContext() { - return datastore.getMappingContext(); - } - - public Serializable persist(Object o) { - if (o == null) { - throw new InvalidDataAccessApiUsageException("Object to persist cannot be null"); - } - - final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(o.getClass().getName()); - if (persistentEntity == null) { - throw new InvalidDataAccessApiUsageException("Object of class [" + - o.getClass().getName() + "] is not a persistent entity"); - } - - jpaTemplate.persist(o); - return (Serializable)new EntityAccess(persistentEntity, o).getIdentifier(); - } - - @Override - public Serializable insert(Object o) { - return persist(o); - } - - public Object merge(Object o) { - if (o == null) { - throw new InvalidDataAccessApiUsageException("Object to merge cannot be null"); - } - - final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(o.getClass().getName()); - if (persistentEntity == null) { - throw new InvalidDataAccessApiUsageException("Object of class [" + - o.getClass().getName() + "] is not a persistent entity"); - } - - return jpaTemplate.merge(o); - } - - public void refresh(Object o) { - if (o == null) { - return; - } - jpaTemplate.refresh(o); - } - - public void attach(Object o) { - if (o == null) { - return; - } - jpaTemplate.merge(o); - } - - public void flush() { - if (hasTransaction()) { - jpaTemplate.flush(); - } - } - - public static boolean hasTransaction() { - return TransactionSynchronizationManager.isActualTransactionActive() && !TransactionSynchronizationManager.isCurrentTransactionReadOnly(); - } - - public void clear() { - jpaTemplate.execute(new JpaCallback() { - public Void doInJpa(EntityManager em) throws PersistenceException { - em.clear(); - return null; - } - }); - } - - public void clear(Object o) { - // do nothing - } - - public boolean contains(Object o) { - return jpaTemplate.contains(o); - } - - public void setFlushMode(FlushModeType flushMode) { - this.flushMode = flushMode; - jpaTemplate.setFlushEager(flushMode == FlushModeType.AUTO); - } - - public FlushModeType getFlushMode() { - return flushMode; - } - - public void lock(final Object o) { - jpaTemplate.execute(new JpaCallback() { - public Void doInJpa(EntityManager em) throws PersistenceException { - em.lock(o, LockModeType.WRITE); - return null; - } - }); - } - - public void unlock(Object o) { - // noop. Not supported in JPA - } - - public List persist(final Iterable objects) { - return jpaTemplate.execute(new JpaCallback>() { - public List doInJpa(EntityManager em) throws PersistenceException { - List identifiers = new ArrayList(); - for (Object object : objects) { - identifiers.add(persist(object)); - } - return identifiers; - } - }); - } - - public T retrieve(Class type, Serializable key) { - final PersistentEntity persistentEntity = getPersistentEntity(type); - if (persistentEntity == null) { - return null; - } - - final ConversionService conversionService = getMappingContext().getConversionService(); - final Object id = conversionService.convert(key, persistentEntity.getIdentity().getType()); - return jpaTemplate.find(type, id); - } - - public T proxy(Class type, Serializable key) { - return jpaTemplate.getReference(type, key); - } - - public T lock(Class type, Serializable key) { - final T obj = retrieve(type, key); - lock(obj); - return obj; - } - - public void delete(Iterable objects) { - for (Object object : objects) { - jpaTemplate.remove(object); - } - } - - public void delete(Object obj) { - jpaTemplate.remove(obj); - } - - /** - * Deletes all objects matching the given criteria - * - * @param criteria The criteria - * @return The total number of records deleted - */ - public int deleteAll(final QueryableCriteria criteria) { - return jpaTemplate.execute(new JpaCallback() { - public Integer doInJpa(EntityManager em) throws PersistenceException { - JpaQueryBuilder builder = new JpaQueryBuilder(criteria); - JpaQueryInfo jpaQueryInfo = builder.buildDelete(); - javax.persistence.Query query = em.createQuery(jpaQueryInfo.getQuery()); - List parameters = jpaQueryInfo.getParameters(); - if (parameters != null) { - for (int i = 0, count = parameters.size(); i < count; i++) { - query.setParameter(i + 1, parameters.get(i)); - } - } - return query.executeUpdate(); - } - }); - } - - /** - * Updates all objects matching the given criteria and property values - * - * @param criteria The criteria - * @param properties The properties - * @return The total number of records updated - */ - public int updateAll(final QueryableCriteria criteria, final Map properties) { - return jpaTemplate.execute(new JpaCallback() { - public Integer doInJpa(EntityManager em) throws PersistenceException { - JpaQueryBuilder builder = new JpaQueryBuilder(criteria); - JpaQueryInfo jpaQueryInfo = builder.buildUpdate(properties); - javax.persistence.Query query = em.createQuery(jpaQueryInfo.getQuery()); - List parameters = jpaQueryInfo.getParameters(); - if (parameters != null) { - for (int i = 0, count = parameters.size(); i < count; i++) { - query.setParameter(i + 1, parameters.get(i)); - } - } - return query.executeUpdate(); - } - }); - } - - public List retrieveAll(Class type, Iterable keys) { - if (keys instanceof List) { - return retrieveAll(getPersistentEntity(type), (List)keys); - } - List identifierList = new ArrayList(); - for (Object key : keys) { - identifierList.add(key); - } - return retrieveAll(getPersistentEntity(type), identifierList); - } - - public PersistentEntity getPersistentEntity(Class type) { - return getMappingContext().getPersistentEntity(type.getName()); - } - - public List retrieveAll(Class type, Serializable... keys) { - if (type == null) { - return Collections.emptyList(); - } - - final PersistentEntity persistentEntity = getPersistentEntity(type); - if (persistentEntity == null) { - return Collections.emptyList(); - } - - final List identifiers = Arrays.asList(keys); - return retrieveAll(persistentEntity, identifiers); - } - - public List retrieveAll(final PersistentEntity persistentEntity, final List identifiers) { - return createQuery(persistentEntity.getJavaClass()) - .in(persistentEntity.getIdentity().getName(), identifiers) - .list(); - } - - public Query createQuery(Class type) { - return new JpaQuery(this, getPersistentEntity(type)); - } - - public Object getNativeInterface() { - return jpaTemplate; - } - - public Persister getPersister(Object o) { - return null; - } - - public Transaction getTransaction() { - if (transaction == null) { - return null; - } - return new JpaTransaction(transactionManager, transaction); - } - - public JpaDatastore getDatastore() { - return datastore; - } - - public void setTransactionStatus(TransactionStatus transaction) { - this.transaction = transaction; - } - - public boolean isDirty(Object instance) { - // TODO - return false; - } - - @Override - public Serializable getObjectIdentifier(Object instance) { - if(instance == null) return null; - PersistentEntity entity = getPersistentEntity(instance.getClass()); - if(entity != null) { - return (Serializable) new EntityAccess(entity, instance).getIdentifier(); - } - return null; - } -} diff --git a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/JpaTransaction.java b/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/JpaTransaction.java deleted file mode 100644 index 33d22d07b..000000000 --- a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/JpaTransaction.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.grails.datastore.mapping.jpa; - -import org.grails.datastore.mapping.transactions.Transaction; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.transaction.TransactionStatus; - -@SuppressWarnings("rawtypes") -public class JpaTransaction implements Transaction { - - private TransactionStatus transaction; - private JpaTransactionManager transactionManager; - - public JpaTransaction(JpaTransactionManager transactionManager, TransactionStatus transaction) { - this.transaction = transaction; - this.transactionManager = transactionManager; - } - - public void commit() { - if (isValidTransactionPresent()) { - transactionManager.commit(transaction); - } - } - - boolean isValidTransactionPresent() { - return transaction != null && !transaction.isCompleted(); - } - - public void rollback() { - if (isValidTransactionPresent()) { - transactionManager.rollback(transaction); - } - } - - public Object getNativeTransaction() { - return transaction; - } - - public boolean isActive() { - return isValidTransactionPresent(); - } - - public void setTimeout(int timeout) { - transactionManager.setDefaultTimeout(timeout); - } -} diff --git a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/Column.java b/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/Column.java deleted file mode 100644 index 31ca95bd0..000000000 --- a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/Column.java +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright 2012 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.mapping.jpa.config; - -import org.grails.datastore.mapping.config.Property; - -/** - * @author Graeme Rocher - */ -public class Column extends Property{ - - javax.persistence.Column annotation; - - public Column(javax.persistence.Column annotation) { - this.annotation = annotation; - } - - public javax.persistence.Column getAnnotation() { - return annotation; - } -} diff --git a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/JpaMappingConfigurationStrategy.java b/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/JpaMappingConfigurationStrategy.java deleted file mode 100644 index a63710049..000000000 --- a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/JpaMappingConfigurationStrategy.java +++ /dev/null @@ -1,231 +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.mapping.jpa.config; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.persistence.Basic; -import javax.persistence.Embedded; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; -import javax.persistence.Temporal; -import javax.persistence.Transient; -import javax.persistence.Version; - -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.IdentityMapping; -import org.grails.datastore.mapping.model.MappingConfigurationStrategy; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.MappingFactory; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.types.ToOne; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; - -/** - * Configuration strategy for JPA. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class JpaMappingConfigurationStrategy implements MappingConfigurationStrategy{ - - private MappingFactory propertyFactory; - private Map identities = new HashMap(); - private Map> properties= new HashMap>(); - private Map owningEntities = new HashMap(); - - public JpaMappingConfigurationStrategy(MappingFactory propertyFactory) { - this.propertyFactory = propertyFactory; - } - - public boolean isPersistentEntity(Class javaClass) { - return javaClass != null && javaClass.getAnnotation(Entity.class) != null; - } - - public List getPersistentProperties(Class javaClass, - MappingContext context) { - return getPersistentProperties(javaClass, context, null); - } - - private PersistentEntity getPersistentEntity(Class javaClass, MappingContext context, ClassMapping classMapping) { - PersistentEntity entity; - if (classMapping != null) { - entity = classMapping.getEntity(); - } - else { - entity = context.getPersistentEntity(javaClass.getName()); - } - return entity; - } - - public List getPersistentProperties(Class javaClass, - MappingContext context, ClassMapping mapping) { - initializeClassMapping(javaClass, context, mapping); - return properties.get(javaClass); - } - - /** - * @see #getPersistentProperties(Class, org.grails.datastore.mapping.model.MappingContext, org.grails.datastore.mapping.model.ClassMapping) - */ - public List getPersistentProperties(PersistentEntity entity, MappingContext context, ClassMapping classMapping) { - return getPersistentProperties(entity.getJavaClass(), context, classMapping); - } - - public void initializeClassMapping(Class javaClass, MappingContext context, - ClassMapping mapping) { - if (properties.containsKey(javaClass)) { - return; - } - - List persistentProperties = new ArrayList(); - Set owners = new HashSet(); - - properties.put(javaClass, persistentProperties); - owningEntities.put(javaClass, owners); - - final ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(javaClass); - final PersistentEntity owner = getPersistentEntity(javaClass, context, mapping); - - for (PropertyDescriptor propertyDescriptor : cpf.getPropertyDescriptors()) { - if (propertyDescriptor.getReadMethod() != null && propertyDescriptor.getWriteMethod() != null) { - Field field; - try { - field = cpf.getDeclaredField(propertyDescriptor.getName()); - } catch (Exception e) { - continue; - } - if (field != null) { - if (field.getAnnotation(Basic.class) != null || field.getAnnotation(Temporal.class) != null || field.getAnnotation(Version.class) != null) { - persistentProperties.add( - propertyFactory.createSimple(owner, context, propertyDescriptor) - ); - } - else if (field.getAnnotation(Id.class) != null) { - identities.put(javaClass, propertyFactory.createIdentity(owner, context, propertyDescriptor)); - } - else if (field.getAnnotation(Embedded.class) != null) { - final org.grails.datastore.mapping.model.types.Embedded embeddedProperty = propertyFactory.createEmbedded(owner, context, propertyDescriptor); - embeddedProperty.setAssociatedEntity(getOrCreateAssociatedEntity(context, field.getType())); - persistentProperties.add( - embeddedProperty - ); - } - else if (field.getAnnotation(OneToOne.class) != null) { - OneToOne one2one = field.getAnnotation(OneToOne.class); - - if (one2one.mappedBy() != null && one2one.targetEntity() != null) { - owners.add(one2one.targetEntity()); - } - final ToOne oneToOneProperty = propertyFactory.createOneToOne(owner, context, propertyDescriptor); - oneToOneProperty.setAssociatedEntity(getOrCreateAssociatedEntity(context, field.getType())); - persistentProperties.add( - oneToOneProperty - ); - } - else if (field.getAnnotation(OneToMany.class) != null) { - OneToMany one2m = field.getAnnotation(OneToMany.class); - - if (one2m.mappedBy() != null && one2m.targetEntity() != null) { - owners.add(one2m.targetEntity()); - } - final org.grails.datastore.mapping.model.types.OneToMany oneToManyProperty = propertyFactory.createOneToMany(owner, context, propertyDescriptor); - oneToManyProperty.setAssociatedEntity(getOrCreateAssociatedEntity(context, one2m.targetEntity())); - persistentProperties.add( - oneToManyProperty - ); - } - else if (field.getAnnotation(ManyToMany.class) != null) { - ManyToMany m2m = field.getAnnotation(ManyToMany.class); - - if (m2m.mappedBy() != null && m2m.targetEntity() != null) { - owners.add(m2m.targetEntity()); - } - final org.grails.datastore.mapping.model.types.ManyToMany manyToManyProperty = propertyFactory.createManyToMany(owner, context, propertyDescriptor); - manyToManyProperty.setAssociatedEntity(getOrCreateAssociatedEntity(context, m2m.targetEntity())); - persistentProperties.add( - manyToManyProperty - ); - } - else if (field.getAnnotation(ManyToOne.class) != null) { - final ToOne manyToOneProperty = propertyFactory.createManyToOne(owner, context, propertyDescriptor); - manyToOneProperty.setAssociatedEntity(getOrCreateAssociatedEntity(context, field.getType())); - persistentProperties.add( - manyToOneProperty - ); - } - else if (field.getAnnotation(Transient.class) == null) { - persistentProperties.add( - propertyFactory.createSimple(owner, context, propertyDescriptor) - ); - } - } - } - } - } - - private PersistentEntity getOrCreateAssociatedEntity(MappingContext context, Class propType) { - PersistentEntity associatedEntity = context.getPersistentEntity(propType.getName()); - if (associatedEntity == null) { - associatedEntity = context.addPersistentEntity(propType); - } - return associatedEntity; - } - - public PersistentProperty getIdentity(Class javaClass, MappingContext context) { - initializeClassMapping(javaClass, context, null); - return identities.get(javaClass); - } - - /** - * Obtains the identity mapping for the specified class mapping - * - * @param classMapping The class mapping - * @return The identity mapping - */ - public IdentityMapping getIdentityMapping(ClassMapping classMapping) { - return getDefaultIdentityMapping(classMapping); - } - - public void setCanExpandMappingContext(boolean canExpandMappingContext) { - // noop - } - - public IdentityMapping getDefaultIdentityMapping(ClassMapping classMapping) { - return null; - } - - public Set getOwningEntities(Class javaClass, MappingContext context) { - initializeClassMapping(javaClass, context, null); - final Set set = owningEntities.get(javaClass); - if (set != null) { - return set; - } - return Collections.EMPTY_SET; - } -} diff --git a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/JpaMappingContext.java b/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/JpaMappingContext.java deleted file mode 100644 index 16a7cd949..000000000 --- a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/JpaMappingContext.java +++ /dev/null @@ -1,48 +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.mapping.jpa.config; - - -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; - -/** - * A MappingContext for JPA compatible entities. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class JpaMappingContext extends AbstractMappingContext{ - - private MappingFactory mappingFactory = new JpaMappingFactory(); - private MappingConfigurationStrategy jpaMappingSyntaxStrategy = new JpaMappingConfigurationStrategy(mappingFactory); - - public MappingConfigurationStrategy getMappingSyntaxStrategy() { - return jpaMappingSyntaxStrategy ; - } - - @Override - public MappingFactory getMappingFactory() { - return mappingFactory; - } - - @Override - protected PersistentEntity createPersistentEntity(Class javaClass) { - return new JpaPersistentEntity(javaClass, this); - } -} diff --git a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/JpaMappingFactory.java b/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/JpaMappingFactory.java deleted file mode 100644 index db223085f..000000000 --- a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/JpaMappingFactory.java +++ /dev/null @@ -1,75 +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.mapping.jpa.config; - -import java.lang.reflect.Field; -import java.util.List; - -import javax.persistence.Column; -import javax.persistence.Table; - -import groovy.lang.Closure; -import org.grails.datastore.mapping.config.groovy.MappingConfigurationBuilder; -import org.grails.datastore.mapping.model.MappingFactory; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.springframework.beans.BeanUtils; - -/** - * MappingFactory for JPA that maps entities to {@link Table} instances and properties - * to {@link Column} instances. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class JpaMappingFactory extends MappingFactory { - - @Override - public org.grails.datastore.mapping.jpa.config.Table createMappedForm(PersistentEntity entity) { - org.grails.datastore.mapping.jpa.config.Table mappedForm = new org.grails.datastore.mapping.jpa.config.Table((Table) entity.getJavaClass().getAnnotation(Table.class)); - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass()); - MappingConfigurationBuilder builder = new MappingConfigurationBuilder(mappedForm, org.grails.datastore.mapping.jpa.config.Table.class); - - List values = cpf.getStaticPropertyValuesFromInheritanceHierarchy(GormProperties.MAPPING, Closure.class); - for (int i = values.size(); i > 0; i--) { - Closure value = values.get(i - 1); - builder.evaluate(value); - } - values = cpf.getStaticPropertyValuesFromInheritanceHierarchy(GormProperties.CONSTRAINTS, Closure.class); - for (int i = values.size(); i > 0; i--) { - Closure value = values.get(i - 1); - builder.evaluate(value); - } - - return mappedForm; - } - - @Override - public org.grails.datastore.mapping.jpa.config.Column createMappedForm(PersistentProperty mpp) { - Field field; - try { - field = mpp.getOwner().getJavaClass().getDeclaredField(mpp.getName()); - return new org.grails.datastore.mapping.jpa.config.Column(field.getAnnotation(Column.class)); - } catch (SecurityException e) { - return null; - } catch (NoSuchFieldException e) { - return null; - } - } -} diff --git a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/JpaPersistentEntity.java b/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/JpaPersistentEntity.java deleted file mode 100644 index f2de4147f..000000000 --- a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/JpaPersistentEntity.java +++ /dev/null @@ -1,79 +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.mapping.jpa.config; - -import javax.persistence.Table; - -import groovy.lang.Closure; -import org.grails.datastore.mapping.config.groovy.MappingConfigurationBuilder; -import org.grails.datastore.mapping.model.AbstractPersistentEntity; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.IdentityMapping; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; - -import java.util.List; - -/** - * Models a JPA-mapped entity. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class JpaPersistentEntity extends AbstractPersistentEntity { - - private final org.grails.datastore.mapping.jpa.config.Table mappedForm; - - public JpaPersistentEntity(@SuppressWarnings("rawtypes") Class javaClass, MappingContext context) { - super(javaClass, context); - Table ann = (Table) getJavaClass().getAnnotation(Table.class); - this.mappedForm = new org.grails.datastore.mapping.jpa.config.Table(ann); - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(getJavaClass()); - MappingConfigurationBuilder builder = new MappingConfigurationBuilder(mappedForm, org.grails.datastore.mapping.jpa.config.Table.class); - - List values = cpf.getStaticPropertyValuesFromInheritanceHierarchy(GormProperties.MAPPING, Closure.class); - for (int i = values.size(); i > 0; i--) { - Closure value = values.get(i - 1); - builder.evaluate(value); - } - values = cpf.getStaticPropertyValuesFromInheritanceHierarchy(GormProperties.CONSTRAINTS, Closure.class); - for (int i = values.size(); i > 0; i--) { - Closure value = values.get(i - 1); - builder.evaluate(value); - } - - } - - @Override - public ClassMapping getMapping() { - - return new ClassMapping() { - public PersistentEntity getEntity() { - return JpaPersistentEntity.this; - } - - @SuppressWarnings("unchecked") - public org.grails.datastore.mapping.jpa.config.Table getMappedForm() { - return mappedForm; - } - - public IdentityMapping getIdentifier() { - return null; - } - }; - } -} diff --git a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/Table.java b/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/Table.java deleted file mode 100644 index 35fae957f..000000000 --- a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/config/Table.java +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright 2012 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.mapping.jpa.config; - -import org.grails.datastore.mapping.config.Entity; - -/** - * @author Graeme Rocher - */ -public class Table extends Entity{ - private javax.persistence.Table annotation; - - public javax.persistence.Table getAnnotation() { - return annotation; - } - - public Table(javax.persistence.Table annotation) { - this.annotation = annotation; - } -} diff --git a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/query/JpaQuery.java b/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/query/JpaQuery.java deleted file mode 100644 index ff312a523..000000000 --- a/grails-datastore-jpa/src/main/groovy/org/grails/datastore/mapping/jpa/query/JpaQuery.java +++ /dev/null @@ -1,134 +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.mapping.jpa.query; - -import java.util.List; - -import javax.persistence.EntityManager; -import javax.persistence.PersistenceException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.grails.datastore.mapping.jpa.JpaSession; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.Restrictions; -import org.grails.datastore.mapping.query.jpa.JpaQueryBuilder; -import org.grails.datastore.mapping.query.jpa.JpaQueryInfo; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.orm.jpa.JpaCallback; -import org.springframework.orm.jpa.JpaTemplate; - -/** - * Query implementation for JPA. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class JpaQuery extends Query { - private static final Log LOG = LogFactory.getLog(JpaQuery.class); - - public JpaQuery(JpaSession session, PersistentEntity entity) { - super(session, entity); - - if (session == null) { - throw new InvalidDataAccessApiUsageException("Argument session cannot be null"); - } - if (entity == null) { - throw new InvalidDataAccessApiUsageException("No persistent entity specified"); - } - } - - @Override - public JpaSession getSession() { - return (JpaSession) super.getSession(); - } - - @Override - public void add(Criterion criterion) { - if (criterion instanceof Equals) { - final Equals eq = (Equals) criterion; - Object resolved = resolveIdIfEntity(eq.getValue()); - if (resolved != eq.getValue()) { - criterion = Restrictions.idEq(resolved); - } - } - - criteria.add(criterion); - } - - @Override - protected List executeQuery(final PersistentEntity entity, final Junction criteria) { - final JpaTemplate jpaTemplate = getSession().getJpaTemplate(); - if (!JpaSession.hasTransaction()) { - jpaTemplate.setFlushEager(false); - } - - return (List)jpaTemplate.execute(new JpaCallback() { - public Object doInJpa(EntityManager em) throws PersistenceException { - return executeQuery(entity, criteria, em, false); - } - }); - } - - @Override - public Object singleResult() { - final JpaTemplate jpaTemplate = getSession().getJpaTemplate(); - if (!JpaSession.hasTransaction()) { - jpaTemplate.setFlushEager(false); - } - try { - return jpaTemplate.execute(new JpaCallback() { - public Object doInJpa(EntityManager em) throws PersistenceException { - return executeQuery(entity, criteria, em, true); - } - }); - } catch (EmptyResultDataAccessException e) { - return null; - } - } - - Object executeQuery(final PersistentEntity entity, final Junction criteria, EntityManager em, boolean singleResult) { - - JpaQueryBuilder queryBuilder = new JpaQueryBuilder(entity, criteria, projections, orderBy); - queryBuilder.setConversionService(session.getDatastore().getMappingContext().getConversionService()); - JpaQueryInfo jpaQueryInfo = queryBuilder.buildSelect(); - List parameters = jpaQueryInfo.getParameters(); - final String queryToString = jpaQueryInfo.getQuery(); - - if (LOG.isDebugEnabled()) { - LOG.debug("Built JPQL to execute: " + queryToString); - } - final javax.persistence.Query q = em.createQuery(queryToString); - - if (parameters != null) { - for (int i = 0, count = parameters.size(); i < count; i++) { - q.setParameter(i + 1, parameters.get(i)); - } - } - q.setFirstResult(offset); - if (max > -1) { - q.setMaxResults(max); - } - - if (!singleResult) { - return q.getResultList(); - } - return q.getSingleResult(); - } -} diff --git a/grails-datastore-mongo/build.gradle b/grails-datastore-mongo/build.gradle deleted file mode 100644 index 6c466ece7..000000000 --- a/grails-datastore-mongo/build.gradle +++ /dev/null @@ -1,7 +0,0 @@ -version = "1.3.0.BUILD-SNAPSHOT" -dependencies { - compile project(":grails-datastore-core") - - compile "org.mongodb:mongo-java-driver:2.11.1" - compile("org.springframework.data:spring-data-mongodb:1.2.1.RELEASE") -} diff --git a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/MongoDatastore.java b/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/MongoDatastore.java deleted file mode 100644 index 0bc0f75b8..000000000 --- a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/MongoDatastore.java +++ /dev/null @@ -1,364 +0,0 @@ -/* Copyright (C) 2010 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.mapping.mongo; - -import static org.grails.datastore.mapping.config.utils.ConfigUtils.read; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.bson.types.Binary; -import org.bson.types.ObjectId; -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.core.StatelessDatastore; -import org.grails.datastore.mapping.document.config.DocumentMappingContext; -import org.grails.datastore.mapping.model.ClassMapping; -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.PropertyMapping; -import org.grails.datastore.mapping.mongo.config.MongoAttribute; -import org.grails.datastore.mapping.mongo.config.MongoCollection; -import org.grails.datastore.mapping.mongo.config.MongoMappingContext; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.convert.converter.Converter; -import org.springframework.dao.DataAccessException; -import org.springframework.data.authentication.UserCredentials; -import org.springframework.data.mongodb.core.DbCallback; -import org.springframework.data.mongodb.core.MongoFactoryBean; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoDbFactory; - -import com.mongodb.BasicDBObject; -import com.mongodb.DB; -import com.mongodb.DBCollection; -import com.mongodb.DBObject; -import com.mongodb.Mongo; -import com.mongodb.MongoException; -import com.mongodb.MongoOptions; -import com.mongodb.ServerAddress; -import com.mongodb.WriteConcern; - -/** - * A Datastore implementation for the Mongo document store. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class MongoDatastore extends AbstractDatastore implements InitializingBean, MappingContext.Listener, DisposableBean, StatelessDatastore { - - public static final String PASSWORD = "password"; - public static final String USERNAME = "username"; - public static final String MONGO_PORT = "port"; - public static final String MONGO_HOST = "host"; - public static final String MONGO_STATELESS = "stateless"; - - protected Mongo mongo; - protected MongoOptions mongoOptions = new MongoOptions(); - protected Map mongoTemplates = new ConcurrentHashMap(); - protected Map mongoCollections = new ConcurrentHashMap(); - protected boolean stateless = false; - protected UserCredentials userCrentials; - - /** - * Constructs a MongoDatastore using the default database name of "test" and defaults for the host and port. - * Typically used during testing. - */ - public MongoDatastore() { - this(new MongoMappingContext("test"), Collections.emptyMap(), null); - } - - /** - * Constructs a MongoDatastore using the given MappingContext and connection details map. - * - * @param mappingContext The MongoMappingContext - * @param connectionDetails The connection details containing the {@link #MONGO_HOST} and {@link #MONGO_PORT} settings - */ - public MongoDatastore(MongoMappingContext mappingContext, - Map connectionDetails, MongoOptions mongoOptions, ConfigurableApplicationContext ctx) { - - this(mappingContext, connectionDetails, ctx); - if (mongoOptions != null) { - this.mongoOptions = mongoOptions; - } - } - - /** - * Constructs a MongoDatastore using the given MappingContext and connection details map. - * - * @param mappingContext The MongoMappingContext - * @param connectionDetails The connection details containing the {@link #MONGO_HOST} and {@link #MONGO_PORT} settings - */ - public MongoDatastore(MongoMappingContext mappingContext, - Map connectionDetails, ConfigurableApplicationContext ctx) { - super(mappingContext, connectionDetails, ctx); - - if (mappingContext != null) { - mappingContext.addMappingContextListener(this); - } - - initializeConverters(mappingContext); - - mappingContext.getConverterRegistry().addConverter(new Converter() { - public ObjectId convert(String source) { - return new ObjectId(source); - } - }); - - mappingContext.getConverterRegistry().addConverter(new Converter() { - public String convert(ObjectId source) { - return source.toString(); - } - }); - - mappingContext.getConverterRegistry().addConverter(new Converter() { - public Binary convert(byte[] source) { - return new Binary(source); - } - }); - - mappingContext.getConverterRegistry().addConverter(new Converter() { - public byte[] convert(Binary source) { - return source.getData(); - } - }); - } - - public MongoDatastore(MongoMappingContext mappingContext) { - this(mappingContext, Collections.emptyMap(), null); - } - - /** - * Constructor for creating a MongoDatastore using an existing Mongo instance - * @param mappingContext The MappingContext - * @param mongo The existing Mongo instance - */ - public MongoDatastore(MongoMappingContext mappingContext, Mongo mongo, - ConfigurableApplicationContext ctx) { - this(mappingContext, Collections.emptyMap(), ctx); - this.mongo = mongo; - } - - /** - * Constructor for creating a MongoDatastore using an existing Mongo instance. In this case - * the connection details are only used to supply a USERNAME and PASSWORD - * - * @param mappingContext The MappingContext - * @param mongo The existing Mongo instance - */ - public MongoDatastore(MongoMappingContext mappingContext, Mongo mongo, - Map connectionDetails, ConfigurableApplicationContext ctx) { - this(mappingContext, connectionDetails, ctx); - this.mongo = mongo; - } - - public Mongo getMongo() { - return mongo; - } - - public MongoTemplate getMongoTemplate(PersistentEntity entity) { - return mongoTemplates.get(entity); - } - - public String getCollectionName(PersistentEntity entity) { - return mongoCollections.get(entity); - } - - public UserCredentials getUserCrentials() { - return userCrentials; - } - - @Override - protected Session createSession(Map connDetails) { - if(stateless) { - return createStatelessSession(connectionDetails); - } - else { - return new MongoSession(this, getMappingContext(), getApplicationEventPublisher(), false); - } - } - - @Override - protected Session createStatelessSession(Map connectionDetails) { - return new MongoSession(this, getMappingContext(), getApplicationEventPublisher(), true); - } - - public void afterPropertiesSet() throws Exception { - if (mongo == null) { - ServerAddress defaults = new ServerAddress(); - MongoFactoryBean dbFactory = new MongoFactoryBean(); - dbFactory.setHost(read(String.class, MONGO_HOST, connectionDetails, defaults.getHost())); - dbFactory.setPort(read(Integer.class, MONGO_PORT, connectionDetails, defaults.getPort())); - this.stateless = read(Boolean.class, MONGO_STATELESS, connectionDetails, false); - if (mongoOptions != null) { - dbFactory.setMongoOptions(mongoOptions); - } - - dbFactory.afterPropertiesSet(); - mongo = dbFactory.getObject(); - } - - for (PersistentEntity entity : mappingContext.getPersistentEntities()) { - // Only create Mongo templates for entities that are mapped with Mongo - if (!entity.isExternal()) { - createMongoTemplate(entity, mongo); - } - } - } - - protected void createMongoTemplate(PersistentEntity entity, Mongo mongoInstance) { - DocumentMappingContext dc = (DocumentMappingContext) getMappingContext(); - String collectionName = entity.getDecapitalizedName(); - String databaseName = dc.getDefaultDatabaseName(); - @SuppressWarnings("unchecked") ClassMapping mapping = entity.getMapping(); - final MongoCollection mongoCollection = mapping.getMappedForm() != null ? mapping.getMappedForm() : null; - - if (mongoCollection != null) { - if (mongoCollection.getCollection() != null) { - collectionName = mongoCollection.getCollection(); - } - if (mongoCollection.getDatabase() != null) { - databaseName = mongoCollection.getDatabase(); - } - } - - final SimpleMongoDbFactory dbf; - - String username = read(String.class, USERNAME, connectionDetails, null); - String password = read(String.class, PASSWORD, connectionDetails, null); - - if (username != null && password != null) { - this.userCrentials = new UserCredentials(username, password); - dbf = new SimpleMongoDbFactory(mongoInstance, databaseName, userCrentials); - } - else { - dbf = new SimpleMongoDbFactory(mongoInstance, databaseName); - } - - final MongoTemplate mt = new MongoTemplate(dbf); - - if (mongoCollection != null) { - final WriteConcern writeConcern = mongoCollection.getWriteConcern(); - if (writeConcern != null) { - final String collectionNameToUse = collectionName; - mt.executeInSession(new DbCallback() { - public Object doInDB(DB db) throws MongoException, DataAccessException { - if (writeConcern != null) { - DBCollection collection = db.getCollection(collectionNameToUse); - collection.setWriteConcern(writeConcern); - } - return null; - } - }); - } - } - - mongoTemplates.put(entity, mt); - mongoCollections.put(entity, collectionName); - - initializeIndices(entity, mt); - } - - /** - * Indexes any properties that are mapped with index:true - * @param entity The entity - * @param template The template - */ - protected void initializeIndices(final PersistentEntity entity, final MongoTemplate template) { - template.execute(new DbCallback() { - @SuppressWarnings({ "unchecked", "rawtypes" }) - public Object doInDB(DB db) throws MongoException, DataAccessException { - final DBCollection collection = db.getCollection(getCollectionName(entity)); - - final ClassMapping classMapping = entity.getMapping(); - if (classMapping != null) { - final MongoCollection mappedForm = classMapping.getMappedForm(); - if (mappedForm != null) { - for (Map compoundIndex : mappedForm.getCompoundIndices()) { - DBObject indexDef = new BasicDBObject(compoundIndex); - collection.ensureIndex(indexDef); - } - } - } - - for (PersistentProperty property : entity.getPersistentProperties()) { - final boolean indexed = isIndexed(property); - - if (indexed) { - final MongoAttribute mongoAttributeMapping = property.getMapping().getMappedForm(); - DBObject dbObject = new BasicDBObject(); - final String fieldName = getMongoFieldNameForProperty(property); - dbObject.put(fieldName,1); - DBObject options = new BasicDBObject(); - if (mongoAttributeMapping != null) { - Map attributes = mongoAttributeMapping.getIndexAttributes(); - if (attributes != null) { - attributes = new HashMap(attributes); - if (attributes.containsKey(MongoAttribute.INDEX_TYPE)) { - dbObject.put(fieldName, attributes.remove(MongoAttribute.INDEX_TYPE)); - } - options.putAll(attributes); - } - } - if (options.toMap().isEmpty()) { - collection.ensureIndex(dbObject); - } - else { - collection.ensureIndex(dbObject, options); - } - } - } - - return null; - } - - String getMongoFieldNameForProperty(PersistentProperty property) { - PropertyMapping pm = property.getMapping(); - String propKey = null; - if (pm.getMappedForm() != null) { - propKey = pm.getMappedForm().getField(); - } - if (propKey == null) { - propKey = property.getName(); - } - return propKey; - } - }); - } - - public void persistentEntityAdded(PersistentEntity entity) { - createMongoTemplate(entity, mongo); - } - - public void destroy() throws Exception { - super.destroy(); - if (mongo != null) { - mongo.close(); - } - } - - @Override - public boolean isSchemaless() { - return true; - } - - -} diff --git a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/MongoSession.java b/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/MongoSession.java deleted file mode 100644 index ecb48e05d..000000000 --- a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/MongoSession.java +++ /dev/null @@ -1,272 +0,0 @@ -/* Copyright (C) 2010 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.mapping.mongo; - -import java.io.Serializable; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.grails.datastore.mapping.core.AbstractSession; -import org.grails.datastore.mapping.core.impl.PendingInsert; -import org.grails.datastore.mapping.core.impl.PendingOperation; -import org.grails.datastore.mapping.document.config.DocumentMappingContext; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.mongo.config.MongoCollection; -import org.grails.datastore.mapping.mongo.engine.MongoEntityPersister; -import org.grails.datastore.mapping.mongo.query.MongoQuery; -import org.grails.datastore.mapping.transactions.SessionOnlyTransaction; -import org.grails.datastore.mapping.transactions.Transaction; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.dao.DataAccessException; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.data.mongodb.core.DbCallback; -import org.springframework.data.mongodb.core.MongoTemplate; - -import com.mongodb.BasicDBObject; -import com.mongodb.DB; -import com.mongodb.DBCollection; -import com.mongodb.DBObject; -import com.mongodb.MongoException; -import com.mongodb.WriteConcern; -import com.mongodb.WriteResult; - -/** - * A {@link org.grails.datastore.mapping.core.Session} implementation for the Mongo document store. - * - * @author Graeme Rocher - * @since 1.0 - */ -public class MongoSession extends AbstractSession { - - private static final Map declaredWriteConcerns = new ConcurrentHashMap(); - MongoDatastore mongoDatastore; - private WriteConcern writeConcern = null; - private boolean errorOccured = false; - protected Map mongoTemplates = new ConcurrentHashMap(); - protected Map mongoCollections = new ConcurrentHashMap(); - - - public MongoSession(MongoDatastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher) { - this(datastore, mappingContext, publisher, false); - } - public MongoSession(MongoDatastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher, boolean stateless) { - super(datastore, mappingContext, publisher, stateless); - mongoDatastore = datastore; - try { - getNativeInterface().requestStart(); - } - catch (IllegalStateException ignored) { - // can't call authenticate() twice, and it's probably been called at startup - } - } - - @Override - public MongoQuery createQuery(@SuppressWarnings("rawtypes") Class type) { - return (MongoQuery) super.createQuery(type); - } - - /** - * Sets the WriteConcern to use for the session - * - * @param writeConcern The WriteConcern to use - */ - public void setWriteConcern(WriteConcern writeConcern) { - this.writeConcern = writeConcern; - } - - /** - * Obtains the WriteConcern to use for the session - * @return the WriteConcern - */ - public WriteConcern getWriteConcern() { - return writeConcern; - } - - /** - * Execute a flush using the given WriteConcern - * - * @param writeConcern The WriteConcern to use - */ - public void flush(WriteConcern writeConcern) { - WriteConcern current = this.writeConcern; - - this.writeConcern = writeConcern; - - try { - if (!errorOccured) { - super.flush(); - } - } - finally { - this.writeConcern = current; - } - } - - @Override - public void flush() { - if (!errorOccured) { - super.flush(); - } - } - - @Override - public void disconnect() { - super.disconnect(); - getNativeInterface().requestDone(); - } - - @Override - @SuppressWarnings({"rawtypes", "unchecked"}) - protected void flushPendingInserts(final Map> inserts) { - // Optimizes saving multipe entities at once - for (final PersistentEntity entity : inserts.keySet()) { - final MongoTemplate template = getMongoTemplate(entity.isRoot() ? entity : entity.getRootEntity()); - final String collectionNameToUse = getCollectionName(entity.isRoot() ? entity : entity.getRootEntity()); - template.execute(new DbCallback() { - public Object doInDB(DB db) throws MongoException, DataAccessException { - - WriteConcern writeConcernToUse = getDeclaredWriteConcern(entity); - final DBCollection collection = db.getCollection(collectionNameToUse); - - final Collection pendingInserts = inserts.get(entity); - List dbObjects = new LinkedList(); - List postOperations = new LinkedList(); - - for (PendingInsert pendingInsert : pendingInserts) { - - final List preOperations = pendingInsert.getPreOperations(); - for (PendingOperation preOperation : preOperations) { - preOperation.run(); - } - - - pendingInsert.run(); - if(!pendingInsert.isVetoed()) { - dbObjects.add((DBObject) pendingInsert.getNativeEntry()); - postOperations.addAll(pendingInsert.getCascadeOperations()); - } - } - - WriteResult writeResult = writeConcernToUse != null ? collection.insert(dbObjects.toArray(new DBObject[dbObjects.size()]), writeConcernToUse ) - : collection.insert(dbObjects.toArray(new DBObject[dbObjects.size()])); - if (writeResult.getError() != null) { - errorOccured = true; - throw new DataIntegrityViolationException(writeResult.getError()); - } - for (PendingOperation pendingOperation : postOperations) { - pendingOperation.run(); - } - return null; - } - }); - } - } - - public WriteConcern getDeclaredWriteConcern(PersistentEntity entity) { - return getDeclaredWriteConcern(this.writeConcern, entity); - } - - private WriteConcern getDeclaredWriteConcern(WriteConcern defaultConcern, PersistentEntity entity) { - WriteConcern writeConcern = declaredWriteConcerns.get(entity); - if (writeConcern == null) { - Object mappedForm = entity.getMapping().getMappedForm(); - if (mappedForm instanceof MongoCollection) { - MongoCollection mc = (MongoCollection) mappedForm; - writeConcern = mc.getWriteConcern(); - if (writeConcern == null) { - writeConcern = defaultConcern; - } - } - - if (writeConcern != null) { - declaredWriteConcerns.put(entity, writeConcern); - } - } - return writeConcern; - } - - public DB getNativeInterface() { - return ((MongoDatastore)getDatastore()).getMongo().getDB( - getDocumentMappingContext().getDefaultDatabaseName()); - } - - public DocumentMappingContext getDocumentMappingContext() { - return (DocumentMappingContext) getMappingContext(); - } - - @Override - protected Persister createPersister(@SuppressWarnings("rawtypes") Class cls, MappingContext mappingContext) { - final PersistentEntity entity = mappingContext.getPersistentEntity(cls.getName()); - return entity == null ? null : new MongoEntityPersister(mappingContext, entity, this, publisher); - } - - @Override - protected Transaction beginTransactionInternal() { - return new SessionOnlyTransaction(getNativeInterface(), this); - } - - public MongoTemplate getMongoTemplate(PersistentEntity entity) { - MongoTemplate mongoTemplate = mongoTemplates.get(entity); - return mongoTemplate != null ? mongoTemplate : mongoDatastore.getMongoTemplate(entity); - } - - public String getCollectionName(PersistentEntity entity) { - return mongoCollections.containsKey(entity) ? mongoCollections.get(entity) : mongoDatastore.getCollectionName(entity); - } - - /** - * Use the given collection for the given entity - * - * @param entity The entity - * @param collectionName The collection - * @return The previous collection that was used - */ - public String useCollection(PersistentEntity entity, String collectionName) { - String current = mongoCollections.containsKey(entity) ? mongoCollections.get(entity) : mongoDatastore.getCollectionName(entity); - mongoCollections.put(entity, collectionName); - return current; - } - - /** - * Use the given database name for the given entity - * - * @param entity The entity name - * @param databaseName The database name - * @return The name of the previous database - */ - public String useDatabase(PersistentEntity entity, String databaseName) { - MongoTemplate currentTemplate = mongoTemplates.containsKey(entity) ? mongoTemplates.get(entity) : mongoDatastore.getMongoTemplate(entity); - String currentDatabase = currentTemplate.getDb().getName(); - mongoTemplates.put(entity, new MongoTemplate(mongoDatastore.getMongo(), databaseName, mongoDatastore.getUserCrentials())); - return currentDatabase; - } - - - @Override - protected void cacheEntry(Serializable key, Object entry, Map entryCache, boolean forDirtyCheck) { - if (forDirtyCheck) { - entryCache.put(key, new BasicDBObject(((DBObject)entry).toMap())); - } - else { - entryCache.put(key, entry); - } - } -} diff --git a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoAttribute.java b/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoAttribute.java deleted file mode 100644 index 7e37ddea8..000000000 --- a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoAttribute.java +++ /dev/null @@ -1,82 +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.mapping.mongo.config; - -import java.util.HashMap; -import java.util.Map; - -import org.grails.datastore.mapping.document.config.Attribute; - -/** - * Extends {@link Attribute} class with additional Mongo specific configuration - * - * @author Graeme Rocher - * @since 1.0 - */ -public class MongoAttribute extends Attribute { - - public static final String INDEX_TYPE = "type"; - - @SuppressWarnings("rawtypes") - private Map indexAttributes; - private boolean reference = false; - - public boolean isReference() { - return reference; - } - - public void setReference(boolean reference) { - this.reference = reference; - } - - @SuppressWarnings("rawtypes") - public Map getIndexAttributes() { - return indexAttributes; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void setIndexAttributes(Map indexAttributes) { - if (this.indexAttributes == null) { - this.indexAttributes = indexAttributes; - } - else { - this.indexAttributes.putAll(indexAttributes); - } - } - - public void setField(String name) { - setTargetName(name); - } - - public String getField() { - return getTargetName(); - } - - @SuppressWarnings("unchecked") - public void setGeoIndex(boolean geoIndex) { - if (geoIndex) { - setIndex(true); - initIndexAttributes(); - indexAttributes.put(INDEX_TYPE, "2d"); - } - } - - @SuppressWarnings("rawtypes") - void initIndexAttributes() { - if (indexAttributes == null) { - indexAttributes = new HashMap(); - } - } -} diff --git a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoCollection.java b/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoCollection.java deleted file mode 100644 index 287debc8d..000000000 --- a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoCollection.java +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (C) 2010 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.mapping.mongo.config; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.grails.datastore.mapping.document.config.Collection; -import org.grails.datastore.mapping.query.Query; - -import com.mongodb.WriteConcern; - -/** - * Provides configuration options for mapping Mongo DBCollection instances - * - * @author Graeme Rocher - */ -@SuppressWarnings("rawtypes") -public class MongoCollection extends Collection { - - private String database; - private WriteConcern writeConcern; - private List compoundIndices = new ArrayList(); - private Query.Order sort; - - public Query.Order getSort() { - return sort; - } - - public void setSort(Object s) { - if (s instanceof Query.Order) { - this.sort = (Query.Order) s; - } - if (s instanceof Map) { - Map m = (Map) s; - if (!m.isEmpty()) { - Map.Entry entry = (Map.Entry) m.entrySet().iterator().next(); - Object key = entry.getKey(); - if ("desc".equalsIgnoreCase(entry.getValue().toString())) { - this.sort = Query.Order.desc(key.toString()); - } - else { - this.sort = Query.Order.asc(key.toString()); - } - } - } - else { - this.sort = Query.Order.asc(s.toString()); - } - } - - /** - * The database to use - * - * @return The name of the database - */ - public String getDatabase() { - return database; - } - /** - * The name of the database to use - * - * @param database The database - */ - public void setDatabase(String database) { - this.database = database; - } - - /** - * @return The {@link WriteConcern} for the collection - */ - public WriteConcern getWriteConcern() { - return writeConcern; - } - - /** - * The {@link WriteConcern} for the collection - */ - public void setWriteConcern(WriteConcern writeConcern) { - this.writeConcern = writeConcern; - } - - /** - * Sets a compound index definition - * - * @param compoundIndex The compount index - */ - public void setCompoundIndex(Map compoundIndex) { - if (compoundIndex != null) { - compoundIndices.add(compoundIndex); - } - } - - /** - * Return all defined compound indices - * - * @return The compound indices to return - */ - public List getCompoundIndices() { - return compoundIndices; - } -} diff --git a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoMappingContext.java b/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoMappingContext.java deleted file mode 100644 index 8eb49af87..000000000 --- a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoMappingContext.java +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright (C) 2010 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.mapping.mongo.config; - -import com.mongodb.DBObject; -import groovy.lang.Closure; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; -import java.util.regex.Pattern; - -import org.bson.BSONObject; -import org.bson.types.BSONTimestamp; -import org.bson.types.Code; -import org.bson.types.CodeWScope; -import org.bson.types.Symbol; -import org.grails.datastore.mapping.config.AbstractGormMappingFactory; -import org.grails.datastore.mapping.config.Property; -import org.grails.datastore.mapping.document.config.Collection; -import org.grails.datastore.mapping.document.config.DocumentMappingContext; -import org.grails.datastore.mapping.model.AbstractClassMapping; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.EmbeddedPersistentEntity; -import org.grails.datastore.mapping.model.IdentityMapping; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.MappingFactory; -import org.grails.datastore.mapping.model.PersistentEntity; - -import com.mongodb.DBRef; - -/** - * Models a {@link org.grails.datastore.mapping.model.MappingContext} for Mongo. - * - * @author Graeme Rocher - */ -@SuppressWarnings("rawtypes") -public class MongoMappingContext extends DocumentMappingContext { - /** - * Java types supported as mongo property types. - */ - private static final Set MONGO_NATIVE_TYPES = Collections.unmodifiableSet(new HashSet(Arrays.asList( - Double.class.getName(), - String.class.getName(), - com.mongodb.DBObject.class.getName(), - org.bson.types.Binary.class.getName(), - org.bson.types.ObjectId.class.getName(), - DBRef.class.getName(), - Boolean.class.getName(), - Date.class.getName(), - Pattern.class.getName(), - Symbol.class.getName(), - Integer.class.getName(), - BSONTimestamp.class.getName(), - Code.class.getName(), - CodeWScope.class.getName(), - Long.class.getName(), - UUID.class.getName(), - byte[].class.getName(), - Byte.class.getName() - ))); - - /** - * Check whether a type is a native mongo type that can be stored by the mongo driver without conversion. - * @param clazz The class to check. - * @return true if no conversion is required and the type can be stored natively. - */ - public static boolean isMongoNativeType(Class clazz) { - return MongoMappingContext.MONGO_NATIVE_TYPES.contains(clazz.getName()) || - DBObject.class.isAssignableFrom(clazz.getClass()); - } - - private final class MongoDocumentMappingFactory extends - AbstractGormMappingFactory { - @Override - protected Class getPropertyMappedFormType() { - return MongoAttribute.class; - } - - @Override - protected Class getEntityMappedFormType() { - return MongoCollection.class; - } - - @Override - protected IdentityMapping getIdentityMappedForm(final ClassMapping classMapping, final MongoAttribute property) { - if (property == null) { - return super.getIdentityMappedForm(classMapping, property); - } - - return new IdentityMapping() { - public String[] getIdentifierName() { - if (property.getName() == null) { - return new String[] { MappingFactory.IDENTITY_PROPERTY }; - } - return new String[] { property.getName()}; - } - - public ClassMapping getClassMapping() { - return classMapping; - } - - public Property getMappedForm() { - return property; - } - }; - } - - @Override - public boolean isSimpleType(Class propType) { - if (propType == null) return false; - if (propType.isArray()) { - return isSimpleType(propType.getComponentType()) || super.isSimpleType(propType); - } - return isMongoNativeType(propType) || super.isSimpleType(propType); - } - } - - public MongoMappingContext(String defaultDatabaseName) { - super(defaultDatabaseName); - } - - public MongoMappingContext(String defaultDatabaseName, Closure defaultMapping) { - super(defaultDatabaseName, defaultMapping); - } - - @Override - protected MappingFactory createDocumentMappingFactory(Closure defaultMapping) { - MongoDocumentMappingFactory mongoDocumentMappingFactory = new MongoDocumentMappingFactory(); - mongoDocumentMappingFactory.setDefaultMapping(defaultMapping); - return mongoDocumentMappingFactory; - } - - @Override - public PersistentEntity createEmbeddedEntity(Class type) { - return new DocumentEmbeddedPersistentEntity(type, this); - } - - class DocumentEmbeddedPersistentEntity extends EmbeddedPersistentEntity { - - private DocumentCollectionMapping classMapping ; - public DocumentEmbeddedPersistentEntity(Class type, MappingContext ctx) { - super(type, ctx); - classMapping = new DocumentCollectionMapping(this, ctx); - } - - @Override - public ClassMapping getMapping() { - return classMapping; - } - public class DocumentCollectionMapping extends AbstractClassMapping { - private Collection mappedForm; - - public DocumentCollectionMapping(PersistentEntity entity, MappingContext context) { - super(entity, context); - this.mappedForm = (Collection) context.getMappingFactory().createMappedForm(DocumentEmbeddedPersistentEntity.this); - } - @Override - public Collection getMappedForm() { - return mappedForm ; - } - } - } -} diff --git a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoEntityPersister.java b/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoEntityPersister.java deleted file mode 100644 index 6250beb06..000000000 --- a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoEntityPersister.java +++ /dev/null @@ -1,862 +0,0 @@ -/* Copyright (C) 2010 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.mapping.mongo.engine; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.bson.BSONObject; -import org.bson.types.ObjectId; -import org.grails.datastore.mapping.core.IdentityGenerationException; -import org.grails.datastore.mapping.core.OptimisticLockingException; -import org.grails.datastore.mapping.core.SessionImplementor; -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.NativeEntryEntityPersister; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.engine.PropertyValueIndexer; -import org.grails.datastore.mapping.model.EmbeddedPersistentEntity; -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.PropertyMapping; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.model.types.EmbeddedCollection; -import org.grails.datastore.mapping.model.types.Identity; -import org.grails.datastore.mapping.model.types.ManyToMany; -import org.grails.datastore.mapping.mongo.MongoDatastore; -import org.grails.datastore.mapping.mongo.MongoSession; -import org.grails.datastore.mapping.mongo.config.MongoAttribute; -import org.grails.datastore.mapping.mongo.config.MongoMappingContext; -import org.grails.datastore.mapping.mongo.query.MongoQuery; -import org.grails.datastore.mapping.query.Query; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.TypeDescriptor; -import org.springframework.dao.DataAccessException; -import org.springframework.data.mongodb.core.DbCallback; -import org.springframework.data.mongodb.core.MongoTemplate; - -import com.mongodb.BasicDBList; -import com.mongodb.BasicDBObject; -import com.mongodb.CommandResult; -import com.mongodb.DB; -import com.mongodb.DBCollection; -import com.mongodb.DBCursor; -import com.mongodb.DBObject; -import com.mongodb.DBRef; -import com.mongodb.MongoException; -import com.mongodb.WriteConcern; -import com.mongodb.WriteResult; - -/** - * A {@link org.grails.datastore.mapping.engine.EntityPersister} implementation for the Mongo document store - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class MongoEntityPersister extends NativeEntryEntityPersister { - - static Logger log = LoggerFactory.getLogger(MongoEntityPersister.class); - - private static final String NEXT_ID_SUFFIX = ".next_id"; - private boolean hasNumericalIdentifier = false; - private boolean hasStringIdentifier = false; - - public static final String MONGO_ID_FIELD = "_id"; - public static final String MONGO_CLASS_FIELD = "_class"; - - public MongoEntityPersister(MappingContext mappingContext, PersistentEntity entity, - MongoSession mongoSession, ApplicationEventPublisher publisher) { - super(mappingContext, entity, mongoSession, publisher); - MongoDatastore datastore = (MongoDatastore) mongoSession.getDatastore(); - - if (!(entity instanceof EmbeddedPersistentEntity)) { - - PersistentProperty identity = entity.getIdentity(); - if (identity != null) { - hasNumericalIdentifier = Long.class.isAssignableFrom(identity.getType()); - hasStringIdentifier = String.class.isAssignableFrom(identity.getType()); - } - } - } - - @Override - protected void refreshObjectStateFromNativeEntry(PersistentEntity persistentEntity, Object obj, Serializable nativeKey, DBObject nativeEntry, boolean isEmbedded) { - if (isEmbedded) { - Object id = nativeEntry.get(MONGO_ID_FIELD); - super.refreshObjectStateFromNativeEntry(persistentEntity, obj, (Serializable) id, nativeEntry, isEmbedded); - } - else { - super.refreshObjectStateFromNativeEntry(persistentEntity, obj, nativeKey, nativeEntry, isEmbedded); - } - } - - @Override - protected DBObject getEmbedded(DBObject nativeEntry, String key) { - final Object embeddedDocument = nativeEntry.get(key); - if (embeddedDocument instanceof DBObject) { - return (DBObject) embeddedDocument; - } - return null; - } - - @Override - protected void setEmbedded(DBObject nativeEntry, String key, DBObject embeddedEntry) { - nativeEntry.put(key, embeddedEntry); - } - - @Override - protected void setEmbeddedCollection(final DBObject nativeEntry, final String key, Collection instances, List embeddedEntries) { - if (instances == null || instances.isEmpty()) { - nativeEntry.put(key, null); - return; - } - - nativeEntry.put(key, embeddedEntries); - } - - /** - * Implementors who want to support one-to-many associations embedded should implement this method - * - * @param association The association - * @param ea - * @param nativeEntry - * @return A list of keys loaded from the embedded instance - */ - @Override - protected List loadEmbeddedCollectionKeys(Association association, EntityAccess ea, DBObject nativeEntry) { - if (nativeEntry == null) { - return super.loadEmbeddedCollectionKeys(association, ea, nativeEntry); - } - - Object entry = nativeEntry.get(getPropertyKey(association)); - List keys = new ArrayList(); - if (entry instanceof List) { - List entries = (List) entry; - for (Object o : entries) { - if (o instanceof DBRef) { - DBRef dbref = (DBRef) o; - keys.add(dbref.getId()); - } - else if (o != null) { - keys.add(o); - } - else { - keys.add(null); - } - } - } - return keys; - } - - @Override - protected void setEmbeddedCollectionKeys(Association association, EntityAccess embeddedEntityAccess, DBObject embeddedEntry, List keys) { - List dbRefs = new ArrayList(); - boolean reference = isReference(association); - for (Object foreignKey : keys) { - if (reference) { - dbRefs.add(new DBRef((DB) session.getNativeInterface(), getCollectionName(association.getAssociatedEntity()), foreignKey)); - } else { - dbRefs.add(foreignKey); - } - } - embeddedEntry.put(association.getName(), dbRefs); - } - - @Override - protected void loadEmbeddedCollection(EmbeddedCollection embeddedCollection, - EntityAccess ea, Object embeddedInstances, String propertyKey) { - - Collection instances; - if (List.class.isAssignableFrom(embeddedCollection.getType())) { - instances = new ArrayList(); - } - else { - instances = new HashSet(); - } - - if (embeddedInstances instanceof List) { - List list = (List)embeddedInstances; - for (Object dbo : list) { - if (dbo instanceof BasicDBObject) { - BasicDBObject nativeEntry = (BasicDBObject)dbo; - Object instance = - createObjectFromEmbeddedNativeEntry(embeddedCollection.getAssociatedEntity(), nativeEntry); - instances.add(instance); - } - } - } - - ea.setProperty(embeddedCollection.getName(), instances); - } - - @Override - protected boolean isEmbeddedEntry(Object entry) { - return entry instanceof DBObject; - } - - public Query createQuery() { - return new MongoQuery((MongoSession) getSession(), getPersistentEntity()); - } - - @Override - protected boolean doesRequirePropertyIndexing() { - return false; - } - - @Override - protected List retrieveAllEntities(PersistentEntity persistentEntity, - Iterable keys) { - - Query query = session.createQuery(persistentEntity.getJavaClass()); - - PersistentProperty identity = persistentEntity.getIdentity(); - if (keys instanceof List) { - List actualKeys = new ArrayList(); - Iterator iterator = keys.iterator(); - while (iterator.hasNext()) { - Object key = iterator.next(); - Object id = getIdentifierForKey(key); - actualKeys.add(id); - - } - query.in(identity.getName(), actualKeys); - } - else { - List keyList = new ArrayList(); - for (Serializable key : keys) { - keyList.add(key); - } - query.in(identity.getName(), keyList); - } - - List entityResults = new ArrayList(); - Iterator keyIterator = keys.iterator(); - Map resultMap = new HashMap(); - for (Object o : query.list()) { - if (o instanceof DBObject) { - DBObject dbo = (DBObject) o; - o = createObjectFromNativeEntry(getPersistentEntity(), (Serializable) dbo.get(MONGO_ID_FIELD), dbo); - } - resultMap.put(getObjectIdentifier(o), o); - } - while (keyIterator.hasNext()) { - Object key = getIdentifierForKey(keyIterator.next()); - ConversionService conversionService = getMappingContext().getConversionService(); - key = conversionService.convert(key, identity.getType()); - Object o = resultMap.get(key); - entityResults.add(o); // may add null, so entityResults list size matches input list size. - } - - return entityResults; - } - - private Object getIdentifierForKey(Object key) { - Object id = key; - if (key instanceof DBRef) { - DBRef ref = (DBRef) key; - id = ref.getId(); - } - return id; - } - - @Override - protected List retrieveAllEntities(PersistentEntity persistentEntity, Serializable[] keys) { - return retrieveAllEntities(persistentEntity, Arrays.asList(keys)); - } - - @Override - public String getEntityFamily() { - return getMongoSession().getCollectionName(getPersistentEntity()); - } - - @Override - protected void deleteEntry(String family, final Object key, final Object entry) { - getMongoTemplate().execute(new DbCallback() { - public Object doInDB(DB con) throws MongoException, DataAccessException { - DBCollection dbCollection = getCollection(con); - - DBObject dbo = createDBObjectWithKey(key); - MongoSession mongoSession = (MongoSession) session; - WriteConcern writeConcern = mongoSession.getDeclaredWriteConcern(getPersistentEntity()); - if (writeConcern != null) { - dbCollection.remove(dbo, writeConcern); - } else { - dbCollection.remove(dbo); - } - return null; - } - - protected DBCollection getCollection(DB con) { - return con.getCollection(getCollectionName(getPersistentEntity())); - } - }); - } - - protected MongoTemplate getMongoTemplate() { - return getMongoSession().getMongoTemplate(getPersistentEntity()); - } - - @Override - protected Object generateIdentifier(final PersistentEntity persistentEntity, final DBObject nativeEntry) { - return getMongoTemplate().execute(new DbCallback() { - public Object doInDB(DB con) throws MongoException, DataAccessException { - - String collectionName = getCollectionName(persistentEntity, nativeEntry); - - DBCollection dbCollection = con.getCollection(collectionName + NEXT_ID_SUFFIX); - - // If there is a numeric identifier then we need to rely on optimistic concurrency controls to obtain a unique identifer - // sequence. If the identifier is not numeric then we assume BSON ObjectIds. - if (hasNumericalIdentifier) { - - int attempts = 0; - while (true) { - DBObject result = dbCollection.findAndModify(new BasicDBObject(MONGO_ID_FIELD, collectionName), null, null, false, new BasicDBObject("$inc", new BasicDBObject("next_id", 1)), true, true); - // result should never be null and we shouldn't come back with an error ,but you never know. We should just retry if this happens... - if (result != null && con.getLastError().ok()) { - long nextId = getMappingContext().getConversionService().convert(result.get("next_id"), Long.class); - nativeEntry.put(MONGO_ID_FIELD, nextId); - break; - } - else { - attempts++; - if(attempts > 3) { - throw new IdentityGenerationException("Unable to generate identity using findAndModify after 3 attempts: " + con.getLastError().getErrorMessage()); - } - } - } - - return nativeEntry.get(MONGO_ID_FIELD); - } - - ObjectId objectId = ObjectId.get(); - if (ObjectId.class.isAssignableFrom(persistentEntity.getIdentity().getType())) { - nativeEntry.put(MONGO_ID_FIELD, objectId); - return objectId; - } - - String stringId = objectId.toString(); - nativeEntry.put(MONGO_ID_FIELD, stringId); - return stringId; - } - }); - } - - @Override - public PropertyValueIndexer getPropertyIndexer(PersistentProperty property) { - // We don't need to implement this for Mongo since Mongo automatically creates indexes for us - return null; - } - - @Override - public AssociationIndexer getAssociationIndexer(DBObject nativeEntry, Association association) { - return new MongoAssociationIndexer(nativeEntry, association, (MongoSession) session); - } - - @Override - protected DBObject createNewEntry(String family) { - BasicDBObject dbo = new BasicDBObject(); - PersistentEntity persistentEntity = getPersistentEntity(); - if (!persistentEntity.isRoot()) { - dbo.put(MONGO_CLASS_FIELD, persistentEntity.getDiscriminator()); - } - - return dbo; - } - - @Override - protected Object getEntryValue(DBObject nativeEntry, String property) { - Object value = nativeEntry.get(property); - if (value instanceof DBRef) { - return getIdentifierForKey(value); - } - return value; - } - - @Override - protected Object formulateDatabaseReference(PersistentEntity persistentEntity, Association association, Serializable associationId) { - DB db = (DB) session.getNativeInterface(); - boolean isReference = isReference(association); - if (isReference) { - return new DBRef(db, getCollectionName(association.getAssociatedEntity()), associationId); - } - return associationId; - } - - private boolean isReference(Association association) { - PropertyMapping mapping = association.getMapping(); - if (mapping != null) { - MongoAttribute attribute = (MongoAttribute) mapping.getMappedForm(); - if (attribute != null) { - return attribute.isReference(); - } - } - return true; - } - - @Override - protected void setEntryValue(DBObject nativeEntry, String key, Object value) { - MappingContext mappingContext = getMappingContext(); - setDBObjectValue(nativeEntry, key, value, mappingContext); - } - - @Override - protected String getPropertyKey(PersistentProperty prop) { - if (prop instanceof Identity) { - return MONGO_ID_FIELD; - } - return super.getPropertyKey(prop); - } - - public static void setDBObjectValue(DBObject nativeEntry, String key, Object value, MappingContext mappingContext) { - Object nativeValue = getSimpleNativePropertyValue(value, mappingContext); - nativeEntry.put(key, nativeValue); - } - - /** - * Convert a value into a type suitable for use in Mongo. Collections and maps are converted recursively. The - * mapping context is used for the conversion if possible, otherwise toString() is the eventual fallback. - * @param value The value to convert (or null) - * @param mappingContext The mapping context. - * @return The converted value (or null) - */ - public static Object getSimpleNativePropertyValue(Object value, MappingContext mappingContext) { - Object nativeValue; - - if (value == null || mappingContext.isPersistentEntity(value)) { - nativeValue = null; - } else if (MongoMappingContext.isMongoNativeType(value.getClass())) { - // easy case, no conversion required. - // Checked first in case any of these types (such as BasicDBObject) are instances of collections - // or arrays, etc.! - nativeValue = value; - } else if (value.getClass().isArray()) { - Object[] array = (Object[]) value; - List nativeColl = new ArrayList(array.length); - for (Object item : array) { - nativeColl.add(getSimpleNativePropertyValue(item, mappingContext)); - } - nativeValue = nativeColl; - } else if (value instanceof Collection) { - Collection existingColl = (Collection)value; - List nativeColl = new ArrayList(existingColl.size()); - for (Object item : existingColl) { - nativeColl.add(getSimpleNativePropertyValue(item, mappingContext)); - } - nativeValue = nativeColl; - } else if (value instanceof Map) { - Map existingMap = (Map)value; - Map newMap = new LinkedHashMap(); - for (Map.Entry entry :existingMap.entrySet()) { - newMap.put(entry.getKey(), getSimpleNativePropertyValue(entry.getValue(), mappingContext)); - } - nativeValue = newMap; - } else { - nativeValue = convertPrimitiveToNative(value, mappingContext); - } - return nativeValue; - } - - private static Object convertPrimitiveToNative(Object item, MappingContext mappingContext) { - Object nativeValue; - if (item != null) { - ConversionService conversionService = mappingContext.getConversionService(); - // go for toInteger or toString. - TypeDescriptor itemTypeDescriptor = TypeDescriptor.forObject(item); - if ((itemTypeDescriptor.getObjectType() == Integer.class || itemTypeDescriptor.getObjectType() == Short.class) && conversionService.canConvert(itemTypeDescriptor, TypeDescriptor.valueOf(Integer.class))) { - nativeValue = conversionService.convert(item, Integer.class); - } else if (conversionService.canConvert(itemTypeDescriptor, TypeDescriptor.valueOf(String.class))) { - nativeValue = conversionService.convert(item, String.class); - } else { - // fall back if no explicit converter is registered, good for URL, Locale, etc. - nativeValue = item.toString(); - } - } else { - nativeValue = null; - } - return nativeValue; - } - - @Override - protected PersistentEntity discriminatePersistentEntity(PersistentEntity persistentEntity, DBObject nativeEntry) { - final Object o = nativeEntry.get(MONGO_CLASS_FIELD); - if (o != null) { - final String className = o.toString(); - final PersistentEntity childEntity = getMappingContext().getChildEntityByDiscriminator(persistentEntity.getRootEntity(), className); - if (childEntity != null) { - return childEntity; - } - } - return super.discriminatePersistentEntity(persistentEntity, nativeEntry); - } - - @Override - protected DBObject retrieveEntry(final PersistentEntity persistentEntity, - String family, final Serializable key) { - return getMongoTemplate().execute(new DbCallback() { - public DBObject doInDB(DB con) throws MongoException, DataAccessException { - DBCollection dbCollection = con.getCollection(getCollectionName(persistentEntity)); - return dbCollection.findOne(createDBObjectWithKey(key)); - } - }); - } - - private DBObject removeNullEntries(DBObject nativeEntry) { - for (String key : new HashSet(nativeEntry.keySet())) { - Object o = nativeEntry.get(key); - if (o == null) { - nativeEntry.removeField(key); - } else if (o instanceof Object[]) { - for (Object o2 : (Object[])o) { - if (o2 instanceof DBObject) { - removeNullEntries((DBObject)o2); - } - } - } else if (o instanceof List) { - for (Object o2 : (List)o) { - if (o2 instanceof DBObject) { - removeNullEntries((DBObject)o2); - } - } - } else if (o instanceof DBObject) { - removeNullEntries((DBObject)o); - } - } - return nativeEntry; - } - - @Override - protected Object storeEntry(final PersistentEntity persistentEntity, final EntityAccess entityAccess, - final Object storeId, final DBObject nativeEntry) { - return getMongoTemplate().execute(new DbCallback() { - public Object doInDB(DB con) throws MongoException, DataAccessException { - removeNullEntries(nativeEntry); - nativeEntry.put(MONGO_ID_FIELD, storeId); - return nativeEntry.get(MONGO_ID_FIELD); - } - }); - } - - public String getCollectionName(PersistentEntity persistentEntity) { - return getCollectionName(persistentEntity, null); - } - - private String getCollectionName(PersistentEntity persistentEntity, DBObject nativeEntry) { - String collectionName; - if (persistentEntity.isRoot()) { - MongoSession mongoSession = (MongoSession) getSession(); - collectionName = mongoSession.getCollectionName(persistentEntity); - } - else { - MongoSession mongoSession = (MongoSession) getSession(); - collectionName = mongoSession.getCollectionName(persistentEntity.getRootEntity()); - } - return collectionName; - } - - private DBObject modifyNullsToUnsets(DBObject nativeEntry) { - DBObject unsets = new BasicDBObject(); - DBObject sets = new BasicDBObject(); - for (String key : nativeEntry.keySet()) { - Object o = nativeEntry.get(key); - if (o == null) { - unsets.put(key, 1); - } else if ("_id".equals(key)) { - } else if (o instanceof Object[]) { - sets.put(key, o); - for (Object o2 : (Object[])o) { - if (o2 instanceof DBObject) { - removeNullEntries((DBObject)o2); - } - } - } else if (o instanceof List) { - sets.put(key, o); - for (Object o2 : (List)o) { - if (o2 instanceof DBObject) { - removeNullEntries((DBObject)o2); - } - } - } else if (o instanceof DBObject) { - sets.put(key, removeNullEntries((DBObject)o)); - } else { - sets.put(key, o); - } - } - DBObject newEntry = new BasicDBObject(); - newEntry.put("$set", sets); - if (!unsets.keySet().isEmpty()) { - newEntry.put("$unset", unsets); - } - return newEntry; - } - - @Override - public void updateEntry(final PersistentEntity persistentEntity, final EntityAccess ea, - final Object key, final DBObject entry) { - getMongoTemplate().execute(new DbCallback() { - public Object doInDB(DB con) throws MongoException, DataAccessException { - String collectionName = getCollectionName(persistentEntity, entry); - DBCollection dbCollection = con.getCollection(collectionName); - DBObject dbo = createDBObjectWithKey(key); - - boolean versioned = isVersioned(ea); - if (versioned) { - Object currentVersion = getCurrentVersion(ea); - incrementVersion(ea); - // query for old version to ensure atomicity - if (currentVersion != null) { - dbo.put("version", currentVersion); - } - } - - DBObject newEntry = modifyNullsToUnsets(entry); - - MongoSession mongoSession = (MongoSession) session; - WriteConcern writeConcern = mongoSession.getDeclaredWriteConcern(getPersistentEntity()); - WriteResult result; - if (writeConcern != null) { - result = dbCollection.update(dbo, newEntry, false, false, writeConcern); - } - else { - result = dbCollection.update(dbo, newEntry, false, false); - } - if (versioned && !((SessionImplementor)getSession()).isStateless(persistentEntity)) { - // ok, we need to check whether the write worked: - // note that this will use the standard write concern unless it wasn't at least ACKNOWLEDGE: - CommandResult error = result.getLastError(WriteConcern.ACKNOWLEDGED); - // may as well handle any networking errors: - error.throwOnError(); - // if the document count "n" of the update was 0, the versioning check must have failed: - if (error.getInt("n") == 0) { - throw new OptimisticLockingException(persistentEntity, key); - } - } - return null; - } - }); - } - - @Override - protected void setManyToMany(PersistentEntity persistentEntity, Object obj, - DBObject nativeEntry, ManyToMany manyToMany, Collection associatedObjects, - Map> toManyKeys) { - - List ids = new ArrayList(); - if (associatedObjects != null) { - for (Object o : associatedObjects) { - if (o == null) { - ids.add(null); - } - else { - PersistentEntity childPersistentEntity = - getMappingContext().getPersistentEntity(o.getClass().getName()); - EntityAccess entityAccess = createEntityAccess(childPersistentEntity, o); - ids.add(entityAccess.getIdentifier()); - } - } - } - - nativeEntry.put(manyToMany.getName() + "_$$manyToManyIds", ids); - } - - @Override - protected Collection getManyToManyKeys(PersistentEntity persistentEntity, Object object, - Serializable nativeKey, DBObject nativeEntry, ManyToMany manyToMany) { - return (Collection)nativeEntry.get(manyToMany.getName() + "_$$manyToManyIds"); - } - - protected Object getCurrentVersion(final EntityAccess ea) { - Object currentVersion = ea.getProperty("version"); - if (Number.class.isAssignableFrom(ea.getPropertyType("version"))) { - currentVersion = currentVersion != null ? ((Number)currentVersion).longValue() : currentVersion; - } - return currentVersion; - } - - @Override - protected void deleteEntries(String family, final List keys) { - getMongoTemplate().execute(new DbCallback() { - public Object doInDB(DB con) throws MongoException, DataAccessException { - String collectionName = getCollectionName(getPersistentEntity()); - DBCollection dbCollection = con.getCollection(collectionName); - - MongoSession mongoSession = (MongoSession) getSession(); - MongoQuery query = mongoSession.createQuery(getPersistentEntity().getJavaClass()); - query.in(getPersistentEntity().getIdentity().getName(), keys); - - dbCollection.remove(query.getMongoQuery()); - - return null; - } - }); - } - - @Override - protected void cascadeDeleteCollection(EntityAccess entityAccess, Association association) { - Object propValue = entityAccess.getProperty(association.getName()); - if (!(propValue instanceof Collection)) { - return; - } - Collection collection = ((Collection) propValue); - Persister persister = null; - for (Iterator iter = collection.iterator(); iter.hasNext(); ) { - Object child = iter.next(); - if (child == null) { - log.warn("Encountered a null associated reference while cascade-deleting '{}' as part of {} (ID {})", - association.getReferencedPropertyName(), entityAccess.getEntity().getClass().getName(), entityAccess.getIdentifier()); - continue; - } - if(persister == null) { - persister = session.getPersister(child); - } - persister.delete(child); - iter.remove(); - } - } - - protected DBObject createDBObjectWithKey(Object key) { - DBObject dbo = new BasicDBObject(); - if (hasNumericalIdentifier || hasStringIdentifier) { - dbo.put(MONGO_ID_FIELD, key); - } - else { - if (key instanceof ObjectId) { - dbo.put(MONGO_ID_FIELD, key); - } - else { - dbo.put(MONGO_ID_FIELD, new ObjectId(key.toString())); - } - } - return dbo; - } - - @Override - public boolean isDirty(Object instance, Object entry) { - if (super.isDirty(instance, entry)) { - return true; - } - - DBObject dbo = (DBObject)entry; - PersistentEntity entity = getPersistentEntity(); - - EntityAccess entityAccess = createEntityAccess(entity, instance, dbo); - - DBObject cached = (DBObject)((SessionImplementor)getSession()).getCachedEntry( - entity, (Serializable)entityAccess.getIdentifier(), true); - - return !dbo.equals(cached); - } - - public MongoSession getMongoSession() { - return (MongoSession) getSession(); - } - - private class MongoAssociationIndexer implements AssociationIndexer { - private DBObject nativeEntry; - private Association association; - private MongoSession session; - private boolean isReference = true; - - public MongoAssociationIndexer(DBObject nativeEntry, Association association, MongoSession session) { - this.nativeEntry = nativeEntry; - this.association = association; - this.session = session; - this.isReference = isReference(association); - } - - public void preIndex(final Object primaryKey, final List foreignKeys) { - // if the association is a unidirectional one-to-many we store the keys - // embedded in the owning entity, otherwise we use a foreign key - if (!association.isBidirectional()) { - DB db = session.getNativeInterface(); - List dbRefs = new ArrayList(); - for (Object foreignKey : foreignKeys) { - if (isReference) { - dbRefs.add(new DBRef(db, getCollectionName(association.getAssociatedEntity()), foreignKey)); - } - else { - dbRefs.add(foreignKey); - } - } - // update the native entry directly. - nativeEntry.put(association.getName(), dbRefs); - } - } - - public void index(final Object primaryKey, final List foreignKeys) { - // indexing is handled by putting the data in the native entry before it is persisted, see preIndex above. - } - - public List query(Object primaryKey) { - // for a unidirectional one-to-many we use the embedded keys - if (!association.isBidirectional()) { - final Object indexed = nativeEntry.get(association.getName()); - if (!(indexed instanceof Collection)) { - return Collections.emptyList(); - } - List indexedList = getIndexedAssociationsAsList(indexed); - - if (associationsAreDbRefs(indexedList)) { - return extractIdsFromDbRefs(indexedList); - } - return indexedList; - } - // for a bidirectional one-to-many we use the foreign key to query the inverse side of the association - Association inverseSide = association.getInverseSide(); - Query query = session.createQuery(association.getAssociatedEntity().getJavaClass()); - query.eq(inverseSide.getName(), primaryKey); - query.projections().id(); - return query.list(); - } - - public PersistentEntity getIndexedEntity() { - return association.getAssociatedEntity(); - } - - public void index(Object primaryKey, Object foreignKey) { - // TODO: Implement indexing of individual entities - } - - private List getIndexedAssociationsAsList(Object indexed) { - return (indexed instanceof List) ? (List) indexed : new ArrayList(((Collection) indexed)); - } - - private boolean associationsAreDbRefs(List indexedList) { - return !indexedList.isEmpty() && (indexedList.get(0) instanceof DBRef); - } - - private List extractIdsFromDbRefs(List indexedList) { - List resolvedDbRefs = new ArrayList(); - for (Object indexedAssociation : indexedList) { - resolvedDbRefs.add(((DBRef) indexedAssociation).getId()); - } - return resolvedDbRefs; - } - } -} diff --git a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/query/MongoQuery.java b/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/query/MongoQuery.java deleted file mode 100644 index 4eafe643f..000000000 --- a/grails-datastore-mongo/src/main/groovy/org/grails/datastore/mapping/mongo/query/MongoQuery.java +++ /dev/null @@ -1,1051 +0,0 @@ -/* Copyright (C) 2010 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.mapping.mongo.query; - -import java.io.Serializable; -import java.util.*; -import java.util.regex.Pattern; - -import org.grails.datastore.mapping.core.SessionImplementor; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.internal.MappingUtils; -import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller; -import org.grails.datastore.mapping.model.EmbeddedPersistentEntity; -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.Custom; -import org.grails.datastore.mapping.model.types.Embedded; -import org.grails.datastore.mapping.model.types.EmbeddedCollection; -import org.grails.datastore.mapping.model.types.ToOne; -import org.grails.datastore.mapping.mongo.MongoSession; -import org.grails.datastore.mapping.mongo.config.MongoAttribute; -import org.grails.datastore.mapping.mongo.config.MongoCollection; -import org.grails.datastore.mapping.mongo.engine.MongoEntityPersister; -import org.grails.datastore.mapping.query.AssociationQuery; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.Restrictions; -import org.grails.datastore.mapping.query.api.QueryArgumentsAware; -import org.grails.datastore.mapping.query.projections.ManualProjections; -import org.springframework.dao.DataAccessException; -import org.springframework.dao.InvalidDataAccessResourceUsageException; -import org.springframework.data.mongodb.core.DbCallback; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.util.StringUtils; - -import com.mongodb.BasicDBObject; -import com.mongodb.DB; -import com.mongodb.DBCollection; -import com.mongodb.DBCursor; -import com.mongodb.DBObject; -import com.mongodb.MongoException; - -/** - * A {@link org.grails.datastore.mapping.query.Query} implementation for the Mongo document store. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class MongoQuery extends Query implements QueryArgumentsAware { - - private static Map queryHandlers = new HashMap(); - private static Map negatedHandlers = new HashMap(); - - public static final String MONGO_IN_OPERATOR = "$in"; - public static final String MONGO_OR_OPERATOR = "$or"; - public static final String MONGO_AND_OPERATOR = "$and"; - public static final String MONGO_GTE_OPERATOR = "$gte"; - public static final String MONGO_LTE_OPERATOR = "$lte"; - public static final String MONGO_GT_OPERATOR = "$gt"; - public static final String MONGO_LT_OPERATOR = "$lt"; - public static final String MONGO_NE_OPERATOR = "$ne"; - public static final String MONGO_NIN_OPERATOR = "$nin"; - public static final String MONGO_ID_REFERENCE_SUFFIX = ".$id"; - public static final String MONGO_WHERE_OPERATOR = "$where"; - - private static final String MONGO_THIS_PREFIX = "this."; - public static final String HINT_ARGUMENT = "hint"; - - private Map queryArguments = Collections.emptyMap(); - - public static final String NEAR_OEPRATOR = "$near"; - - public static final String BOX_OPERATOR = "$box"; - - public static final String POLYGON_OPERATOR = "$polygon"; - - public static final String WITHIN_OPERATOR = "$within"; - - public static final String CENTER_OPERATOR = "$center"; - - static { - queryHandlers.put(IdEquals.class, new QueryHandler() { - public void handle(PersistentEntity entity, IdEquals criterion, DBObject query) { - query.put(MongoEntityPersister.MONGO_ID_FIELD, criterion.getValue()); - } - }); - - queryHandlers.put(AssociationQuery.class, new QueryHandler() { - public void handle(PersistentEntity entity, AssociationQuery criterion, DBObject query) { - Association association = criterion.getAssociation(); - PersistentEntity associatedEntity = association.getAssociatedEntity(); - if (association instanceof EmbeddedCollection) { - BasicDBObject associationCollectionQuery = new BasicDBObject(); - populateMongoQuery(associatedEntity, associationCollectionQuery, criterion.getCriteria()); - BasicDBObject collectionQuery = new BasicDBObject("$elemMatch", associationCollectionQuery); - String propertyKey = getPropertyName(entity, association.getName()); - query.put(propertyKey, collectionQuery); - } - else if (associatedEntity instanceof EmbeddedPersistentEntity || association instanceof Embedded ) { - BasicDBObject associatedEntityQuery = new BasicDBObject(); - populateMongoQuery(associatedEntity, associatedEntityQuery, criterion.getCriteria()); - for (String property : associatedEntityQuery.keySet()) { - String propertyKey = getPropertyName(entity, association.getName()); - query.put(propertyKey + '.' + property, associatedEntityQuery.get(property)); - } - } - else { - throw new UnsupportedOperationException("Join queries are not supported by MongoDB"); - } - } - }); - - queryHandlers.put(Equals.class, new QueryHandler() { - public void handle(PersistentEntity entity, Equals criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - Object value = criterion.getValue(); - MongoEntityPersister.setDBObjectValue(query, propertyName, value, entity.getMappingContext()); - } - }); - - queryHandlers.put(IsNull.class, new QueryHandler() { - @SuppressWarnings("unchecked") - public void handle(PersistentEntity entity, IsNull criterion, DBObject query) { - queryHandlers.get(Equals.class).handle(entity, new Equals(criterion.getProperty(), null), query); - } - }); - queryHandlers.put(IsNotNull.class, new QueryHandler() { - @SuppressWarnings("unchecked") - public void handle(PersistentEntity entity, IsNotNull criterion, DBObject query) { - queryHandlers.get(NotEquals.class).handle(entity, new NotEquals(criterion.getProperty(), null), query); - } - }); - queryHandlers.put(EqualsProperty.class, new QueryHandler() { - public void handle(PersistentEntity entity, EqualsProperty criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - String otherPropertyName = getPropertyName(entity, criterion.getOtherProperty()); - addWherePropertyComparison(query, propertyName, otherPropertyName, "=="); - } - }); - queryHandlers.put(NotEqualsProperty.class, new QueryHandler() { - public void handle(PersistentEntity entity, NotEqualsProperty criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - String otherPropertyName = getPropertyName(entity, criterion.getOtherProperty()); - addWherePropertyComparison(query, propertyName, otherPropertyName, "!="); - } - }); - queryHandlers.put(GreaterThanProperty.class, new QueryHandler() { - public void handle(PersistentEntity entity, GreaterThanProperty criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - String otherPropertyName = getPropertyName(entity, criterion.getOtherProperty()); - addWherePropertyComparison(query, propertyName, otherPropertyName, ">"); - } - }); - queryHandlers.put(LessThanProperty.class, new QueryHandler() { - public void handle(PersistentEntity entity, LessThanProperty criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - String otherPropertyName = getPropertyName(entity, criterion.getOtherProperty()); - addWherePropertyComparison(query, propertyName, otherPropertyName, "<"); - } - }); - queryHandlers.put(GreaterThanEqualsProperty.class, new QueryHandler() { - public void handle(PersistentEntity entity, GreaterThanEqualsProperty criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - String otherPropertyName = getPropertyName(entity, criterion.getOtherProperty()); - addWherePropertyComparison(query, propertyName, otherPropertyName, ">="); - } - }); - queryHandlers.put(LessThanEqualsProperty.class, new QueryHandler() { - public void handle(PersistentEntity entity, LessThanEqualsProperty criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - String otherPropertyName = getPropertyName(entity, criterion.getOtherProperty()); - addWherePropertyComparison(query, propertyName, otherPropertyName, "<="); - } - }); - - queryHandlers.put(NotEquals.class, new QueryHandler() { - public void handle(PersistentEntity entity, NotEquals criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - DBObject notEqualQuery = getOrCreatePropertyQuery(query, propertyName); - MongoEntityPersister.setDBObjectValue(notEqualQuery, MONGO_NE_OPERATOR, criterion.getValue(), entity.getMappingContext()); - - query.put(propertyName, notEqualQuery); - } - }); - - queryHandlers.put(Like.class, new QueryHandler() { - public void handle(PersistentEntity entity, Like like, DBObject query) { - handleLike(entity, like, query, true); - } - }); - - queryHandlers.put(ILike.class, new QueryHandler() { - public void handle(PersistentEntity entity, ILike like, DBObject query) { - handleLike(entity, like, query, false); - } - }); - - queryHandlers.put(RLike.class, new QueryHandler() { - public void handle(PersistentEntity entity, RLike like, DBObject query) { - Object value = like.getValue(); - if (value == null) value = "null"; - final String expr = value.toString(); - Pattern regex = Pattern.compile(expr); - String propertyName = getPropertyName(entity, like); - query.put(propertyName, regex); - } - }); - - queryHandlers.put(In.class, new QueryHandler() { - public void handle(PersistentEntity entity, In in, DBObject query) { - DBObject inQuery = new BasicDBObject(); - List values = getInListQueryValues(entity, in); - inQuery.put(MONGO_IN_OPERATOR, values); - String propertyName = getPropertyName(entity, in); - query.put(propertyName, inQuery); - } - }); - - queryHandlers.put(Near.class, new QueryHandler() { - public void handle(PersistentEntity entity, Near near, DBObject query) { - DBObject nearQuery = new BasicDBObject(); - MongoEntityPersister.setDBObjectValue(nearQuery, NEAR_OEPRATOR, near.getValues(), entity.getMappingContext()); - String propertyName = getPropertyName(entity, near); - query.put(propertyName, nearQuery); - } - }); - - queryHandlers.put(WithinBox.class, new QueryHandler() { - public void handle(PersistentEntity entity, WithinBox withinBox, DBObject query) { - DBObject nearQuery = new BasicDBObject(); - DBObject box = new BasicDBObject(); - MongoEntityPersister.setDBObjectValue(box, BOX_OPERATOR, withinBox.getValues(), entity.getMappingContext()); - nearQuery.put(WITHIN_OPERATOR, box); - String propertyName = getPropertyName(entity, withinBox); - query.put(propertyName, nearQuery); - } - }); - - queryHandlers.put(WithinPolygon.class, new QueryHandler() { - public void handle(PersistentEntity entity, WithinPolygon withinPolygon, DBObject query) { - DBObject nearQuery = new BasicDBObject(); - DBObject box = new BasicDBObject(); - MongoEntityPersister.setDBObjectValue(box, POLYGON_OPERATOR, withinPolygon.getValues(), entity.getMappingContext()); - nearQuery.put(WITHIN_OPERATOR, box); - String propertyName = getPropertyName(entity, withinPolygon); - query.put(propertyName, nearQuery); - } - }); - - queryHandlers.put(WithinCircle.class, new QueryHandler() { - public void handle(PersistentEntity entity, WithinCircle withinCentre, DBObject query) { - DBObject nearQuery = new BasicDBObject(); - DBObject center = new BasicDBObject(); - MongoEntityPersister.setDBObjectValue(center, CENTER_OPERATOR, withinCentre.getValues(), entity.getMappingContext()); - nearQuery.put(WITHIN_OPERATOR, center); - String propertyName = getPropertyName(entity, withinCentre); - query.put(propertyName, nearQuery); - } - }); - - queryHandlers.put(Between.class, new QueryHandler() { - public void handle(PersistentEntity entity, Between between, DBObject query) { - DBObject betweenQuery = new BasicDBObject(); - MongoEntityPersister.setDBObjectValue(betweenQuery, MONGO_GTE_OPERATOR, between.getFrom(), entity.getMappingContext()); - MongoEntityPersister.setDBObjectValue(betweenQuery, MONGO_LTE_OPERATOR, between.getTo(), entity.getMappingContext()); - String propertyName = getPropertyName(entity, between); - query.put(propertyName, betweenQuery); - } - }); - - queryHandlers.put(GreaterThan.class, new QueryHandler() { - public void handle(PersistentEntity entity, GreaterThan criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - DBObject greaterThanQuery = getOrCreatePropertyQuery(query, propertyName); - MongoEntityPersister.setDBObjectValue(greaterThanQuery, MONGO_GT_OPERATOR, criterion.getValue(), entity.getMappingContext()); - - query.put(propertyName, greaterThanQuery); - } - }); - - queryHandlers.put(GreaterThanEquals.class, new QueryHandler() { - public void handle(PersistentEntity entity, GreaterThanEquals criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - DBObject greaterThanQuery = getOrCreatePropertyQuery(query, propertyName); - MongoEntityPersister.setDBObjectValue(greaterThanQuery, MONGO_GTE_OPERATOR, criterion.getValue(), entity.getMappingContext()); - - query.put(propertyName, greaterThanQuery); - } - }); - - queryHandlers.put(LessThan.class, new QueryHandler() { - public void handle(PersistentEntity entity, LessThan criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - DBObject lessThanQuery = getOrCreatePropertyQuery(query, propertyName); - MongoEntityPersister.setDBObjectValue(lessThanQuery, MONGO_LT_OPERATOR, criterion.getValue(), entity.getMappingContext()); - - query.put(propertyName, lessThanQuery); - } - }); - - queryHandlers.put(LessThanEquals.class, new QueryHandler() { - public void handle(PersistentEntity entity, LessThanEquals criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - DBObject lessThanQuery = getOrCreatePropertyQuery(query, propertyName); - MongoEntityPersister.setDBObjectValue(lessThanQuery, MONGO_LTE_OPERATOR, criterion.getValue(), entity.getMappingContext()); - - query.put(propertyName, lessThanQuery); - } - }); - - queryHandlers.put(Conjunction.class, new QueryHandler() { - public void handle(PersistentEntity entity, Conjunction criterion, DBObject query) { - populateMongoQuery(entity, query, criterion); - } - }); - - queryHandlers.put(Negation.class, new QueryHandler() { - @SuppressWarnings("unchecked") - public void handle(PersistentEntity entity, Negation criteria, DBObject query) { - for (Criterion criterion : criteria.getCriteria()) { - final QueryHandler queryHandler = negatedHandlers.get(criterion.getClass()); - if (queryHandler != null) { - queryHandler.handle(entity, criterion, query); - } - else { - throw new UnsupportedOperationException("Query of type "+criterion.getClass().getSimpleName()+" cannot be negated"); - } - } - } - }); - - queryHandlers.put(Disjunction.class, new QueryHandler() { - @SuppressWarnings("unchecked") - public void handle(PersistentEntity entity, Disjunction criterion, DBObject query) { - populateMongoQuery(entity, query, criterion); - } - }); - - negatedHandlers.put(Equals.class, new QueryHandler() { - @SuppressWarnings("unchecked") - public void handle(PersistentEntity entity, Equals criterion, DBObject query) { - queryHandlers.get(NotEquals.class).handle(entity, Restrictions.ne(criterion.getProperty(), criterion.getValue()), query); - } - }); - - negatedHandlers.put(NotEquals.class, new QueryHandler() { - @SuppressWarnings("unchecked") - public void handle(PersistentEntity entity, NotEquals criterion, DBObject query) { - queryHandlers.get(Equals.class).handle(entity, Restrictions.eq(criterion.getProperty(), criterion.getValue()), query); - } - }); - - negatedHandlers.put(In.class, new QueryHandler() { - public void handle(PersistentEntity entity, In in, DBObject query) { - Object nativePropertyValue = getInListQueryValues(entity, in); - String property = getPropertyName(entity, in); - DBObject inQuery = getOrCreatePropertyQuery(query, property); - inQuery.put(MONGO_NIN_OPERATOR, nativePropertyValue); - query.put(property, inQuery); - } - }); - - negatedHandlers.put(Between.class, new QueryHandler() { - public void handle(PersistentEntity entity, Between between, DBObject query) { - String property = getPropertyName(entity, between); - DBObject betweenQuery = getOrCreatePropertyQuery(query, property); - betweenQuery.put(MONGO_LTE_OPERATOR, between.getFrom()); - betweenQuery.put(MONGO_GTE_OPERATOR, between.getTo()); - query.put(property, betweenQuery); - } - }); - - negatedHandlers.put(GreaterThan.class, new QueryHandler() { - @SuppressWarnings("unchecked") - public void handle(PersistentEntity entity, GreaterThan criterion, DBObject query) { - queryHandlers.get(LessThan.class).handle(entity, Restrictions.lt(criterion.getProperty(), criterion.getValue()), query); - } - }); - - negatedHandlers.put(GreaterThanEquals.class, new QueryHandler() { - @SuppressWarnings("unchecked") - public void handle(PersistentEntity entity, GreaterThanEquals criterion, DBObject query) { - queryHandlers.get(LessThanEquals.class).handle(entity, Restrictions.lte(criterion.getProperty(), criterion.getValue()), query); - } - }); - - negatedHandlers.put(LessThan.class, new QueryHandler() { - @SuppressWarnings("unchecked") - public void handle(PersistentEntity entity, LessThan criterion, DBObject query) { - queryHandlers.get(GreaterThan.class).handle(entity, Restrictions.gt(criterion.getProperty(), criterion.getValue()), query); - } - }); - - negatedHandlers.put(LessThanEquals.class, new QueryHandler() { - @SuppressWarnings("unchecked") - public void handle(PersistentEntity entity, LessThanEquals criterion, DBObject query) { - queryHandlers.get(GreaterThanEquals.class).handle(entity, Restrictions.gte(criterion.getProperty(), criterion.getValue()), query); - } - }); - } - - private static DBObject getOrCreatePropertyQuery(DBObject query, String propertyName) { - Object existing = query.get(propertyName); - DBObject queryObject = existing instanceof DBObject ? (DBObject) existing : null; - if (queryObject == null) { - queryObject = new BasicDBObject(); - } - return queryObject; - } - - private static void addWherePropertyComparison(DBObject query, String propertyName, String otherPropertyName, String operator) { - query.put(MONGO_WHERE_OPERATOR, new StringBuilder(MONGO_THIS_PREFIX).append(propertyName).append(operator).append(MONGO_THIS_PREFIX).append(otherPropertyName).toString()); - } - - /** - * Get the list of native values to use in the query. This converts entities to ids and other types to - * their persisted types. - * @param entity The entity - * @param in The criterion - * @return The list of native values suitable for passing to Mongo. - */ - private static List getInListQueryValues(PersistentEntity entity, In in) { - List values = new ArrayList(in.getValues().size()); - for (Object value : in.getValues()) { - if (entity.getMappingContext().isPersistentEntity(value)) { - PersistentEntity pe = entity.getMappingContext().getPersistentEntity( - value.getClass().getName()); - values.add(new EntityAccess(pe, value).getIdentifier()); - } else { - value = MongoEntityPersister.getSimpleNativePropertyValue(value, entity.getMappingContext()); - values.add(value); - } - } - return values; - } - - private static void handleLike(PersistentEntity entity, Like like, DBObject query, boolean caseSensitive) { - Object value = like.getValue(); - if (value == null) value = "null"; - - String[] array = value.toString().split("%", -1); - for (int i=0; i() { - @SuppressWarnings("unchecked") - public List doInDB(DB db) throws MongoException, DataAccessException { - - final DBCollection collection = db.getCollection(mongoEntityPersister.getCollectionName(entity)); - if (uniqueResult) { - final DBObject dbObject; - if (criteria.isEmpty()) { - if (entity.isRoot()) { - dbObject = collection.findOne(); - } - else { - dbObject = collection.findOne(new BasicDBObject( - MongoEntityPersister.MONGO_CLASS_FIELD, entity.getDiscriminator())); - } - } - else { - dbObject = collection.findOne(getMongoQuery()); - } - return wrapObjectResultInList(createObjectFromDBObject(dbObject)); - } - - DBCursor cursor = null; - DBObject query = createQueryObject(entity); - - final List projectionList = projections().getProjectionList(); - if (projectionList.isEmpty()) { - cursor = executeQuery(entity, criteria, collection, query); - return (List)new MongoResultList(cursor,offset, mongoEntityPersister).clone(); - } - - List projectedResults = new ArrayList(); - for (Projection projection : projectionList) { - if (projection instanceof CountProjection) { - // For some reason the below doesn't return the expected result whilst executing the query and returning the cursor does - //projectedResults.add(collection.getCount(query)); - if (cursor == null) { - cursor = executeQuery(entity, criteria, collection, query); - } - projectedResults.add(cursor.size()); - } - else if (projection instanceof MinProjection) { - if (cursor == null) { - cursor = executeQuery(entity, criteria, collection, query); - } - MinProjection mp = (MinProjection) projection; - - MongoResultList results = new MongoResultList(cursor,offset, mongoEntityPersister); - projectedResults.add(manualProjections.min((Collection) results.clone(), getPropertyName(entity, mp.getPropertyName()))); - } - else if (projection instanceof MaxProjection) { - if (cursor == null) { - cursor = executeQuery(entity, criteria, collection, query); - } - MaxProjection mp = (MaxProjection) projection; - - MongoResultList results = new MongoResultList(cursor,offset, mongoEntityPersister); - projectedResults.add(manualProjections.max((Collection) results.clone(), getPropertyName(entity, mp.getPropertyName()))); - } - else if (projection instanceof CountDistinctProjection) { - if (cursor == null) { - cursor = executeQuery(entity, criteria, collection, query); - } - CountDistinctProjection mp = (CountDistinctProjection) projection; - - MongoResultList results = new MongoResultList(cursor, offset,mongoEntityPersister); - projectedResults.add(manualProjections.countDistinct((Collection) results.clone(), getPropertyName(entity, mp.getPropertyName()))); - - } - else if ((projection instanceof DistinctPropertyProjection) || (projection instanceof PropertyProjection) || (projection instanceof IdProjection)) { - final boolean distinct = (projection instanceof DistinctPropertyProjection); - final PersistentProperty persistentProperty; - final String propertyName; - if (projection instanceof IdProjection) { - persistentProperty = entity.getIdentity(); - propertyName = MongoEntityPersister.MONGO_ID_FIELD; - } - else { - PropertyProjection pp = (PropertyProjection) projection; - persistentProperty = entity.getPropertyByName(pp.getPropertyName()); - propertyName = getPropertyName(entity, persistentProperty.getName()); - } - if (persistentProperty != null) { - populateMongoQuery(entity, query, criteria); - - List propertyResults = null; - if (max > -1) { - // if there is a limit then we have to do a manual projection since the MongoDB driver doesn't support limits and distinct together - cursor = executeQueryAndApplyPagination(collection, query); - if (distinct) { - propertyResults = new ArrayList(manualProjections.distinct(new MongoResultList(cursor, offset,mongoEntityPersister), propertyName)); - } - else { - propertyResults = manualProjections.property(new MongoResultList(cursor,offset, mongoEntityPersister), propertyName); - } - } - else { - if (distinct || (projection instanceof IdProjection)) { - propertyResults = collection.distinct(propertyName, query); - } - else { - - DBCursor propertyCursor = collection.find(query, new BasicDBObject(propertyName, 1)); - ArrayList projectedProperties = new ArrayList(); - while(propertyCursor.hasNext()) { - DBObject dbo = propertyCursor.next(); - projectedProperties.add(dbo.get(propertyName)); - } - - propertyResults = projectedProperties; - } - } - - if (persistentProperty instanceof ToOne) { - Association a = (Association) persistentProperty; - propertyResults = session.retrieveAll(a.getAssociatedEntity().getJavaClass(), propertyResults); - } - - if (projectedResults.size() == 0 && projectionList.size() == 1) { - return propertyResults; - } - projectedResults.add(propertyResults); - } - else { - throw new InvalidDataAccessResourceUsageException("Cannot use [" + - projection.getClass().getSimpleName() + - "] projection on non-existent property: " + propertyName); - } - } - } - - return projectedResults; - } - - protected DBCursor executeQuery(final PersistentEntity entity, - final Junction criteria, final DBCollection collection, DBObject query) { - final DBCursor cursor; - if (criteria.isEmpty()) { - cursor = executeQueryAndApplyPagination(collection, query); - } - else { - populateMongoQuery(entity, query, criteria); - cursor = executeQueryAndApplyPagination(collection, query); - } - - if (queryArguments != null) { - if (queryArguments.containsKey(HINT_ARGUMENT)) { - Object hint = queryArguments.get(HINT_ARGUMENT); - if (hint instanceof Map) { - cursor.hint(new BasicDBObject((Map)hint)); - } - else if (hint != null) { - cursor.hint(hint.toString()); - } - } - } - return cursor; - } - - protected DBCursor executeQueryAndApplyPagination(final DBCollection collection, DBObject query) { - final DBCursor cursor; - cursor = collection.find(query); - if (offset > 0) { - cursor.skip(offset); - } - if (max > -1) { - cursor.limit(max); - } - - if (!orderBy.isEmpty()) { - DBObject orderObject = new BasicDBObject(); - for (Order order : orderBy) { - String property = order.getProperty(); - property = getPropertyName(entity, property); - orderObject.put(property, order.getDirection() == Order.Direction.DESC ? -1 : 1); - } - cursor.sort(orderObject); - } - else { - MongoCollection coll = (MongoCollection) entity.getMapping().getMappedForm(); - if (coll != null && coll.getSort() != null) { - DBObject orderObject = new BasicDBObject(); - Order order = coll.getSort(); - String property = order.getProperty(); - property = getPropertyName(entity, property); - orderObject.put(property, order.getDirection() == Order.Direction.DESC ? -1 : 1); - cursor.sort(orderObject); - } - } - - return cursor; - } - }); - } - - private DBObject createQueryObject(PersistentEntity persistentEntity) { - DBObject query; - if (persistentEntity.isRoot()) { - query = new BasicDBObject(); - } - else { - query = new BasicDBObject(MongoEntityPersister.MONGO_CLASS_FIELD, persistentEntity.getDiscriminator()); - } - return query; - } - - @SuppressWarnings("unchecked") - public static void populateMongoQuery(PersistentEntity entity, DBObject query, Junction criteria) { - - List subList = null; - // if a query combines more than 1 item, wrap the items in individual $and or $or arguments - // so that property names can't clash (e.g. for an $and containing two $ors) - if (criteria.getCriteria().size() > 1) { - if (criteria instanceof Disjunction) { - subList = new ArrayList(); - query.put(MONGO_OR_OPERATOR, subList); - } else if (criteria instanceof Conjunction) { - subList = new ArrayList(); - query.put(MONGO_AND_OPERATOR, subList); - } - } - for (Criterion criterion : criteria.getCriteria()) { - final QueryHandler queryHandler = queryHandlers.get(criterion.getClass()); - if (queryHandler != null) { - DBObject dbo = query; - if (subList != null) { - dbo = new BasicDBObject(); - subList.add(dbo); - } - - if (criterion instanceof PropertyCriterion) { - PropertyCriterion pc = (PropertyCriterion) criterion; - PersistentProperty property = entity.getPropertyByName(pc.getProperty()); - if (property instanceof Custom) { - CustomTypeMarshaller customTypeMarshaller = ((Custom) property).getCustomTypeMarshaller(); - customTypeMarshaller.query(property, pc, query); - continue; - } - } - queryHandler.handle(entity, criterion, dbo); - } - else { - throw new InvalidDataAccessResourceUsageException("Queries of type "+criterion.getClass().getSimpleName()+" are not supported by this implementation"); - } - } - } - - protected static String getPropertyName(PersistentEntity entity, PropertyNameCriterion criterion) { - String propertyName = criterion.getProperty(); - return getPropertyName(entity, propertyName); - } - - private static String getPropertyName(PersistentEntity entity, String propertyName) { - if (entity.isIdentityName(propertyName)) { - propertyName = MongoEntityPersister.MONGO_ID_FIELD; - } - else { - PersistentProperty property = entity.getPropertyByName(propertyName); - if (property != null) { - propertyName = MappingUtils.getTargetKey(property); - if (property instanceof ToOne && !(property instanceof Embedded)) { - ToOne association = (ToOne) property; - MongoAttribute attr = (MongoAttribute) association.getMapping().getMappedForm(); - boolean isReference = attr == null || attr.isReference(); - if (isReference) { - propertyName = propertyName + MONGO_ID_REFERENCE_SUFFIX; - } - } - } - } - - return propertyName; - } - - private Object createObjectFromDBObject(DBObject dbObject) { - // we always use the session cached version where available. - final Object id = dbObject.get(MongoEntityPersister.MONGO_ID_FIELD); - Class type = mongoEntityPersister.getPersistentEntity().getJavaClass(); - Object instance = mongoSession.getCachedInstance(type, (Serializable) id); - if (instance == null) { - instance = mongoEntityPersister.createObjectFromNativeEntry( - mongoEntityPersister.getPersistentEntity(), (Serializable) id, dbObject); - mongoSession.cacheInstance(type, (Serializable) id, instance); - } - // note cached instances may be stale, but user can call 'refresh' to fix that. - return instance; - } - - @SuppressWarnings("unchecked") - private List wrapObjectResultInList(Object object) { - List result = new ArrayList(); - result.add(object); - return result; - } - - /** - * Geospacial query for values near the given two dimensional list - * - * @param property The property - * @param value A two dimensional list of values - * @return this - */ - public Query near(String property, List value) { - add(new Near(property, value)); - return this; - } - - /** - * Geospacial query for values within a given box. A box is defined as a multi-dimensional list in the form - * - * [[40.73083, -73.99756], [40.741404, -73.988135]] - * - * @param property The property - * @param value A multi-dimensional list of values - * @return This query - */ - public Query withinBox(String property, List value) { - add(new WithinBox(property, value)); - return this; - } - - /** - * Geospacial query for values within a given polygon. A polygon is defined as a multi-dimensional list in the form - * - * [[0, 0], [3, 6], [6, 0]] - * - * @param property The property - * @param value A multi-dimensional list of values - * @return This query - */ - public Query withinPolygon(String property, List value) { - add(new WithinPolygon(property, value)); - return this; - } - - /** - * Geospacial query for values within a given circle. A circle is defined as a multi-dimensial list containing the position of the center and the radius: - * - * [[50, 50], 10] - * - * @param property The property - * @param value A multi-dimensional list of values - * @return This query - */ - public Query withinCircle(String property, List value) { - add(new WithinBox(property, value)); - return this; - } - - /** - * @param arguments The query arguments - */ - public void setArguments(Map arguments) { - this.queryArguments = arguments; - } - - /** - * Used for Geospacial querying - * - * @author Graeme Rocher - * @since 1.0 - */ - public static class Near extends PropertyCriterion { - - public Near(String name, List value) { - super(name, value); - } - - public List getValues() { - return (List) getValue(); - } - - public void setValue(List value) { - this.value = value; - } - } - - /** - * Used for Geospacial querying of boxes - * - * @author Graeme Rocher - * @since 1.0 - */ - public static class WithinBox extends PropertyCriterion { - - public WithinBox(String name, List value) { - super(name, value); - } - - public List getValues() { - return (List) getValue(); - } - - public void setValue(List matrix) { - this.value = matrix; - } - } - - /** - * Used for Geospacial querying of polygons - */ - public static class WithinPolygon extends PropertyCriterion { - - public WithinPolygon(String name, List value) { - super(name, value); - } - - public List getValues() { - return (List) getValue(); - } - - public void setValue(List value) { - this.value = value; - } - } - - /** - * Used for Geospacial querying of circles - * - * @author Graeme Rocher - * @since 1.0 - */ - public static class WithinCircle extends PropertyCriterion { - - public WithinCircle(String name, List value) { - super(name, value); - } - - public List getValues() { - return (List) getValue(); - } - - public void setValue(List matrix) { - this.value = matrix; - } - } - - private static interface QueryHandler { - public void handle(PersistentEntity entity, T criterion, DBObject query); - } - - @SuppressWarnings("serial") - public static class MongoResultList extends AbstractList { - - private MongoEntityPersister mongoEntityPersister; - private DBCursor cursor; - private int offset = 0; - private int internalIndex; - private List initializedObjects = new ArrayList(); - private Integer size; - - @SuppressWarnings("unchecked") - public MongoResultList(DBCursor cursor, int offset, MongoEntityPersister mongoEntityPersister) { - this.cursor = cursor; - this.mongoEntityPersister = mongoEntityPersister; - this.offset = offset; - } - - @SuppressWarnings("unchecked") - @Override - public Object get(int index) { - if(initializedObjects.size() > index) { - return initializedObjects.get(index); - } - else { - while(cursor.hasNext()) { - if(internalIndex > index) throw new ArrayIndexOutOfBoundsException("Cannot retrieve element at index " + index + " for cursor size " + size()); - Object o = convertDBObject(cursor.next()); - initializedObjects.add(internalIndex,o); - if(index == internalIndex++) { - return o; - } - } - } - throw new ArrayIndexOutOfBoundsException("Cannot retrieve element at index " + index + " for cursor size " + size()); - } - - @Override - public Object set(int index, Object o) { - if(index > (size()-1)) { - throw new ArrayIndexOutOfBoundsException("Cannot set element at index " + index + " for cursor size " + size()); - } - else { - // initialize - get(index); - return initializedObjects.set(index, o); - } - } - - /** - * Override to transform elements if necessary during iteration. - * @return an iterator over the elements in this list in proper sequence - */ - @Override - public Iterator iterator() { - final DBCursor cursor = this.cursor.copy(); - cursor.skip(offset); - return new Iterator() { - public boolean hasNext() { - return cursor.hasNext(); - } - - @SuppressWarnings("unchecked") - public Object next() { - Object object = cursor.next(); - if (object instanceof DBObject) { - object = convertDBObject(object); - } - return object; - } - - public void remove() { - throw new UnsupportedOperationException("Method remove() not supported by MongoResultList iterator"); - } - }; - } - - @Override - public int size() { - if(this.size == null) { - this.size = cursor.size(); - } - return size; - } - - protected Object convertDBObject(Object object) { - final DBObject dbObject = (DBObject) object; - Object id = dbObject.get(MongoEntityPersister.MONGO_ID_FIELD); - SessionImplementor session = (SessionImplementor) mongoEntityPersister.getSession(); - Class type = mongoEntityPersister.getPersistentEntity().getJavaClass(); - Object instance = session.getCachedInstance(type, (Serializable) id); - if (instance == null) { - instance = mongoEntityPersister.createObjectFromNativeEntry( - mongoEntityPersister.getPersistentEntity(), (Serializable) id, dbObject); - session.cacheInstance(type, (Serializable) id, instance); - } - return instance; - } - - @SuppressWarnings("unchecked") - @Override - public Object clone() { - return new MongoResultList(cursor,offset, mongoEntityPersister); - } - } -} diff --git a/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/AbstractMongoTest.groovy b/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/AbstractMongoTest.groovy deleted file mode 100644 index c876847b5..000000000 --- a/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/AbstractMongoTest.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package org.grails.datastore.mapping.mongo - -import org.junit.Before -import org.springframework.context.support.GenericApplicationContext - -abstract class AbstractMongoTest { - - protected MongoDatastore md - - @Before - void setUp() { - md = new MongoDatastore() - def ctx = new GenericApplicationContext() - ctx.refresh() - md.applicationContext = ctx - md.afterPropertiesSet() - } -} diff --git a/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/BasicPersistenceSpec.groovy b/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/BasicPersistenceSpec.groovy deleted file mode 100644 index 66727b3fa..000000000 --- a/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/BasicPersistenceSpec.groovy +++ /dev/null @@ -1,51 +0,0 @@ -package org.grails.datastore.mapping.mongo - -import org.junit.Test - -class BasicPersistenceSpec extends AbstractMongoTest { - - @Test - void testBasicPersistenceOperations() { - md.mappingContext.addPersistentEntity(TestEntity) - - MongoSession session = md.connect() - - session.nativeInterface.dropDatabase() - - def te = new TestEntity(name:"Bob") - - session.persist te - session.flush() - - assert te != null - assert te.id != null - assert te.id instanceof Long - - session.clear() - te = session.retrieve(TestEntity, te.id) - - assert te != null - assert te.name == "Bob" - - te.name = "Fred" - session.persist(te) - session.flush() - session.clear() - - te = session.retrieve(TestEntity, te.id) - assert te != null - assert te.id != null - assert te.name == 'Fred' - - session.delete te - session.flush() - - te = session.retrieve(TestEntity, te.id) - assert te == null - } -} - -class TestEntity { - Long id - String name -} diff --git a/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/EnumPersistenceSpec.groovy b/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/EnumPersistenceSpec.groovy deleted file mode 100644 index 3ab07ffce..000000000 --- a/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/EnumPersistenceSpec.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package org.grails.datastore.mapping.mongo - -import org.junit.Test - -class EnumPersistenceSpec extends AbstractMongoTest { - - @Test - void testBasicPersistenceOperations() { - md.mappingContext.addPersistentEntity(TestEnumEntity) - - MongoSession session = md.connect() - - session.nativeInterface.dropDatabase() - - def te = new TestEnumEntity(name:"Bob", type:TestType.T1) - - session.persist te - session.flush() - - assert te != null - assert te.id != null - assert te.id instanceof Long - - session.clear() - te = session.retrieve(TestEnumEntity, te.id) - - assert te != null - assert te instanceof TestEnumEntity - assert te.name == "Bob" - assert te.type instanceof TestType - assert te.type == TestType.T1 - - te.type = TestType.T2 - session.persist(te) - session.flush() - session.clear() - - te = session.retrieve(TestEnumEntity, te.id) - assert te != null - assert te.type == TestType.T2 - } -} - -class TestEnumEntity { - Long id - String name - TestType type -} - -enum TestType { - T1, T2, T3 -} diff --git a/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/LongIdTests.groovy b/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/LongIdTests.groovy deleted file mode 100644 index 78329d34b..000000000 --- a/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/LongIdTests.groovy +++ /dev/null @@ -1,61 +0,0 @@ -package org.grails.datastore.mapping.mongo - -import org.junit.Test - -class LongIdTests extends AbstractMongoTest { - - @Test - void testBasicPersistenceOperations() { - md.mappingContext.addPersistentEntity(MongoLongIdEntity) - - MongoSession session = md.connect() - - session.nativeInterface.dropDatabase() - - def te = new MongoLongIdEntity(name:"Bob") - - session.persist te - session.flush() - - assert te != null - assert te.id != null - assert te.id instanceof Long - assert te.id == 1 - - long previousId = te.id - - session.clear() - te = session.retrieve(MongoLongIdEntity, te.id) - - assert te != null - assert te.name == "Bob" - - te.name = "Fred" - session.persist(te) - session.flush() - session.clear() - - te = session.retrieve(MongoLongIdEntity, te.id) - assert te != null - assert te.id != null - assert te.name == 'Fred' - - session.delete te - session.flush() - - te = session.retrieve(MongoLongIdEntity, te.id) - assert te == null - - // check increment - te = new MongoLongIdEntity(name:'Bob 2') - session.persist te - session.flush() - - assert te.id == 2 - } -} - -class MongoLongIdEntity { - Long id - String name -} diff --git a/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/ObjectIdTests.groovy b/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/ObjectIdTests.groovy deleted file mode 100644 index e0ca7212d..000000000 --- a/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/ObjectIdTests.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package org.grails.datastore.mapping.mongo - -import org.bson.types.ObjectId -import org.junit.Test - -class ObjectIdTests extends AbstractMongoTest { - - @Test - void testBasicPersistenceOperations() { - md.mappingContext.addPersistentEntity(MongoObjectIdEntity) - - MongoSession session = md.connect() - - session.nativeInterface.dropDatabase() - - def te = new MongoObjectIdEntity(name:"Bob") - - session.persist te - session.flush() - - assert te != null - assert te.id != null - assert te.id instanceof ObjectId - - session.clear() - te = session.retrieve(MongoObjectIdEntity, te.id) - - assert te != null - assert te.name == "Bob" - - te.name = "Fred" - session.persist(te) - session.flush() - session.clear() - - te = session.retrieve(MongoObjectIdEntity, te.id) - assert te != null - assert te.id != null - assert te.name == 'Fred' - - session.delete te - session.flush() - - te = session.retrieve(MongoObjectIdEntity, te.id) - assert te == null - } -} - -class MongoObjectIdEntity { - ObjectId id - String name -} diff --git a/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/StringIdTests.groovy b/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/StringIdTests.groovy deleted file mode 100644 index b66871839..000000000 --- a/grails-datastore-mongo/src/test/groovy/org/grails/datastore/mapping/mongo/StringIdTests.groovy +++ /dev/null @@ -1,51 +0,0 @@ -package org.grails.datastore.mapping.mongo - -import org.junit.Test - -class StringIdTests extends AbstractMongoTest { - - @Test - void testBasicPersistenceOperations() { - md.mappingContext.addPersistentEntity(MongoStringIdEntity) - - MongoSession session = md.connect() - - session.nativeInterface.dropDatabase() - - def te = new MongoStringIdEntity(name:"Bob") - - session.persist te - session.flush() - - assert te != null - assert te.id != null - assert te.id instanceof String - - session.clear() - te = session.retrieve(MongoStringIdEntity, te.id) - - assert te != null - assert te.name == "Bob" - - te.name = "Fred" - session.persist(te) - session.flush() - session.clear() - - te = session.retrieve(MongoStringIdEntity, te.id) - assert te != null - assert te.id != null - assert te.name == 'Fred' - - session.delete te - session.flush() - - te = session.retrieve(MongoStringIdEntity, te.id) - assert te == null - } -} - -class MongoStringIdEntity { - String id - String name -} diff --git a/grails-datastore-redis/TODO.txt b/grails-datastore-redis/TODO.txt deleted file mode 100644 index 0f0c36cf1..000000000 --- a/grails-datastore-redis/TODO.txt +++ /dev/null @@ -1,11 +0,0 @@ -TODO high priorities - -TODO medium priorities - -* Nested querying of associations in criteria -* Port as many GORM related tests from Grails core as possible - -TODO lower priorities - -* Embedded components -* JPA-QL for string based queries \ No newline at end of file diff --git a/grails-datastore-redis/build.gradle b/grails-datastore-redis/build.gradle deleted file mode 100644 index 16a3bb8d5..000000000 --- a/grails-datastore-redis/build.gradle +++ /dev/null @@ -1,10 +0,0 @@ -version = "1.0.0.BUILD-SNAPSHOT" - -dependencies { - compile project(":grails-datastore-core") - compile("commons-pool:commons-pool:1.5.5") - compile('redis.clients:jedis:2.0.0') { - transitive = false - } - testRuntime "org.springframework:spring-expression:$springVersion" -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/RedisDatastore.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/RedisDatastore.java deleted file mode 100644 index f77a39fe4..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/RedisDatastore.java +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis; - -import static org.grails.datastore.mapping.config.utils.ConfigUtils.read; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ConfigurableApplicationContext; -import org.grails.datastore.mapping.config.Property; -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.DatastoreUtils; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.PropertyValueIndexer; -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext; -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.query.Query; -import org.grails.datastore.mapping.redis.engine.RedisEntityPersister; -import org.grails.datastore.mapping.redis.util.JedisTemplate; -import org.grails.datastore.mapping.redis.util.RedisTemplate; -import org.springframework.util.ClassUtils; - -import redis.clients.jedis.JedisPool; -import redis.clients.jedis.JedisPoolConfig; - -/** - * A Datastore implementation for the Redis key/value datastore. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class RedisDatastore extends AbstractDatastore implements InitializingBean, DisposableBean { - - private static final boolean jedisClientAvailable = - ClassUtils.isPresent("redis.clients.jedis.Jedis", RedisSession.class.getClassLoader()); - - public static final String CONFIG_HOST = "host"; - public static final String CONFIG_TIMEOUT = "timeout"; - private static final String CONFIG_RESOURCE_COUNT = "resources"; - public static final String CONFIG_PORT = "port"; - public static final String CONFIG_PASSWORD = "password"; - - private static final String CONFIG_POOLED = "pooled"; - - public static final String DEFAULT_HOST = "localhost"; - public static final int DEFAULT_PORT = 6379; - private String host = DEFAULT_HOST; - private String password; - private int port = DEFAULT_PORT; - - private int timeout = 2000; - private boolean pooled = true; - private boolean backgroundIndex; - private JedisPool pool; - - public RedisDatastore() { - this(new KeyValueMappingContext("")); - } - - public RedisDatastore(MappingContext mappingContext) { - this(mappingContext, null, null); - } - - public RedisDatastore(MappingContext mappingContext, Map connectionDetails, - ConfigurableApplicationContext ctx) { - super(mappingContext, connectionDetails, ctx); - - int resourceCount = 10; - if (connectionDetails != null) { - host = read(String.class, CONFIG_HOST, connectionDetails, DEFAULT_HOST); - port = read(Integer.class, CONFIG_PORT, connectionDetails, DEFAULT_PORT); - timeout = read(Integer.class, CONFIG_TIMEOUT, connectionDetails, 2000); - pooled = read(Boolean.class, CONFIG_POOLED, connectionDetails, true); - password = read(String.class, CONFIG_PASSWORD, connectionDetails, null); - resourceCount = read(Integer.class, CONFIG_RESOURCE_COUNT, connectionDetails, resourceCount); - } - if (pooled && useJedis()) { - this.pool = JedisTemplateFactory.createPool(host, port, timeout, resourceCount, password); - } - - initializeConverters(mappingContext); - } - - private boolean useJedis() { - return jedisClientAvailable; - } - - public void destroy() throws Exception { - super.destroy(); - if (pool != null) { - pool.destroy(); - } - } - - static class JedisTemplateFactory { - static JedisPool pool; - - static JedisPool createPool(String host, int port, int timeout, int resources, String password) { - JedisPoolConfig poolConfig = new JedisPoolConfig(); - poolConfig.setMaxWait(timeout); - poolConfig.setMaxActive(resources); - poolConfig.setMaxIdle(5); - poolConfig.setMinIdle(1); - poolConfig.setTestOnBorrow(true); - poolConfig.setTestOnReturn(true); - poolConfig.setTestWhileIdle(true); - poolConfig.setNumTestsPerEvictionRun(10); - poolConfig.setTimeBetweenEvictionRunsMillis(60000); - - if (password != null) { - pool = new JedisPool(poolConfig, host, port, timeout, password); - } - else { - pool = new JedisPool(poolConfig, host, port, timeout); - } - return pool; - } - - static RedisTemplate create(String host, int port, int timeout, boolean pooled, String password) { - - JedisTemplate template; - - if (pooled) { - template = new JedisTemplate(pool); - } - else { - template = new JedisTemplate(host, port, timeout); - } - - if (password != null) { - template.setPassword(password); - } - - return template; - } - } - - /** - * Sets whether the Redis datastore should create indices in the background instead of on startup - * - * @param backgroundIndex True to create indices in the background - */ - public void setBackgroundIndex(boolean backgroundIndex) { - this.backgroundIndex = backgroundIndex; - } - - @Override - protected Session createSession(Map connDetails) { - if (!useJedis()) { - throw new IllegalStateException( - "Cannot create RedisSession. No Redis client library found on classpath. " + - "Please make sure you have the Jedis library on your classpath"); - } - - return new RedisSession(this, getMappingContext(), - JedisTemplateFactory.create(host, port, timeout, pooled, password), - getApplicationEventPublisher()); - } - - public void afterPropertiesSet() throws Exception { - if (backgroundIndex) { - new Thread(new IndexOperation()).start(); - } - else { - new IndexOperation().run(); - } - } - - /** - * Used to update indices on startup or when a new entity is added - */ - class IndexOperation implements Runnable { - - public void run() { - final Session session = RedisDatastore.this.connect(); - try { - - DatastoreUtils.bindSession(session); - - final Collection entities = RedisDatastore.this.getMappingContext().getPersistentEntities(); - for (PersistentEntity entity : entities) { - final List props = entity.getPersistentProperties(); - List indexed = new ArrayList(); - for (PersistentProperty prop : props) { - Property kv = (Property) prop.getMapping().getMappedForm(); - if (kv != null && kv.isIndex()) { - indexed.add(prop); - } - } - - if (!indexed.isEmpty()) { - // page through entities indexing each one - final Class cls = entity.getJavaClass(); - Query query = session.createQuery(cls); - query.projections().count(); - Long total = (Long) query.singleResult(); - - if (total < 100) { - List persistedObjects = session.createQuery(cls).list(); - for (Object persistedObject : persistedObjects) { - updatedPersistedObjectIndices(session, entity, persistedObject, indexed); - } - } - else { - query = session.createQuery(cls); - int offset = 0; - int max = 100; - - // 300+100 < 350 - while(offset < total) { - query.offset(offset); - query.max(max); - List persistedObjects = query.list(); - for (Object persistedObject : persistedObjects) { - updatedPersistedObjectIndices(session, entity, persistedObject, indexed); - } - - offset += max; - } - } - } - } - } - finally { - session.disconnect(); - } - } - - private void updatedPersistedObjectIndices(Session session, PersistentEntity entity, Object persistedObject, List indexed) { - EntityAccess ea = new EntityAccess(entity, persistedObject); - Object identifier = ea.getIdentifier(); - for (PersistentProperty persistentProperty : indexed) { - Object value = ea.getProperty(persistentProperty.getName()); - if (value != null) { - RedisEntityPersister persister = (RedisEntityPersister) session.getPersister(entity.getJavaClass()); - PropertyValueIndexer indexer = persister.getPropertyIndexer(persistentProperty); - indexer.index(value, identifier); - } - } - } - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/RedisEntry.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/RedisEntry.java deleted file mode 100644 index 1f870769d..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/RedisEntry.java +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis; - -import java.util.HashMap; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class RedisEntry extends HashMap { - - private static final long serialVersionUID = 1; - - protected String family; - - public RedisEntry(String family) { - this.family = family; - } - - public String getFamily() { - return family; - } - - @Override - public Object get(Object o) { - - final Object val = super.get(o); - if (val != null) { - return val; - } - return null; - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/RedisSession.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/RedisSession.java deleted file mode 100644 index 5a3b9fea8..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/RedisSession.java +++ /dev/null @@ -1,335 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis; - -import java.io.IOException; -import java.io.Serializable; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.persistence.FlushModeType; - -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.dao.CannotAcquireLockException; -import org.grails.datastore.mapping.core.AbstractSession; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.core.impl.PendingInsert; -import org.grails.datastore.mapping.core.impl.PendingOperation; -import org.grails.datastore.mapping.core.impl.PendingUpdate; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.LockableEntityPersister; -import org.grails.datastore.mapping.engine.NonPersistentTypeException; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.redis.collection.RedisSet; -import org.grails.datastore.mapping.redis.engine.RedisEntityPersister; -import org.grails.datastore.mapping.redis.util.RedisCallback; -import org.grails.datastore.mapping.redis.util.RedisTemplate; -import org.grails.datastore.mapping.transactions.Transaction; -import org.springframework.transaction.CannotCreateTransactionException; - -/** - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class RedisSession extends AbstractSession { - - private RedisTemplate redisTemplate; - - public RedisSession(Datastore ds, MappingContext mappingContext, RedisTemplate template, - ApplicationEventPublisher publisher) { - super(ds, mappingContext, publisher); - redisTemplate = template; - } - - @Override - protected void flushPendingInserts(final Map> inserts) { - // Optimizes saving multiple entities at once - for (final PersistentEntity entity : inserts.keySet()) { - final Collection pendingInserts = inserts.get(entity); - - final List> postOperations = new LinkedList>(); - - final RedisEntityPersister persister = (RedisEntityPersister)getPersister(entity); - - redisTemplate.pipeline(new RedisCallback() { - public Object doInRedis(RedisTemplate redis) throws IOException { - for (PendingInsert pendingInsert : pendingInserts) { - final EntityAccess entityAccess = pendingInsert.getEntityAccess(); - if (persister.cancelInsert(entity, entityAccess)) { - continue; - } - - List> preOperations = pendingInsert.getPreOperations(); - for (PendingOperation preOperation : preOperations) { - preOperation.run(); - } - - persister.storeEntry(entity, entityAccess, pendingInsert.getNativeKey(), - pendingInsert.getNativeEntry()); - persister.firePostInsertEvent(entity, entityAccess); - postOperations.addAll(pendingInsert.getCascadeOperations()); - } - for (PendingOperation pendingOperation : postOperations) { - pendingOperation.run(); - } - return null; - } - }); - } - } - - @Override - protected void flushPendingUpdates(Map> updates) { - // Optimizes saving multiple entities at once - for (final PersistentEntity entity : updates.keySet()) { - final Collection pendingInserts = updates.get(entity); - - final List> postOperations = new LinkedList>(); - - final RedisEntityPersister persister = (RedisEntityPersister)getPersister(entity); - - redisTemplate.pipeline(new RedisCallback() { - public Object doInRedis(RedisTemplate redis) throws IOException { - for (PendingUpdate pendingInsert : pendingInserts) { - final EntityAccess entityAccess = pendingInsert.getEntityAccess(); - if (persister.cancelUpdate(entity, entityAccess)) { - continue; - } - - List> preOperations = pendingInsert.getPreOperations(); - for (PendingOperation preOperation : preOperations) { - preOperation.run(); - } - - persister.updateEntry(entity, entityAccess, pendingInsert.getNativeKey(), - pendingInsert.getNativeEntry()); - persister.firePostUpdateEvent(entity, entityAccess); - postOperations.addAll(pendingInsert.getCascadeOperations()); - } - for (PendingOperation pendingOperation : postOperations) { - pendingOperation.run(); - } - return null; - } - }); - } - } - - @Override - protected Persister createPersister(Class cls, MappingContext mappingContext) { - PersistentEntity entity = mappingContext.getPersistentEntity(cls.getName()); - if (entity == null) { - return null; - } - - return new RedisEntityPersister(mappingContext, entity, this, redisTemplate, publisher); - } - - @Override - public void disconnect() { - try { - for (Object lockedObject : lockedObjects) { - unlock(lockedObject); - } - redisTemplate.close(); - } - finally { - super.disconnect(); - } - } - - @Override - protected Transaction beginTransactionInternal() { - try { - redisTemplate.multi(); - } - catch (Exception e) { - throw new CannotCreateTransactionException("Error starting Redis transaction: " + e.getMessage(), e); - } - return new RedisTransaction(redisTemplate); - } - - @Override - public void lock(Object o) { - LockableEntityPersister ep = (LockableEntityPersister)getPersister(o); - if (ep == null) { - throw new CannotAcquireLockException("Cannot lock object [" + o + "]. It is not a persistent instance!"); - } - - Serializable id = ep.getObjectIdentifier(o); - if (id == null) { - throw new CannotAcquireLockException("Cannot lock transient instance [" + o + "]"); - } - - ep.lock(id); - } - - @Override - public void unlock(Object o) { - if (o == null) { - return; - } - - LockableEntityPersister ep = (LockableEntityPersister)getPersister(o); - if (ep == null) { - return; - } - - ep.unlock(o); - lockedObjects.remove(o); - } - - @Override - public Object lock(Class type, Serializable key) { - LockableEntityPersister ep = (LockableEntityPersister)getPersister(type); - if (ep == null) { - throw new CannotAcquireLockException("Cannot lock key [" + key + "]. It is not a persistent instance!"); - } - - final Object lockedObject = ep.lock(key); - if (lockedObject != null) { - cacheObject(key, lockedObject); - lockedObjects.add(lockedObject); - } - return lockedObject; - } - - /** - * Returns a random entity for the given type - * - * @param type The entity type - * @return A random entity instance - */ - public Object random(Class type) { - flushIfNecessary(); - RedisEntityPersister ep = (RedisEntityPersister)getPersister(type); - if (ep == null) { - throw new NonPersistentTypeException("The class [" + type.getName() + "] is not a known persistent type."); - } - - RedisSet set = (RedisSet)ep.getAllEntityIndex(); - String id = set.random(); - return retrieve(type, id); - } - - /** - * Expires an instance - * - * @param instance The instance to expire - * @param ttl The time to live in seconds - */ - public void expire(Object instance, int ttl) { - if (instance == null) { - return; - } - - final RedisEntityPersister ep = (RedisEntityPersister)getPersister(instance); - if (ep == null) { - throw new NonPersistentTypeException("The class [" + instance.getClass().getName() - + "] is not a known persistent type."); - } - - final Serializable key = ep.getObjectIdentifier(instance); - if (key != null) { - expire(instance.getClass(), key, ttl); - } - } - - /** - * Expires an entity for the given type, identifier and time to live - * - * @param type The entity type - * @param key The entity key - * @param ttl The time to live in seconds - */ - public void expire(final Class type, final Serializable key, final int ttl) { - final RedisEntityPersister ep = (RedisEntityPersister)getPersister(type); - - if (ep == null) { - throw new NonPersistentTypeException("The class [" + type + "] is not a known persistent type."); - } - - String entityKey = ep.getRedisKey(key); - redisTemplate.expire(entityKey, ttl); - new Thread(new Runnable() { - public void run() { - try { - Thread.sleep(ttl * 1000); - } - catch (InterruptedException e) { - // ignore - } - final RedisSession newSession = (RedisSession)getDatastore().connect(); - RedisEntityPersister newEp = (RedisEntityPersister)newSession.getPersister(type); - newEp.getAllEntityIndex().remove(key); - } - }).start(); - } - - private void flushIfNecessary() { - if (getFlushMode() == FlushModeType.AUTO) { - flush(); - } - } - - @Override - protected void postFlush(boolean hasUpdates) { - if (!hasUpdates) { - return; - } - - final Set keys = redisTemplate.keys("~*"); - if (keys != null && !keys.isEmpty()) { - redisTemplate.del(keys.toArray(new String[keys.size()])); - } - } - - /** - * Locates a random entity and removes it within the same operation - * - * @param type The entity type - * @return A random entity - */ - public Object pop(Class type) { - flushIfNecessary(); - RedisEntityPersister ep = (RedisEntityPersister)getPersister(type); - if (ep == null) { - throw new NonPersistentTypeException("The class [" + type + "] is not a known persistent type."); - } - - RedisSet set = (RedisSet)ep.getAllEntityIndex(); - String id = set.pop(); - Object result = null; - try { - result = retrieve(type, id); - return result; - } - finally { - if (result != null) { - delete(result); - } - } - } - - public RedisTemplate getNativeInterface() { - return redisTemplate; - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/RedisTransaction.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/RedisTransaction.java deleted file mode 100644 index b9ab7ba9f..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/RedisTransaction.java +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis; - -import org.grails.datastore.mapping.redis.util.RedisTemplate; -import org.grails.datastore.mapping.transactions.Transaction; -import org.springframework.transaction.IllegalTransactionStateException; -import org.springframework.transaction.TransactionSystemException; -import org.springframework.transaction.UnexpectedRollbackException; - -/** - * Represents a Redis transaction - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class RedisTransaction implements Transaction { - private RedisTemplate redisTemplate; - private boolean rollbackCalled; - private boolean commitCalled; - - public RedisTransaction(RedisTemplate redisTemplate) { - this.redisTemplate = redisTemplate; - } - - public void commit() { - if (rollbackCalled) { - throw new IllegalTransactionStateException("Cannot call commit after rollback. Start another transaction first!"); - } - try { - /*final Object[] objects =*/ redisTemplate.exec(); - commitCalled = true; - } catch (Exception e) { - throw new TransactionSystemException("Exception occurred committing back Redis transaction: " + e.getMessage()); - } - } - - public boolean isActive() { - return !commitCalled && !rollbackCalled; - } - - public void setTimeout(int timeout) { - throw new UnsupportedOperationException("Transaction timeouts not supported in Redis"); - } - - public void rollback() { - if (rollbackCalled) { - throw new UnexpectedRollbackException("Cannot rollback Redis transaction. Transaction already rolled back!"); - } - try { - redisTemplate.discard(); - rollbackCalled = true; - } catch (Exception e) { - throw new TransactionSystemException("Exception occurred rolling back Redis transaction: " + e.getMessage()); - } - } - - public RedisTemplate getNativeTransaction() { - return redisTemplate; - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/AbstractRedisCollection.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/AbstractRedisCollection.java deleted file mode 100644 index d3c29476c..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/AbstractRedisCollection.java +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis.collection; - -import org.grails.datastore.mapping.redis.util.RedisTemplate; - -import java.util.Collection; -import java.util.Iterator; - -/** - * Abstract base class for Redis collections. - * - * @author Graeme Rocher - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class AbstractRedisCollection implements RedisCollection { - protected RedisTemplate redisTemplate; - protected String redisKey; - - public AbstractRedisCollection(RedisTemplate redisTemplate, String redisKey) { - this.redisTemplate = redisTemplate; - this.redisKey = redisKey; - } - - /** - * They key used by the collection - * - * @return The redis key - */ - public String getRedisKey() { - return redisKey; - } - - public void clear() { - redisTemplate.del(redisKey); - } - - public boolean isEmpty() { - return size() == 0; - } - - public Object[] toArray() { - return new Object[0]; - } - - public boolean containsAll(Collection c) { - for (Object o : c) { - if (!contains(o)) return false; - } - return true; - } - - public boolean addAll(Collection c) { - boolean changed = false; - for (Object e : c) { - boolean elChange = add(e); - if (elChange && !changed) changed = true; - } - return changed; - } - - public boolean retainAll(Collection c) { - Iterator i = iterator(); - boolean changed = false; - while (i.hasNext()) { - Object o = i.next(); - if (!c.contains(o)) { - i.remove(); - changed = true; - } - } - return changed; - } - - public boolean removeAll(Collection c) { - boolean changed = false; - for (Object e : c) { - boolean elChange = remove(e); - if (elChange && !changed) changed = true; - } - return changed; - - } - - public Object[] toArray(Object[] array) { - return new Object[0]; - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisCollection.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisCollection.java deleted file mode 100644 index 7063e3c48..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisCollection.java +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis.collection; - -import java.util.Collection; -import java.util.List; -import java.util.Set; - -/** - * Commons interface for Redis collections. - */ -@SuppressWarnings("rawtypes") -public interface RedisCollection extends Collection { - - /** - * They key used by the collection - * - * @return The redis key - */ - String getRedisKey(); - - Set members(); - - List members(int offset, int max); -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisList.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisList.java deleted file mode 100644 index c333d2392..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisList.java +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis.collection; - -import java.util.AbstractList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import org.grails.datastore.mapping.redis.util.RedisTemplate; - -/** - * Creates a list that is backed onto a Redis list. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class RedisList extends AbstractList implements List, RedisCollection { - private RedisTemplate redisTemplate; - private String redisKey; - - public RedisList(RedisTemplate redisTemplate, String redisKey) { - this.redisTemplate = redisTemplate; - this.redisKey = redisKey; - } - - @Override - public Object get(int index) { - return redisTemplate.lindex(redisKey, index); - } - - @Override - public Object set(int index, Object element) { - Object prev = get(index); - redisTemplate.lset(redisKey, index, element); - return prev; - } - - @Override - public void add(int index, Object element) { - if (index == 0) { - redisTemplate.lpush(redisKey, element); - } - else if (index == size()) { - redisTemplate.rpush(redisKey, element); - } - else { - throw new UnsupportedOperationException("Redis lists only support adding elements at the beginning or end of a list"); - } - } - - @Override - public Object remove(int index) { - Object o = get(index); - remove(o); - return o; - } - - @Override - public int size() { - return Long.valueOf(redisTemplate.llen(redisKey)).intValue(); - } - - @Override - public boolean contains(Object o) { - return Arrays.asList(elements()).contains(o); - } - - @Override - public Iterator iterator() { - return elements().iterator(); - } - - private List elements() { - return redisTemplate.lrange(redisKey, 0, -1); - } - - @Override - public boolean add(Object e) { - redisTemplate.rpush(redisKey, e); - return true; - } - - @Override - public boolean remove(Object o) { - return redisTemplate.lrem(redisKey, o, 0) != 0; - } - - public String getRedisKey() { - return redisKey; - } - - public Set members() { - return new HashSet(redisTemplate.lrange(redisKey, 0, -1)); - } - - public List members(int offset, int max) { - return redisTemplate.lrange(redisKey, offset, max); - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisMap.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisMap.java deleted file mode 100644 index 07a925109..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisMap.java +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis.collection; - -import org.grails.datastore.mapping.redis.util.RedisTemplate; - -import java.util.AbstractMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * A map that is backed onto a Redis hash. - * - * @author Graeme Rocher - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class RedisMap extends AbstractMap { - - private String redisKey; - private RedisTemplate redisTemplate; - - public RedisMap(RedisTemplate template, String redisKey) { - this.redisKey = redisKey; - this.redisTemplate = template; - } - - @Override - public Set entrySet() { - - final Map redisMap = redisTemplate.hgetall(redisKey); - Set entrySet = new HashSet(); - for (final String key : redisMap.keySet()) { - entrySet.add(new Map.Entry() { - public Object getKey() { - return redisMap.get(key); - } - - public Object getValue() { - return redisMap.get(key); - } - - public Object setValue(Object value) { - Object current = getValue(); - redisTemplate.hset(redisKey, key, value); - return current; - } - }); - } - return entrySet; - } - - @Override - public Object put(Object key, Object value) { - Object current = get(key); - - if (key != null) { - redisTemplate.hset(redisKey, key.toString(), value); - } - return current; - } - - @Override - public Object remove(Object key) { - Object current = get(key); - - if (key != null) { - redisTemplate.hdel(redisKey, key.toString()); - } - return current; - } - - @Override - public Object get(Object key) { - if (key != null) { - return redisTemplate.hget(redisKey, key.toString()); - } - return super.get(key); - } - - @Override - public int size() { - return Long.valueOf(redisTemplate.hlen(redisKey)).intValue(); - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisSet.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisSet.java deleted file mode 100644 index 6a3a6b9b4..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisSet.java +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis.collection; - -import org.grails.datastore.mapping.redis.util.RedisTemplate; - -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -/** - * A Java set implementation that backs onto a Redis set. - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class RedisSet extends AbstractRedisCollection implements Set { - - public RedisSet(RedisTemplate redisTemplate, String redisKey) { - super(redisTemplate, redisKey); - } - - public int size() { - return Long.valueOf(redisTemplate.scard(redisKey)).intValue(); - } - - public boolean contains(Object o) { - return redisTemplate.sismember(redisKey, o); - } - - public Iterator iterator() { - return redisTemplate.smembers(redisKey).iterator(); - } - - public boolean add(Object o) { - return redisTemplate.sadd(redisKey, o); - } - - public boolean remove(Object o) { - return redisTemplate.srem(redisKey, o); - } - - public Set members() { - return redisTemplate.smembers(redisKey); - } - - public List members(final int offset, final int max) { - return redisTemplate.sort(redisKey, redisTemplate.sortParams().limit(offset, max)); - } - - public String random() { - return redisTemplate.srandmember(redisKey); - } - - public String pop() { - return redisTemplate.spop(redisKey); - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisValue.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisValue.java deleted file mode 100644 index 42be02585..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/collection/RedisValue.java +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis.collection; - -import org.springframework.beans.TypeConverter; - -public class RedisValue { - private byte[] value; - private TypeConverter converter; - - public RedisValue(byte[] bytes, TypeConverter converter) { - this.value = bytes; - this.converter = converter; - } - - public byte[] getBytes() { - return value; - } - - public String plus(String str) { - return toString() + str; - } - - public Long plus(Long n) { - return toLong() + n; - } - - public Long plus(Integer n) { - return toLong() + n; - } - - public Long toLong() { - return converter.convertIfNecessary(value, Long.class); - } - - @Override - public String toString() { - return converter.convertIfNecessary(value, String.class); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof CharSequence) { - return toString().equals(obj.toString()); - } - if (obj instanceof Number) { - return toLong().equals(obj); - } - return super.equals(obj); - } - - @Override - public int hashCode() { - return value.hashCode(); - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/engine/RedisAssociationIndexer.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/engine/RedisAssociationIndexer.java deleted file mode 100644 index f20cbd2df..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/engine/RedisAssociationIndexer.java +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis.engine; - -import org.springframework.core.convert.ConversionService; -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.redis.collection.RedisCollection; -import org.grails.datastore.mapping.redis.collection.RedisList; -import org.grails.datastore.mapping.redis.collection.RedisSet; -import org.grails.datastore.mapping.redis.query.RedisQueryUtils; -import org.grails.datastore.mapping.redis.util.RedisTemplate; - -import java.util.Collection; -import java.util.List; - -/** - * An indexer for Redis. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class RedisAssociationIndexer implements AssociationIndexer { - private RedisTemplate template; - private ConversionService typeConverter; - private Association association; - - public RedisAssociationIndexer(RedisTemplate template, ConversionService typeConverter, Association association) { - this.template = template; - this.typeConverter = typeConverter; - this.association = association; - } - - public void preIndex(Long primaryKey, List foreignKeys) { - // handled by index below. - } - - public void index(Long primaryKey, final List foreignKeys) { - final String redisKey = createRedisKey(primaryKey); - RedisCollection col = createRedisCollection(redisKey); - col.addAll(foreignKeys); - } - - public void index(Long primaryKey, Long foreignKey) { - final String redisKey = createRedisKey(primaryKey); - RedisCollection col = createRedisCollection(redisKey); - col.add(foreignKey); - } - - private String createRedisKey(Long primaryKey) { - return association.getOwner().getName() + ":" + primaryKey + ":" + association.getName(); - } - - public List query(Long primaryKey) { - String redisKey = createRedisKey(primaryKey); - return queryInternal(redisKey); - } - - public PersistentEntity getIndexedEntity() { - return association.getAssociatedEntity(); - } - - private List queryInternal(final String redisKey) { - RedisCollection col = createRedisCollection(redisKey); - return queryRedisCollection(col); - } - - private List queryRedisCollection(RedisCollection col) { - Collection results = col.members(); - return RedisQueryUtils.transformRedisResults(typeConverter, results); - } - - private RedisCollection createRedisCollection(String redisKey) { - return association.isList() ? new RedisList(template, redisKey) : new RedisSet(template, redisKey); - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/engine/RedisEntityPersister.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/engine/RedisEntityPersister.java deleted file mode 100644 index ae2d2003d..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/engine/RedisEntityPersister.java +++ /dev/null @@ -1,410 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis.engine; - -import java.io.IOException; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import org.grails.datastore.mapping.core.OptimisticLockingException; -import org.grails.datastore.mapping.core.SessionImplementor; -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.PropertyValueIndexer; -import org.grails.datastore.mapping.keyvalue.engine.AbstractKeyValueEntityPersister; -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.Association; -import org.grails.datastore.mapping.proxy.EntityProxy; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.redis.RedisEntry; -import org.grails.datastore.mapping.redis.RedisSession; -import org.grails.datastore.mapping.redis.collection.RedisCollection; -import org.grails.datastore.mapping.redis.collection.RedisSet; -import org.grails.datastore.mapping.redis.query.RedisQuery; -import org.grails.datastore.mapping.redis.util.RedisCallback; -import org.grails.datastore.mapping.redis.util.RedisTemplate; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.core.convert.ConversionService; -import org.springframework.dao.CannotAcquireLockException; - -import redis.clients.jedis.exceptions.JedisDataException; -import redis.clients.util.SafeEncoder; - -/** - * An {@link org.grails.datastore.mapping.engine.EntityPersister} for the Redis NoSQL datastore. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class RedisEntityPersister extends AbstractKeyValueEntityPersister { - public static final String UTF_8 = "UTF-8"; - private RedisTemplate redisTemplate; - private RedisCollection allEntityIndex; - - public static final String DISCRIMINATOR = "discriminator"; - - public RedisEntityPersister(MappingContext context, PersistentEntity entity, RedisSession conn, - final RedisTemplate template, ApplicationEventPublisher publisher) { - super(context, entity, conn, publisher); - this.redisTemplate = template; - allEntityIndex = new RedisSet(redisTemplate, getEntityFamily() + ".all"); - } - - private Long getLong(Object key) { - return getMappingContext().getConversionService().convert(key, Long.class); - } - - @Override - protected RedisEntry createNewEntry(String family) { - return new RedisEntry(family); - } - - @Override - protected Object getEntryValue(Map nativeEntry, String property) { - return nativeEntry.get(property); - } - - @Override - protected void setEntryValue(Map nativeEntry, String key, Object value) { - if (value == null || !shouldConvert(value)) { - return; - } - - Class type = value.getClass(); - if(value != null && type.isArray() && byte.class.isAssignableFrom(type.getComponentType())) { - nativeEntry.put(key, SafeEncoder.encode((byte[])value)); - } - else { - - final ConversionService conversionService = getMappingContext().getConversionService(); - nativeEntry.put(key, conversionService.convert(value, String.class)); - } - } - - private boolean shouldConvert(Object value) { - return !getMappingContext().isPersistentEntity(value) && !(value instanceof EntityProxy); - } - - @Override - protected void lockEntry(PersistentEntity persistentEntity, String entityFamily, Serializable id, int timeout) { - String redisKey = getRedisKey(entityFamily, id); - final TimeUnit milliUnit = TimeUnit.MILLISECONDS; - final long waitTime = TimeUnit.SECONDS.toMillis(timeout); - final String lockName = lockName(redisKey); - int sleepTime = 0; - while(true) { - if (redisTemplate.setnx(lockName, System.currentTimeMillis()) && redisTemplate.expire(lockName, timeout)) { - break; - } - if (redisTemplate.ttl(lockName) > 0) { - try { - if (sleepTime > waitTime) { - throw new CannotAcquireLockException("Failed to acquire lock on key ["+redisKey+"]. Wait time exceeded timeout."); - } - // wait for previous lock to expire - sleepTime += 500; - milliUnit.sleep(500); - } catch (InterruptedException e) { - throw new CannotAcquireLockException("Failed to acquire lock on key ["+redisKey+"]: " + e.getMessage(), e); - } - } - else { - if (redisTemplate.getset(lockName, System.currentTimeMillis()) != null && - redisTemplate.expire(lockName, timeout)) { - break; - } - } - } - } - - private String lockName(String redisKey) { - return redisKey + ".lock"; - } - - @Override - protected void unlockEntry(PersistentEntity persistentEntity, String entityFamily, Serializable id) { - String redisKey = getRedisKey(entityFamily, id); - redisTemplate.del(lockName(redisKey)); - } - - @Override - protected Serializable convertToNativeKey(Serializable nativeKey) { - return getMappingContext().getConversionService().convert(nativeKey, Long.class); - } - - @Override - protected PersistentEntity discriminatePersistentEntity(PersistentEntity persistentEntity, Map nativeEntry) { - if (!nativeEntry.containsKey(DISCRIMINATOR)) { - return persistentEntity; - } - - String discriminator = nativeEntry.get(DISCRIMINATOR).toString(); - final PersistentEntity childEntity = getMappingContext().getChildEntityByDiscriminator(persistentEntity.getRootEntity(), discriminator); - return childEntity == null ? persistentEntity : childEntity; - } - - @Override - protected Map retrieveEntry(PersistentEntity persistentEntity, final String family, Serializable key) { - String hashKey = getEntryKey(persistentEntity, family, key); - - final Map map = redisTemplate.hgetall(hashKey); - return map == null || map.isEmpty() ? null : map; - } - - private String getEntryKey(PersistentEntity persistentEntity, String family, Serializable key) { - String hashKey; - if (persistentEntity.isRoot()) { - hashKey = getRedisKey(family, key); - } - else { - RedisEntityPersister persister = (RedisEntityPersister) session.getPersister(persistentEntity.getRootEntity()); - hashKey = getRedisKey(persister.getFamily(), key); - } - return hashKey; - } - - @Override - protected List retrieveAllEntities(final PersistentEntity persistentEntity, Iterable keys) { - - List entityResults = new ArrayList(); - - if (keys == null) { - return entityResults; - } - - final List redisKeys; - if (keys instanceof List) { - redisKeys = (List) keys; - } - else { - redisKeys = new ArrayList(); - for (Serializable key : keys) { - redisKeys.add(key); - } - } - - if (redisKeys.isEmpty()) { - return entityResults; - } - - List results = redisTemplate.pipeline(new RedisCallback() { - public Object doInRedis(RedisTemplate redis) throws IOException { - for (Serializable key : redisKeys) { - redis.hgetall(getEntryKey(persistentEntity, getFamily(), key)); - } - return null; - } - }); - - Iterator keyIter = redisKeys.iterator(); - Iterator resultIter = results.iterator(); - while (keyIter.hasNext() && resultIter.hasNext()) { - Serializable nativeKey = keyIter.next(); - Object entity; - SessionImplementor sessionImplementor = (SessionImplementor)session; - if (sessionImplementor.isCached(persistentEntity.getJavaClass(), nativeKey)) { - entity = sessionImplementor.getCachedInstance(persistentEntity.getJavaClass(), nativeKey); - } - else { - Map nativeEntry = (Map)resultIter.next(); - entity = createObjectFromNativeEntry(persistentEntity, nativeKey, nativeEntry); - sessionImplementor.cacheInstance(persistentEntity.getJavaClass(), nativeKey, entity); - } - entityResults.add(entity); - } - return entityResults; - } - - private String getRedisKey(String family, Serializable key) { - return family + ":" + getLong(key); - } - - @Override - public void updateEntry(final PersistentEntity persistentEntity, final EntityAccess entityAccess, - final Long key, final Map nativeEntry) { - try { - if (!persistentEntity.isRoot()) { - saveOrUpdate(getRootFamily(persistentEntity), key, nativeEntry, persistentEntity, entityAccess, true); - } - else { - saveOrUpdate(getFamily(), key, nativeEntry, persistentEntity, entityAccess, true); - } - } finally { - updateAllEntityIndex(persistentEntity, key); - } - } - - @Override - public Long storeEntry(final PersistentEntity persistentEntity, final EntityAccess entityAccess, - final Long storeId, final Map nativeEntry) { - try { - if (!persistentEntity.isRoot()) { - nativeEntry.put(DISCRIMINATOR, persistentEntity.getDiscriminator()); - saveOrUpdate(getRootFamily(persistentEntity), storeId, nativeEntry, persistentEntity, entityAccess, false); - return storeId; - } - saveOrUpdate(getFamily(), storeId, nativeEntry, persistentEntity, entityAccess, false); - return storeId; - } - finally { - updateAllEntityIndex(persistentEntity, storeId); - } - } - - private void updateAllEntityIndex(PersistentEntity persistentEntity, Long storeId) { - try { - getAllEntityIndex().add(storeId); - } - catch (JedisDataException e) { - handleJedisDataException(e); - } - PersistentEntity parent = persistentEntity.getParentEntity(); - while (parent != null) { - RedisEntityPersister persister = (RedisEntityPersister) session.getPersister(parent); - try { - persister.getAllEntityIndex().add(storeId); - } - catch (JedisDataException e) { - handleJedisDataException(e); - } - parent = parent.getParentEntity(); - } - } - - private void handleJedisDataException(JedisDataException e) { - // TODO horrible hack workaround for a Jedis 2.0.0 bug; the command works but the - // client doesn't handle the response correctly, so it's safe to ignore the - // exception if we're in a transaction - if (e.getMessage().startsWith("Please close pipeline or multi block before calling this method")) { - if (!getRedisTemplate().isInMulti()) { - throw e; - } - } - else { - throw e; - } - } - - private String getRootFamily(PersistentEntity persistentEntity) { - final PersistentEntity root = persistentEntity.getRootEntity(); - return ((RedisEntityPersister)session.getPersister(root)).getFamily(); - } - - @Override - protected Long generateIdentifier(PersistentEntity persistentEntity, Map entry) { - // always use the root of an inheritance hierarchy to generate the identifier - PersistentEntity root = persistentEntity.getRootEntity(); - RedisEntityPersister persister = (RedisEntityPersister) session.getPersister(root); - - return generateIdentifier(persister.getFamily()); - } - - private void saveOrUpdate(final String family, final Long id, final Map nativeEntry, - final PersistentEntity persistentEntity, final EntityAccess entityAccess, final boolean update) { - - final String key = family + ":" + id; - - if (update && isVersioned(entityAccess)) { - String oldVersion; - RedisSession newSession = (RedisSession)getSession().getDatastore().connect(); - try { - oldVersion = newSession.getNativeInterface().hget(key, "version"); - } - finally { - newSession.disconnect(); - } - - String version = (String)nativeEntry.get("version"); - if (oldVersion != null && version != null && !version.equals(oldVersion)) { - throw new OptimisticLockingException(persistentEntity, id); - } - - incrementVersion(entityAccess); - } - - redisTemplate.hmset(key, nativeEntry); - } - - public RedisCollection getAllEntityIndex() { - return allEntityIndex; - } - - public String getFamily() { - return entityFamily; - } - - protected Long generateIdentifier(final String family) { - return (long) redisTemplate.incr(family + ".next_id"); - } - - @Override - protected void deleteEntries(final String family, final List keys) { - final List actualKeys = new ArrayList(); - for (Long key : keys) { - actualKeys.add(family + ":" + key); - getAllEntityIndex().remove(key); - } - - redisTemplate.del(actualKeys.toArray(new String[actualKeys.size()])); - } - - @Override - protected void deleteEntry(final String family, final Long key, final Object entry) { - final String actualKey = family + ":" + key; - getAllEntityIndex().remove(key); - redisTemplate.del(actualKey); - } - - @Override - public PropertyValueIndexer getPropertyIndexer(PersistentProperty property) { - return new RedisPropertyValueIndexer(getMappingContext(),this, property); - } - - @Override - public AssociationIndexer getAssociationIndexer(Map nativeEntry, Association oneToMany) { - return new RedisAssociationIndexer(redisTemplate, getMappingContext().getConversionService(), oneToMany); - } - - public Query createQuery() { - return new RedisQuery((RedisSession) session, getRedisTemplate(), getPersistentEntity(), this); - } - - public RedisTemplate getRedisTemplate() { - return redisTemplate; - } - - public String getEntityBaseKey() { - return getFamily(getPersistentEntity(), getPersistentEntity().getMapping()); - } - - public String getPropertySortKey(PersistentProperty property) { - return getEntityBaseKey() + ":" + property.getName() + ":sorted"; - } - - public String getPropertySortKeyPattern() { - return getEntityBaseKey() + ":*:sorted"; - } - - public String getRedisKey(Serializable key) { - return getRedisKey(getFamily(), key); - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/engine/RedisPropertyValueIndexer.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/engine/RedisPropertyValueIndexer.java deleted file mode 100644 index 93dc2e0ac..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/engine/RedisPropertyValueIndexer.java +++ /dev/null @@ -1,188 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis.engine; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Set; - -import org.grails.datastore.mapping.core.SessionImplementor; -import org.grails.datastore.mapping.engine.PropertyValueIndexer; -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.redis.collection.RedisSet; -import org.grails.datastore.mapping.redis.query.RedisQueryUtils; -import org.grails.datastore.mapping.redis.util.RedisTemplate; -import org.springframework.dao.DataAccessException; - -import redis.clients.jedis.exceptions.JedisDataException; - -/** - * Indexes property values for querying later - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class RedisPropertyValueIndexer implements PropertyValueIndexer { - - private RedisTemplate template; - private PersistentProperty property; - private RedisEntityPersister entityPersister; - private MappingContext mappingContext; - - public RedisPropertyValueIndexer(MappingContext context, RedisEntityPersister redisEntityPersister, - PersistentProperty property) { - this.template = redisEntityPersister.getRedisTemplate(); - this.entityPersister = redisEntityPersister; - this.property = property; - this.mappingContext = context; - } - - public void deindex(Object value, Long primaryKey) { - if (value == null) { - return; - } - - final String primaryIndex = createRedisKey(value); - template.srem(primaryIndex, primaryKey); - } - - public void index(final Object value, final Long primaryKey) { - if (value == null) { - return; - } - - String propSortKey = entityPersister.getPropertySortKey(property); - clearCachedIndices(entityPersister.getPropertySortKeyPattern()); - final String primaryIndex = createRedisKey(value); - try { - template.sadd(primaryIndex, primaryKey); - } - catch (JedisDataException e) { - // TODO horrible hack workaround for a Jedis 2.0.0 bug; the command works but the - // client doesn't handle the response correctly, so it's safe to ignore the - // exception if we're in a transaction - if (e.getMessage().startsWith("Please close pipeline or multi block before calling this method")) { - if (!template.isInMulti()) { - throw e; - } - } - else { - throw e; - } - } - - // for numbers and dates we also create a list index in order to support range queries - - if (value instanceof Number) { - template.zadd(propSortKey, ((Number)value).doubleValue(), primaryKey); - } - else if (value instanceof Date) { - template.zadd(propSortKey, ((Date)value).getTime(), primaryKey); - } - } - - private void clearCachedIndices(final String propSortKey) { - final SessionImplementor session = (SessionImplementor) entityPersister.getSession(); - final String keyPattern = propSortKey + "~*"; - session.addPostFlushOperation(new KeyPatternRunnable(keyPattern) { - public void run() { - deleteKeys(template.keys(keyPattern)); - } - }); - } - - private abstract class KeyPatternRunnable implements Runnable { - private String keyPattern; - - public KeyPatternRunnable(String keyPattern) { - this.keyPattern = keyPattern; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof KeyPatternRunnable) { - return keyPattern.equals(((KeyPatternRunnable)obj).keyPattern); - } - return super.equals(obj); - } - - @Override - public int hashCode() { - return keyPattern.hashCode(); - } - } - - private void deleteKeys(Set toDelete) { - if (toDelete != null && !toDelete.isEmpty()) { - template.del(toDelete.toArray(new String[toDelete.size()])); - } - } - - private String createRedisKey(Object value) { - return getIndexRoot() + urlEncode(value); - } - - @SuppressWarnings("serial") - private String urlEncode(Object value) { - try { - return URLEncoder.encode(value.toString(), "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new DataAccessException("Cannot encoding Redis key: " + e.getMessage(), e){}; - } - } - - private String getIndexRoot() { - return getRootEntityName() + ":" + property.getName() + ":"; - } - - private String getRootEntityName() { - - final PersistentEntity owner = property.getOwner(); - if (owner.isRoot()) { - return owner.getName(); - } - return owner.getRootEntity().getName(); - } - - public List query(final Object value) { - return query(value, 0, -1); - } - - public List query(final Object value, final int offset, final int max) { - RedisSet set = new RedisSet(template, createRedisKey(value)); - Collection results; - if (offset > 0 || max > 0) { - results = set.members(offset, max); - } - else { - results = set.members(); - } - return RedisQueryUtils.transformRedisResults(mappingContext.getConversionService(), results); - } - - public String getIndexName(Object value) { - return createRedisKey(value); - } - - public String getIndexPattern(String pattern) { - return getIndexRoot() + urlEncode(pattern.replaceAll("%", "*")); - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/query/RedisQuery.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/query/RedisQuery.java deleted file mode 100644 index 85952fc02..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/query/RedisQuery.java +++ /dev/null @@ -1,573 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis.query; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.codehaus.groovy.runtime.DefaultGroovyMethods; -import org.grails.datastore.mapping.config.Property; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.types.Identity; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.Restrictions; -import org.grails.datastore.mapping.redis.RedisSession; -import org.grails.datastore.mapping.redis.engine.RedisEntityPersister; -import org.grails.datastore.mapping.redis.engine.RedisPropertyValueIndexer; -import org.grails.datastore.mapping.redis.util.RedisCallback; -import org.grails.datastore.mapping.redis.util.RedisTemplate; -import org.grails.datastore.mapping.redis.util.SortParams; -import org.springframework.core.convert.ConversionService; -import org.springframework.dao.DataRetrievalFailureException; -import org.springframework.dao.InvalidDataAccessResourceUsageException; - -/** - * A Query implementation for Redis. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class RedisQuery extends Query { - private RedisEntityPersister entityPersister; - private RedisTemplate template; - private ConversionService conversionService; - - public RedisQuery(RedisSession session, RedisTemplate redisTemplate, PersistentEntity persistentEntity, RedisEntityPersister entityPersister) { - super(session, persistentEntity); - this.entityPersister = entityPersister; - template = redisTemplate; - conversionService = getSession().getMappingContext().getConversionService(); - } - - @Override - protected List executeQuery(PersistentEntity entity, Junction criteria) { - final ProjectionList projectionList = projections(); - String finalKey; - if (criteria.isEmpty()) { - finalKey = entityPersister.getAllEntityIndex().getRedisKey(); - } - else { - List criteriaList = criteria.getCriteria(); - finalKey = executeSubQuery(criteria, criteriaList); - } - - if (!getEntity().isRoot()) { - // if the entity is not a root entity then apply a conjunction to trim - // any entities not of this type - - final String childEntityResultsKey = finalKey + "-" + getEntity().getDecapitalizedName(); - template.sinterstore(childEntityResultsKey, finalKey, - entityPersister.getAllEntityIndex().getRedisKey()); - finalKey = childEntityResultsKey; - } - - Collection results; - IdProjection idProjection = null; - if (projectionList.isEmpty()) { - results = paginateResults(finalKey); - } - else { - List projectionResults = new ArrayList(); - String postSortAndPaginationKey = null; - for (Projection projection : projectionList.getProjectionList()) { - if (projection instanceof CountProjection) { - if (postSortAndPaginationKey == null) postSortAndPaginationKey = storeSortedKey(finalKey); - projectionResults.add(getCountResult(postSortAndPaginationKey)); - } - else if (projection instanceof MaxProjection) { - MaxProjection max = (MaxProjection) projection; - final String sortKey = getValidSortKey(max); - if (!shouldSortOrPaginate()) { - projectionResults.add(getMaxValueFromSortedSet(sortKey)); - } - } - else if (projection instanceof MinProjection) { - MinProjection min = (MinProjection) projection; - final String sortKey = getValidSortKey(min); - if (!shouldSortOrPaginate()) { - projectionResults.add(getMinValueFromSortedSet(sortKey)); - } - } - else { - final String projectionType = projection.getClass().getSimpleName(); - if (projection instanceof SumProjection) { - return unsupportedProjection(projectionType); - } - else if (projection instanceof AvgProjection) { - return unsupportedProjection(projectionType); - } - else if (projection instanceof CountDistinctProjection) { - PropertyProjection propertyProjection = (PropertyProjection) projection; - final PersistentProperty validProperty = getValidProperty(propertyProjection); - final List values = projectProperty(finalKey, postSortAndPaginationKey, validProperty); - projectionResults.add( DefaultGroovyMethods.unique(values).size() ); - } - else if (projection instanceof PropertyProjection) { - List resultList = new ArrayList(); - PropertyProjection propertyProjection = (PropertyProjection) projection; - final PersistentProperty validProperty = getValidProperty(propertyProjection); - final List values = projectProperty(finalKey, postSortAndPaginationKey, validProperty); - return convertProjectedListToActual(resultList, validProperty, values); - } - else if (projection instanceof IdProjection) { - idProjection = (IdProjection) projection; - } - } - } - - if (!projectionResults.isEmpty()) return projectionResults; - results = paginateResults(finalKey); - } - - if (results != null) { - if (idProjection != null) { - return RedisQueryUtils.transformRedisResults(conversionService, results); - } - return getSession().retrieveAll(getEntity().getJavaClass(), results); - } - return Collections.emptyList(); - } - - private List convertProjectedListToActual(List resultList, PersistentProperty validProperty, List values) { - Class type = validProperty.getType(); - final PersistentEntity associatedEntity = getSession().getMappingContext().getPersistentEntity(type.getName()); - final boolean isEntityType = associatedEntity != null; - if (isEntityType) { - return getSession().retrieveAll(type, values); - } - for (String value : values) { - resultList.add(conversionService.convert(value, type)); - } - - return resultList; - } - - private List projectProperty(String finalKey, String postSortAndPaginationKey, PersistentProperty validProperty) { - if (postSortAndPaginationKey == null) postSortAndPaginationKey = storeSortedKey(finalKey); - - String entityKey = entityPersister.getEntityBaseKey(); - return template.sort(postSortAndPaginationKey, template.sortParams().get(entityKey + ":*->" + validProperty.getName())); - } - - private List unsupportedProjection(String projectionType) { - throw new InvalidDataAccessResourceUsageException("Cannot use ["+ projectionType +"] projection. ["+projectionType+"] projections are not currently supported."); - } - - private String getValidSortKey(PropertyProjection projection) { - PersistentProperty prop = getValidProperty(projection); - return entityPersister.getPropertySortKey(prop); - } - - private PersistentProperty getValidProperty(PropertyProjection projection) { - final String propName = projection.getPropertyName(); - PersistentProperty prop = entityPersister.getPersistentEntity().getPropertyByName(propName); - if (prop == null) { - throw new InvalidDataAccessResourceUsageException("Cannot use ["+projection.getClass().getSimpleName()+"] projection on non-existent property: " + propName); - } - else if (!isIndexed(prop)) { - throw new InvalidDataAccessResourceUsageException("Cannot use ["+projection.getClass().getSimpleName()+"] projection on non-indexed property: " + propName); - } - return prop; - } - - private String storeSortedKey(String finalKey) { - if (shouldSortOrPaginate()) { - StringBuilder builder = new StringBuilder(); - builder.append('~') - .append(finalKey) - .append('-') - .append(offset) - .append('-') - .append(max) - .append('-'); - - if (!orderBy.isEmpty()) { - final Order order = orderBy.get(0); - builder.append(order.getProperty()) - .append('-') - .append(order.getDirection()); - } - - String sortKey = builder.toString(); - template.sortstore(finalKey, sortKey, getSortAndPaginationParams()); - return sortKey; - } - return finalKey; - } - - private String executeSubQuery(Junction junction, List criteria) { - List indices = getIndexNames(junction, entityPersister); - - if (indices.isEmpty()) { - throw new DataRetrievalFailureException("Unsupported Redis query"); - } - if (indices.size() == 1) { - return indices.get(0); - } - final String[] keyArray = indices.toArray(new String[indices.size()]); - String finalKey; - if (junction instanceof Conjunction) { - finalKey = formulateConjunctionKey(indices); - template.sinterstore(finalKey, keyArray); - } - else { - finalKey = formulateDisjunctionKey(indices); - template.sunionstore(finalKey, keyArray); - } - - // since the keys used for queries are temporary we set Redis to kill them after a while -// template.expire(finalKey, 1000); - return finalKey; - } - - private Collection paginateResults(final String key) { - final boolean shouldSort = shouldSortOrPaginate(); - - if (shouldSort) { - return template.sort(key, getSortAndPaginationParams()); - } - return template.smembers(key); - } - - private boolean shouldSortOrPaginate() { - return offset > 0 || max > -1 || !orderBy.isEmpty(); - } - - private SortParams getSortAndPaginationParams() { - SortParams params = template.sortParams(); - if (!orderBy.isEmpty()) { - Order o = orderBy.get(0); // Redis doesn't really allow multiple orderings - String orderBy = entityPersister.getEntityBaseKey() + ":*->" + o.getProperty(); - - params.by(orderBy); - if (o.getDirection() == Order.Direction.DESC) { - params.desc(); - } - else { - params.asc(); - } - } - if (offset > 0 || max > -1) { - params.limit(offset, max); - } - return params; - } - - @SuppressWarnings("unused") - private String formulateDisjunctionKey(String[] indices) { - final List indicesList = Arrays.asList(indices); - return formulateDisjunctionKey(indicesList); - } - - private String formulateDisjunctionKey(List indicesList) { - Collections.sort(indicesList); - return "~!" + indicesList.toString().replaceAll("\\s", ""); - } - - private String formulateConjunctionKey(List indices) { - return "~" + indices.toString().replaceAll("\\s", ""); - } - - private long getCountResult(String redisKey) { - if (shouldSortOrPaginate()) { - return template.llen(redisKey); - } - return template.scard(redisKey); - } - - private boolean isIndexed(PersistentProperty property) { - if (property instanceof Identity) return true; - Property kv = (Property) property.getMapping().getMappedForm(); - return kv.isIndex(); - } - - @SuppressWarnings("serial") - private final Map criterionHandlers = new HashMap() {{ - CriterionHandler likeHandler = new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, Like criterion) { - String key = executeSubLike(entityPersister, criterion); - indices.add(key); - } - }; - put(Like.class, likeHandler); - put(ILike.class, likeHandler); - put(Between.class, new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, Between criterion) { - String key = executeSubBetween(entityPersister, criterion); - indices.add(key); - } - }); - put(GreaterThanEquals.class, new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, GreaterThanEquals criterion) { - String key = executeGreaterThanEquals(entityPersister, criterion); - indices.add(key); - } - }); - put(GreaterThan.class, new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, GreaterThan criterion) { - String key = executeGreaterThanEquals(entityPersister, criterion); - indices.add(key); - } - }); - put(LessThanEquals.class, new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, LessThanEquals criterion) { - String key = executeLessThanEquals(entityPersister, criterion); - indices.add(key); - } - }); - put(LessThan.class, new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, LessThan criterion) { - String key = executeLessThanEquals(entityPersister, criterion); - indices.add(key); - } - }); - put(Equals.class, new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, Equals criterion) { - final String property = criterion.getProperty(); - final Object value = criterion.getValue(); - final String indexName = getIndexName(entityPersister, property, value); - indices.add(indexName); - } - }); - put(IdEquals.class, new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, IdEquals criterion) { - final Object value = criterion.getValue(); - final String indexName = getIndexName(entityPersister, entityPersister.getPersistentEntity().getIdentity().getName(), value); - indices.add(indexName); - } - }); - put(NotEquals.class, new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, NotEquals criterion) { - final String property = criterion.getProperty(); - final Object value = criterion.getValue(); - final String indexName = getIndexName(entityPersister, property, value); - - indices.add(negateIndex(entityPersister, indexName)); - } - }); - put(In.class, new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, In criterion) { - final String property = criterion.getName(); - Disjunction dis = new Disjunction(); - for (Object value : criterion.getValues()) { - dis.add(Restrictions.eq(property, value)); - } - indices.add(executeSubQuery(dis, dis.getCriteria())); - } - }); - put(Conjunction.class, new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, Junction criterion) { - indices.add(executeSubQuery(criterion, criterion.getCriteria())); - } - }); - put(Disjunction.class, new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, Junction criterion) { - indices.add(executeSubQuery(criterion, criterion.getCriteria())); - } - }); - put(Negation.class, new CriterionHandler() { - public void handle(RedisEntityPersister entityPersister, List indices, Negation criterion) { - final String finalIndex = executeSubQuery(criterion, criterion.getCriteria()); - indices.add(negateIndex(entityPersister, finalIndex)); - } - }); - }}; - - private String negateIndex(RedisEntityPersister entityPersister, String indexName) { - final String negatedIndex = "!" + indexName; - template.sdiffstore(negatedIndex, entityPersister.getAllEntityIndex().getRedisKey(), indexName); - return negatedIndex; - } - - private static interface CriterionHandler { - void handle(RedisEntityPersister entityPersister, List indices, T criterion); - } - - private List getIndexNames(Junction criteria, RedisEntityPersister entityPersister) { - - List criteriaList = criteria.getCriteria(); - List indices = new ArrayList(); - for (Criterion criterion : criteriaList) { - CriterionHandler handler = criterionHandlers.get(criterion.getClass()); - if (handler != null) { - handler.handle(entityPersister, indices, criterion); - } - } - return indices; - } - - protected String executeLessThanEquals(RedisEntityPersister entityPersister, PropertyCriterion criterion) { - - final String property = criterion.getProperty(); - PersistentProperty prop = getAndValidateProperty(entityPersister, property); - - return executeBetweenInternal(entityPersister, prop, 0, criterion.getValue(), false, true); - } - - protected String executeGreaterThanEquals(RedisEntityPersister entityPersister, PropertyCriterion criterion) { - final String property = criterion.getProperty(); - PersistentProperty prop = getAndValidateProperty(entityPersister, property); - - String sortKey = entityPersister.getPropertySortKey(prop); - Object max = getMaxValueFromSortedSet(sortKey); - - return executeBetweenInternal(entityPersister, prop, criterion.getValue(), max, false, true); - } - - private Object getMaxValueFromSortedSet(String sortKey) { - String maxKey = sortKey + "~max-score"; - - Object max = template.get(maxKey); - if (max == null) { - Set results = template.zrevrange(sortKey, 0, 0); - if (results.isEmpty()) { - max = -1; - } - else { - max = template.zscore(sortKey, results.iterator().next()); - } - - template.setex(maxKey, max, 500); - } - - return conversionService.convert(max, Double.class); - } - - private Object getMinValueFromSortedSet(String sortKey) { - String minKey = sortKey + "~min-score"; - - Object min = template.get(minKey); - if (min == null) { - Set results = template.zrange(sortKey, 0, 0); - if (results.isEmpty()) { - min = -1; - } - else { - min = template.zscore(sortKey, results.iterator().next()); - } - - template.setex(minKey, min, 500); - } - return conversionService.convert(min, Double.class); - } - - protected String executeSubBetween(RedisEntityPersister entityPersister, Between between) { - final String property = between.getProperty(); - - PersistentProperty prop = getAndValidateProperty(entityPersister, property); - return executeBetweenInternal(entityPersister, prop, between.getFrom(), between.getTo(), false, true); - } - - private String executeBetweenInternal(RedisEntityPersister entityPersister, - PersistentProperty prop, Object fromObject, Object toObject, - boolean includeFrom, boolean includeTo) { - String sortKey = entityPersister.getPropertySortKey(prop); - if (fromObject instanceof Date) { - fromObject = ((Date)fromObject).getTime(); - } - if (toObject instanceof Date) { - toObject = ((Date)toObject).getTime(); - } - - if (!(fromObject instanceof Number)) { - fromObject = conversionService.convert(fromObject, Double.class); - } - if (!(toObject instanceof Number)) { - toObject = conversionService.convert(toObject, Double.class); - } - - final double from = ((Number) fromObject).doubleValue(); - final double to = ((Number) toObject).doubleValue(); - - final String key = sortKey + "~between-" + from + "-" + to; - if (!template.exists(key)) { - final Set results = template.zrangebyscore(sortKey, from, to); - if (results != null && !results.isEmpty()) { - template.pipeline(new RedisCallback() { - public Object doInRedis(RedisTemplate redis) throws IOException { - for (String result : results) { - redis.sadd(key, result); - } -// redis.expire(key, 1000); - - return null; - } - }); - } - } - return key; - } - - private PersistentProperty getAndValidateProperty(RedisEntityPersister entityPersister, String property) { - final PersistentEntity entity = entityPersister.getPersistentEntity(); - PersistentProperty prop = entity.getPropertyByName(property); - if (prop == null) { - throw new InvalidDataAccessResourceUsageException("Cannot execute between query on property [" + - property + "] of class [" + entity + "]. Property does not exist."); - } - return prop; - } - - private String executeSubLike(RedisEntityPersister entityPersister, Like like) { - final String property = like.getProperty(); - String pattern = like.getPattern(); - final List keys = resolveMatchingIndices(entityPersister, property, pattern); - final String disjKey = formulateDisjunctionKey(keys); - template.sunionstore(disjKey, keys.toArray(new String[keys.size()])); -// template.expire(disjKey, 1000); - return disjKey; - } - - private List resolveMatchingIndices(RedisEntityPersister entityPersister, String property, String pattern) { - PersistentProperty prop = getEntity().getPropertyByName(property); - assertIndexed(property, prop); - RedisPropertyValueIndexer indexer = (RedisPropertyValueIndexer) entityPersister.getPropertyIndexer(prop); - return new ArrayList(template.keys(indexer.getIndexPattern(pattern))); - } - - private String getIndexName(RedisEntityPersister entityPersister, String property, Object value) { - PersistentProperty prop = getEntity().getPropertyByName(property); - if (prop == null) { - final PersistentProperty identity = getEntity().getIdentity(); - if (identity.getName().equals(property)) { - prop = identity; - } - } - assertIndexed(property, prop); - - return entityPersister.getPropertyIndexer(prop).getIndexName(value); - } - - private void assertIndexed(String property, PersistentProperty prop) { - if (prop == null) { - throw new InvalidDataAccessResourceUsageException("Cannot execute query. Entity [" + - getEntity() + "] does not declare a property named [" + property + "]"); - } - if (!isIndexed(prop)) { - throw new InvalidDataAccessResourceUsageException("Cannot query class [" + - getEntity() + "] on property [" + prop + "]. The property is not indexed!"); - } - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/query/RedisQueryUtils.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/query/RedisQueryUtils.java deleted file mode 100644 index d7df790ff..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/query/RedisQueryUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 2010 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.mapping.redis.query; - -import org.springframework.core.convert.ConversionService; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * Internal utility methods for dealing with queries - * - * @author Graeme Rocher - * @since 1.0 - */ -public class RedisQueryUtils { - - public static List transformRedisResults(ConversionService conversionService, Collection results) { - List returnResults; - if (!results.isEmpty()) { - List foreignKeys = new ArrayList(); - for (String result : results) { - foreignKeys.add(conversionService.convert(result, Long.class)); - } - returnResults = foreignKeys; - } - else { - returnResults = Collections.emptyList(); - } - return returnResults; - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/util/JedisTemplate.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/util/JedisTemplate.java deleted file mode 100644 index ea6679f31..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/util/JedisTemplate.java +++ /dev/null @@ -1,1288 +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.mapping.redis.util; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.transaction.NoTransactionException; -import org.springframework.util.ReflectionUtils; - -import redis.clients.jedis.Client; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisPool; -import redis.clients.jedis.PipelineBlock; -import redis.clients.jedis.Response; -import redis.clients.jedis.SortingParams; -import redis.clients.jedis.Transaction; -import redis.clients.jedis.exceptions.JedisConnectionException; - -/** - * A Spring-style template for querying Redis and translating - * Jedis exceptions into Spring exceptions - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("unchecked") -public class JedisTemplate implements RedisTemplate { - - public static final String QUEUED = "QUEUED"; - - private String password; - private Jedis redis; - private Transaction transaction; - private JedisPool pool; - private PipelineBlock pipeline; - private String host = "localhost"; - private int port; - private int timeout = 2000; - - public JedisTemplate(String host, int port, int timeout) { - this.host = host; - this.port = port; - this.timeout = timeout; - } - - public JedisTemplate(Jedis jedis) { - this.redis = jedis; - } - - public boolean append(final String key, final Object val) { - return (Boolean)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - Response response = transaction.append(key, val.toString()); - return QUEUED.equals(response.get()); - } - if (pipeline != null) { - pipeline.append(key, val.toString()); - return false; - } - return redis.append(key, val.toString()) > 0; - } - }); - } - - public List blpop(final int timeout, final String... keys) { - return (List) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.blpop(timeout, keys); - } - }); - } - - public List brpop(final int timeout, final String... keys) { - return (List) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.brpop(timeout, keys); - } - }); - } - - public boolean decr(final String key) { - return (Boolean) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.decr(key) > 0; - } - }); - } - - public boolean decrby(final String key, final int amount) { - return (Boolean) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.decrBy(key, amount) > 0; - } - }); - } - - public List pipeline(final RedisCallback> pipeline) { - return (List) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) throws IOException { - if (isInMulti()) { - // call directly if in a transaction - return pipeline.doInRedis(JedisTemplate.this); - } - - return redis.pipelined(new PipelineBlock() { - @Override - public void execute() { - try { - JedisTemplate.this.pipeline = this; - pipeline.doInRedis(JedisTemplate.this); - } catch (IOException e) { - disconnect(); - throw new DataAccessResourceFailureException("I/O exception thrown connecting to Redis: " + e.getMessage(), e); - } catch (RuntimeException e) { - disconnect(); - throw e; - } - finally { - JedisTemplate.this.pipeline = null; - } - } - }); - } - }); - } - - private void disconnect() { - // hack in to get the private client since disconnect() isn't in the interface - Field field = ReflectionUtils.findField(pipeline.getClass(), "client"); - field.setAccessible(true); - try { - Client client = (Client)field.get(pipeline); - client.disconnect(); - } - catch (Exception e) { - ReflectionUtils.handleReflectionException(e); - } - } - - public boolean persist(final String redisKey) { - return (Boolean) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.persist(redisKey) > 0; - } - }); - } - - public JedisTemplate(JedisPool pool) { - this.pool = pool; - } - - public JedisTemplate(JedisPool pool, int timeout) { - this.timeout = timeout; - this.pool = pool; - } - - public Object execute(RedisCallback jedisRedisCallback) { - try { - if (redis == null) { - redis = getNewConnection(); - doConnect(); - } - else { - if (!redis.isConnected()) { - try { - doConnect(); - } - catch (JedisConnectionException e) { - throw new DataAccessResourceFailureException( - "Connection failure connecting to Redis: " + e.getMessage(), e); - } - } - } - - return jedisRedisCallback.doInRedis(redis); - } catch (IOException e) { - throw new DataAccessResourceFailureException("I/O exception thrown connecting to Redis: " + e.getMessage(), e); - } - } - - private void doConnect() { - redis.connect(); - doAuthentication(); - } - - private void doAuthentication() { - if (password != null) { - try { - redis.auth(password); - } catch (Exception e) { - throw new DataAccessResourceFailureException("I/O exception authenticating with Redis: " + e.getMessage(), e); - } - } - } - - protected Jedis getNewConnection() { - Jedis jedis; - if (pool == null) { - jedis = new Jedis(host, port, timeout); - } - else { - try { - jedis = pool.getResource(); - } catch (JedisConnectionException e) { - throw new DataAccessResourceFailureException("Connection timeout getting Jedis connection from pool: " + e.getMessage(), e); - } - } - return jedis; - } - - protected void closeNewConnection(Jedis jedis) { - if (pool == null) { - jedis.disconnect(); - } - else { - pool.returnResource(jedis); - } - } - - @SuppressWarnings("rawtypes") - public SortParams sortParams() { - return new JedisSortParams(); - } - - public void save() { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.save(); - } - else { - redis.save(); - } - - return null; - } - }); - } - - public void bgsave() { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.save(); - } - else { - redis.bgsave(); - } - - return null; - } - }); - } - - public boolean sismember(final String redisKey, final Object o) { - return (Boolean)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - Response response = transaction.sismember(redisKey, o.toString()); - return QUEUED.equals(response.get()); - } - if (pipeline != null) { - pipeline.sismember(redisKey, o.toString()); - return false; - } - return redis.sismember(redisKey, o.toString()); - } - }); - } - - public void del(final String redisKey) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.del(redisKey); - } - else { - if (pipeline != null) { - pipeline.del(redisKey); - } - else { - redis.del(redisKey); - } - } - return null; - } - }); - } - - public long scard(final String redisKey) { - return (Long)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - redis.scard(redisKey); - return 0; - } - return redis.scard(redisKey); - } - }); - } - - public boolean sadd(final String redisKey, final Object o) { - return (Boolean)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - Response response = transaction.sadd(redisKey, o.toString()); - return QUEUED.equals(response.get()); - } - if (pipeline != null) { - pipeline.sadd(redisKey, o.toString()); - return false; - } - return redis.sadd(redisKey, o.toString()) > 0; - } - }); - } - - public boolean srem(final String redisKey, final Object o) { - return (Boolean)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - Response response = transaction.append(redisKey, o.toString()); - return QUEUED.equals(response.get()); - } - if (pipeline != null) { - pipeline.srem(redisKey, o.toString()); - return false; - } - return redis.srem(redisKey, o.toString()) > 0; - } - }); - } - - public Set smembers(final String redisKey) { - return (Set) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.smembers(redisKey); - } - }); - } - - public void lset(final String redisKey, final int index, final Object o) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.lset(redisKey, index, o.toString()); - } - else { - if (pipeline != null) { - pipeline.lset(redisKey, index, o.toString()); - } else { - redis.lset(redisKey, index, o.toString()); - } - } - return null; - } - }); - } - - public void ltrim(final String redisKey, final int start, final int end) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.ltrim(redisKey, start, end); - } - else { - if (pipeline != null) { - pipeline.ltrim(redisKey, start, end); - } else { - redis.ltrim(redisKey, start, end); - } - } - return null; - } - }); - } - - public String lindex(final String redisKey, final int index) { - return (String) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.lindex(redisKey, index); - return null; - } - return redis.lindex(redisKey, index); - } - }); - } - - public long llen(final String redisKey) { - return (Long) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.llen(redisKey); - return 0; - } - return redis.llen(redisKey); - } - }); - } - - public List lrange(final String redisKey, final int start, final int end) { - return (List) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.lrange(redisKey, start, end); - return null; - } - return redis.lrange(redisKey, start, end); - } - }); - } - - public String rename(final String old, final String newKey) { - return (String) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.rename(old, newKey); - } - else if (pipeline != null) { - pipeline.rename(old, newKey); - } - else { - return redis.rename(old, newKey); - } - - return null; - } - }); - - } - - public String rpop(final String redisKey) { - return (String) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.rpop(redisKey); - } - else if (pipeline != null) { - pipeline.rpop(redisKey); - } - else { - return redis.rpop(redisKey); - } - - return null; - } - }); - } - - public void rpush(final String redisKey, final Object o) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.rpush(redisKey, o.toString()); - } - else { - if (pipeline != null) { - pipeline.rpush(redisKey, o.toString()); - } else { - redis.rpush(redisKey, o.toString()); - } - } - return null; - } - }); - } - - public long lrem(final String redisKey, final Object o, final int count) { - return (Long) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.lrem(redisKey, count, o.toString()); - return 0; - } - if (pipeline != null) { - pipeline.lrem(redisKey, count, o.toString()); - return 0; - } - return redis.lrem(redisKey, count, o.toString()); - } - }); - } - - public void flushdb() { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - redis.flushDB(); - return null; - } - }); - } - - public void flushall() { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - redis.flushAll(); - return null; - } - }); - } - - public void select(final int index) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - redis.select(index); - return null; - } - }); - } - - public long dbsize() { - return (Long) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.dbSize(); - } - }); - } - - public void lpush(final String redisKey, final Object o) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.lpush(redisKey, o.toString()); - } - else { - if (pipeline != null) { - pipeline.lpush(redisKey, o.toString()); - } else { - redis.lpush(redisKey, o.toString()); - } - } - - return null; - } - }); - } - - public void lpop(final String redisKey) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.lpop(redisKey); - } - else { - if (pipeline != null) { - pipeline.lpop(redisKey); - } else { - redis.lpop(redisKey); - } - } - - return null; - } - }); - } - - public String hget(final String redisKey, final String entryKey) { - return (String) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.hget(redisKey, entryKey); - return null; - } - return redis.hget(redisKey, entryKey); - } - }); - } - - public long hlen(final String redisKey) { - return (Long) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.hlen(redisKey); - return 0; - } - return redis.hlen(redisKey); - } - }); - } - - public List hkeys(final String redisKey) { - return (List) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.hkeys(redisKey); - return null; - } - return redis.hkeys(redisKey); - } - }); - } - - public boolean hset(final String redisKey, final String key, final Object o) { - return (Boolean)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - return transaction.hset(redisKey, key, o.toString()).equals(QUEUED); - } - if (pipeline != null) { - pipeline.hset(redisKey, key, o.toString()); - return false; - } - return redis.hset(redisKey, key, o.toString()) > 0; - } - }); - } - - public boolean hsetnx(final String redisKey, final String key, final Object o) { - return (Boolean)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - return transaction.hsetnx(redisKey, key, o.toString()).equals(QUEUED); - } - if (pipeline != null) { - pipeline.hsetnx(redisKey, key, o.toString()); - return false; - } - return redis.hsetnx(redisKey, key, o.toString()) > 0; - } - }); - } - - public List hvals(final String redisKey) { - return (List) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.hvals(redisKey); - return null; - } - return redis.hvals(redisKey); - } - }); - } - - public boolean hdel(final String redisKey, final String entryKey) { - return (Boolean)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - return transaction.hdel(redisKey, entryKey).equals(QUEUED); - } - if (pipeline != null) { - pipeline.hdel(redisKey, entryKey); - return false; - } - return redis.hdel(redisKey, entryKey) > 0; - } - }); - } - - public boolean hexists(final String redisKey, final String entryKey) { - return (Boolean)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - return transaction.hexists(redisKey, entryKey).equals(QUEUED); - } - if (pipeline != null) { - pipeline.hexists(redisKey, entryKey); - return false; - } - return redis.hexists(redisKey, entryKey); - } - }); - } - - public Map hgetall(final String redisKey) { - return (Map) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.hgetAll(redisKey); - return null; - } - return redis.hgetAll(redisKey); - } - }); - } - - public boolean hincrby(final String redisKey, final String entryKey, final int amount) { - return (Boolean)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - return transaction.hincrBy(redisKey, entryKey, amount).equals(QUEUED); - } - if (pipeline != null) { - pipeline.hincrBy(redisKey, entryKey, amount); - return false; - } - return redis.hincrBy(redisKey, entryKey, amount) > 0; - } - }); - } - - public List hmget(final String hashKey, final String... fields) { - return (List) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.hmget(hashKey, fields); - return null; - } - return redis.hmget(hashKey, fields); - } - }); - } - - public void hmset(final String key, final Map nativeEntry) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.hmset(key, nativeEntry); - } - else { - if (pipeline != null) { - pipeline.hmset(key, nativeEntry); - return null; - } - redis.hmset(key, nativeEntry); - } - - return null; - } - }); - } - - public long incr(final String key) { - return (Long)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) throws IOException { - if (transaction != null) { - redis = getNewConnection(); - redis.connect(); - try { - return redis.incr(key); - } - finally { - closeNewConnection(redis); - } - } - return redis.incr(key); - } - }); - } - - public long incrby(final String key, final int amount) { - return (Long)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) throws IOException { - if (transaction != null) { - redis = getNewConnection(); - redis.connect(); - try { - return redis.incrBy(key, amount); - } - finally { - closeNewConnection(redis); - } - } - return redis.incrBy(key, amount); - } - }); - } - - public long del(final String... redisKey) { - return (Long)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.del(redisKey); - return 0; - } - return redis.del(redisKey); - } - }); - } - - public Set sinter(final String...keys) { - return (Set) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.sinter(keys); - } - }); - } - - public Set sunion(final String... keys) { - return (Set) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.sunion(keys); - } - }); - } - - public void sinterstore(final String storeKey, final String... keys) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.sinterstore(storeKey, keys); - } - else { - redis.sinterstore(storeKey, keys); - } - return null; - } - }); - } - - public void sunionstore(final String storeKey, final String... keys) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.sunionstore(storeKey, keys); - } - else { - redis.sunionstore(storeKey, keys); - } - return null; - } - }); - } - - public Set sdiff(final String... keys) { - return (Set) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.sdiff(keys); - } - }); - } - - public boolean smove(final String source, final String destination, final String member) { - return (Boolean) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.smove(source, destination, member); - } - else { - if (pipeline != null) { - pipeline.smove(source, destination, member); - return null; - } - return redis.smove(source, destination, member) > 0; - } - - return false; - } - }); - } - - public void sdiffstore(final String storeKey, final String... keys) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.sdiffstore(storeKey, keys); - } - else { - redis.sdiffstore(storeKey, keys); - } - return null; - } - }); - } - - public boolean setnx(final String redisKey, final Object o) { - return (Boolean)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - return transaction.setnx(redisKey, o.toString()).equals(QUEUED); - } - return redis.setnx(redisKey, o.toString()) > 0; - } - }); - } - - public long strlen(final String redisKey) { - return (Long)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.strlen(redisKey); - } - }); - } - - public boolean expire(final String key, final int timeout) { - return (Boolean)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - Response response = transaction.expire(key, timeout); - return QUEUED.equals(response.get()); - } - return redis.expire(key,timeout) > 0; - } - }); - } - - public long ttl(final String key) { - return (Long)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.ttl(key); - } - }); - } - - public String type(final String key) { - return (String) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.type(key); - } - }); - } - - public String getset(final String redisKey, final Object o) { - return (String) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.getSet(redisKey, o.toString()); - } - }); - } - - public Set keys(final String pattern) { - return (Set) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) throws IOException { - if (transaction != null) { - redis = getNewConnection(); - redis.connect(); - try { - return redis.keys(pattern); - } - finally { - closeNewConnection(redis); - } - } - return redis.keys(pattern); - } - }); - } - - public void close() { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) throws IOException { - if (pool != null) { - pool.returnResource(redis); - } - else { - redis.disconnect(); - } - return null; - } - }); - } - - public Object multi() { - return execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - transaction = redis.multi(); - return transaction; - } - }); - } - - public Jedis getRedisClient() { - return redis; - } - - public boolean exists(final String key) { - return (Boolean)execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.exists(key); - } - }); - } - - public String get(final String key) { - return (String) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.get(key); - } - }); - } - - public List mget(final String... keys) { - return (List) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.mget(keys); - } - }); - } - - public void mset(Map map) { - final String[] keysAndValues = new String[map.size()*2]; - int index = 0; - for (String key : map.keySet()) { - keysAndValues[index++] = key; - keysAndValues[index++] = map.get(key); - } - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.mset(keysAndValues); - } - else { - redis.mset(keysAndValues); - } - - return null; - } - }); - } - - public Object[] exec() { - return (Object[]) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - List results = transaction.exec(); - try { - return results.toArray(new Object[results.size()]); - } finally { - transaction = null; - } - } - throw new NoTransactionException("No transaction started. Call multi() first!"); - } - }); - } - - public void discard() { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) throws IOException { - if (transaction != null) { - transaction.discard(); - transaction = null; - redis.disconnect(); - JedisTemplate.this.redis = null; - } - - return null; - } - }); - } - - public boolean zadd(final String key, final double rank, final Object o) { - return (Boolean) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - return transaction.zadd(key, rank, o.toString()).equals(QUEUED); - } - if (pipeline != null) { - pipeline.zadd(key, rank, o.toString()); - return true; - } - return redis.zadd(key, rank, o.toString()) > 0; - } - }); - } - - public long zcount(final String key, final double min, final double max) { - return (Long) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.zcount(key, min, max); - } - }); - } - - public double zincrby(final String key, final double score, final String member) { - return (Double) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.zincrby(key, score, member); - } - }); - } - - public long zinterstore(final String destKey, final String...keys) { - return (Long) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.zinterstore(destKey, keys); - return 0; - } - return redis.zinterstore(destKey,keys); - } - }); - } - - public long zunionstore(final String destKey, final String... keys) { - return (Long) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.zunionstore(destKey, keys); - return 0; - } - return redis.zunionstore(destKey, keys); - } - }); - } - - public long zcard(final String key) { - return (Long) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.zcard(key); - } - }); - } - - public long zrank(final String key, final Object member) { - return (Long) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - redis.zrank(key, member.toString()); - return 0; - } - return redis.zrank(key, member.toString()); - } - }); - } - - public long zrem(final String key, final Object member) { - return (Long) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.zrem(key, member.toString()); - return 0; - } - return redis.zrem(key, member.toString()); - } - }); - } - - public Set zrange(final String key, final int fromIndex, final int toIndex) { - return (Set) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.zrange(key, fromIndex, toIndex); - } - }); - } - - public Set zrangebyscore(final String sortKey, final double rank1, final double rank2) { - return (Set) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.zrangeByScore(sortKey, rank1, rank2); - } - }); - } - - public void set(final String key, final Object value) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.set(key, value.toString()); - } - else { - redis.set(key, value.toString()); - } - - return null; - } - }); - } - - public void setex(final String key, final Object value, final int timeout) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (transaction != null) { - transaction.setex(key, timeout, String.valueOf(value)); - } - else { - redis.setex(key, timeout, String.valueOf(value)); - } - return null; - } - }); - } - - public Double zscore(final String key, final String member) { - return (Double) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - if (pipeline != null) { - pipeline.zscore(key, member); - return 0; - } - return redis.zscore(key, member); - } - }); - } - - public Set zrevrange(final String key, final int start, final int end) { - return (Set) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.zrevrange(key, start, end); - } - }); - } - - public void setPassword(String pass) { - this.password = pass; - } - - public String srandmember(final String key) { - return (String) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.srandmember(key); - } - }); - } - - public String spop(final String key) { - return (String) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.spop(key); - } - }); - } - - public List sort(final String key, final SortParams params) { - return (List) execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - return redis.sort(key, params.getParamList().get(0)); - } - }); - } - - public void sortstore(final String key, final String destKey, final SortParams params) { - execute(new RedisCallback() { - public Object doInRedis(Jedis redis) { - redis.sort(key, params.getParamList().get(0), destKey); - return null; - } - }); - } - - public boolean isInMulti() { - return getRedisClient().getClient().isInMulti(); - } - - private class JedisSortParams extends SortParams { - private SortingParams nativeParams; - - private JedisSortParams() { - this.nativeParams = new SortingParams(); - getParamList().add(nativeParams); - } - - @Override - protected SortingParams createAlpha() { - nativeParams.alpha(); - return nativeParams; - } - - @Override - protected SortingParams createDesc() { - nativeParams.desc(); - return nativeParams; - } - - @Override - protected SortingParams createGet(String pattern) { - nativeParams.get(pattern); - return nativeParams; - } - - @Override - protected SortingParams createLimit(int start, int count) { - nativeParams.limit(start, count); - return nativeParams; - } - - @Override - protected SortingParams createAsc() { - nativeParams.asc(); - return nativeParams; - } - - @Override - protected SortingParams createBy(String pattern) { - nativeParams.by(pattern); - return nativeParams; - } - } -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/util/RedisCallback.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/util/RedisCallback.java deleted file mode 100644 index ec9ecc2c8..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/util/RedisCallback.java +++ /dev/null @@ -1,31 +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.mapping.redis.util; - -import java.io.IOException; - -/** - * @author Graeme Rocher - */ -public interface RedisCallback { - - /** - * Executes redis logic whilst handling exec. - * - * @param redis The RedisClient instance - * @return The result of the calling jredis - */ - Object doInRedis(T redis) throws IOException; -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/util/RedisTemplate.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/util/RedisTemplate.java deleted file mode 100644 index b8cc7dc47..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/util/RedisTemplate.java +++ /dev/null @@ -1,229 +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.mapping.redis.util; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Interface for RedisTemplate implementations to implement. - * - * @param The concrete Redis client class - */ -public interface RedisTemplate { - - /** - * See http://redis.io/commands/append - */ - boolean append(String key, Object val); - - /** - * See http://redis.io/commands/blpop - */ - List blpop(int timeout, String... keys); - - /** - * See http://redis.io/commands/brpop - */ - List brpop(int timeout, String... keys); - - /** - * See http://redis.io/commands/decr - */ - boolean decr(String key); - - /** - * See http://redis.io/commands/decrby - */ - boolean decrby(String key, int amount); - - /** - * See http://redis.io/commands/del - */ - void del(String redisKey); - - /** - * See http://redis.io/commands/del - */ - long del(String... redisKey); - - List pipeline(RedisCallback> pipeline); - - boolean persist(String redisKey); - - Object execute(RedisCallback callback); - - @SuppressWarnings("rawtypes") - SortParams sortParams(); - - void save(); - - void bgsave(); - - boolean sismember(String redisKey, Object o); - - long scard(String redisKey); - - boolean sadd(String redisKey, Object o); - - boolean srem(String redisKey, Object o); - - Set smembers(String redisKey); - - void lset(String redisKey, int index, Object o); - - void ltrim(String redisKey, int start, int end); - - String lindex(String redisKey, int index); - - long llen(String redisKey); - - List lrange(String redisKey, int start, int end); - - String rename(String old, String newKey); - - String rpop(String redisKey); - - void rpush(String redisKey, Object o); - - long lrem(String redisKey, Object o, int count); - - void flushdb(); - - void flushall(); - - void select(int index); - - long dbsize(); - - void lpush(String redisKey, Object o); - - void lpop(String redisKey); - - String hget(String redisKey, String entryKey); - - long hlen(String redisKey); - - List hkeys(String redisKey); - - boolean hset(String redisKey, String key, Object o); - - boolean hsetnx(String redisKey, String key, Object o); - - List hvals(String redisKey); - - boolean hdel(String redisKey, String entryKey); - - boolean hexists(String redisKey, String entryKey); - - Map hgetall(String redisKey); - - boolean hincrby(String redisKey, String entryKey, int amount); - - List hmget(String hashKey, String... fields); - - void hmset(String key, Map nativeEntry); - - long incr(String key); - - long incrby(String key, int amount); - - Set sinter(String...keys); - - Set sunion(String... keys); - - void sinterstore(String storeKey, String... keys); - - void sunionstore(String storeKey, String... keys); - - Set sdiff(final String... keys); - - boolean smove(String source, String destination, String member); - - void sdiffstore(String key, String... otherKeys); - - boolean setnx(String redisKey, Object o); - - long strlen(String redisKey); - - boolean expire(String key, int timeout); - - long ttl(String key); - - String type(String key); - - String getset(String redisKey, Object o); - - Set keys(String pattern); - - void close(); - - Object multi(); - - boolean exists(String key); - - String get(String key); - - List mget(String...keys); - - void mset(Map map); - - Object[] exec(); - - void discard(); - - boolean zadd(String key, double rank, Object o); - - long zcard(String key); - - long zcount(String key, double min, double max); - - double zincrby(String key, double score, String member); - - long zinterstore(final String destKey, final String...keys); - - long zunionstore(final String destKey, final String...keys); - - long zrank(String key, Object member); - - long zrem(String key, Object member); - - Set zrange(String key, int fromIndex, int toIndex); - - Set zrangebyscore(String sortKey, double rank1, double rank2); - - void set(String key, Object value); - - void setex(String key, Object value, int timeout); - - Double zscore(String key, String member); - - Set zrevrange(String key, int start, int end); - - void setPassword(String pass); - - String srandmember(String key); - - String spop(String key); - - List sort(String key, SortParams params); - - void sortstore(String key, String destKey, SortParams params); - - T getRedisClient(); - - boolean isInMulti(); -} diff --git a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/util/SortParams.java b/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/util/SortParams.java deleted file mode 100644 index 65243c34d..000000000 --- a/grails-datastore-redis/src/main/java/org/grails/datastore/mapping/redis/util/SortParams.java +++ /dev/null @@ -1,85 +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.mapping.redis.util; - -import java.util.ArrayList; -import java.util.List; - -/** - * Parameters used for sorting. - * - * @author Graeme Rocher - */ -public abstract class SortParams { - - List paramList = new ArrayList(); - - public List getParamList() { - return paramList; - } - - @SuppressWarnings("rawtypes") - public SortParams by(final String pattern) { - paramList.add(createBy(pattern)); - return this; - } - - @SuppressWarnings("rawtypes") - public SortParams limit(final int start, final int count) { - paramList.add(createLimit(start, count)); - return this; - } - - @SuppressWarnings("rawtypes") - public SortParams get(final String pattern) { - paramList.add(createGet(pattern)); - return this; - } - - @SuppressWarnings("rawtypes") - public SortParams asc() { - paramList.add(createAsc()); - return this; - } - - @SuppressWarnings("rawtypes") - public SortParams desc() { - paramList.add(createDesc()); - return this; - } - - @SuppressWarnings("rawtypes") - public SortParams alpha() { - paramList.add(createAlpha()); - return this; - } - - protected abstract T createAlpha(); - - protected abstract T createDesc(); - - protected abstract T createGet(String pattern); - - protected abstract T createLimit(int start, int count); - - protected abstract T createAsc(); - - protected abstract T createBy(String pattern); - - @SuppressWarnings("unchecked") - public T[] getParamArray() { - return (T[])paramList.toArray(); - } -} diff --git a/grails-datastore-redis/src/test/groovy/grails/persistence/Entity.java b/grails-datastore-redis/src/test/groovy/grails/persistence/Entity.java deleted file mode 100644 index 725fbaf53..000000000 --- a/grails-datastore-redis/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-redis/src/test/groovy/org/grails/datastore/mapping/redis/AbstractRedisTest.groovy b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/AbstractRedisTest.groovy deleted file mode 100644 index 9dbeb638f..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/AbstractRedisTest.groovy +++ /dev/null @@ -1,30 +0,0 @@ -package org.grails.datastore.mapping.redis - -import org.junit.After -import org.junit.Before -import org.springframework.context.support.GenericApplicationContext -import org.grails.datastore.mapping.core.DatastoreUtils -import org.grails.datastore.mapping.core.Session - -abstract class AbstractRedisTest { - - protected RedisDatastore ds - protected Session session - - @Before - void setUp() { - def ctx = new GenericApplicationContext() - ctx.refresh() - ds = new RedisDatastore() - ds.applicationContext = ctx - - session = ds.connect() - DatastoreUtils.bindSession session - } - - @After - void tearDown() { - session.disconnect() - ds.destroy() - } -} diff --git a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/BackgroundIndexerTests.groovy b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/BackgroundIndexerTests.groovy deleted file mode 100644 index 1d7d64af2..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/BackgroundIndexerTests.groovy +++ /dev/null @@ -1,63 +0,0 @@ -package org.grails.datastore.mapping.redis - -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.springframework.context.support.GenericApplicationContext -import org.grails.datastore.mapping.core.DatastoreUtils -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.redis.util.JedisTemplate -import org.grails.datastore.mapping.redis.util.RedisTemplate - -import redis.clients.jedis.Jedis - -/** - * Tests background indexing functions correctly - */ -class BackgroundIndexerTests { - - private RedisDatastore ds - private Session session - - @Before - void setUp() { - def ctx = new GenericApplicationContext() - ctx.refresh() - ds = new RedisDatastore() - ds.applicationContext = ctx - } - - @After - void tearDown() { - session.disconnect() - ds.destroy() - } - - @Test - void testBackgroundIndexer() { - - // create some existing data - def template = createTemplate() - template.flushdb() - - template.hmset("org.grails.datastore.mapping.redis.Book:1", [title:"It"]) - template.hmset("org.grails.datastore.mapping.redis.Book:2", [title:"The Shining"]) - template.sadd("org.grails.datastore.mapping.redis.Book.all", 1L) - template.sadd("org.grails.datastore.mapping.redis.Book.all", 2L) - - // initialise datastore - ds.mappingContext.addPersistentEntity(Book) - ds.afterPropertiesSet() - - session = ds.connect() - DatastoreUtils.bindSession session - - def results = session.createQuery(Book).eq("title", "It").list() - - assert 1 == results.size() - } - - private RedisTemplate createTemplate() { - return new JedisTemplate(new Jedis("localhost")) - } -} diff --git a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/CountQueryTests.groovy b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/CountQueryTests.groovy deleted file mode 100644 index 0d5add4f1..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/CountQueryTests.groovy +++ /dev/null @@ -1,63 +0,0 @@ -package org.grails.datastore.mapping.redis - -import static org.grails.datastore.mapping.query.Restrictions.* - -import org.junit.Test -import org.grails.datastore.mapping.query.Query - -class CountQueryTests extends AbstractRedisTest { - - @Test - void testDisjunctionAndCount() { - ds.mappingContext.addPersistentEntity(Author) - session.getNativeInterface().flushall() - - def a = new Author(name:"Stephen King") - a.books = [ - new Book(title:"The Stand"), - new Book(title:"It") , - new Book(title:"The Shining") - ] - - session.persist(a) - - Query q = session.createQuery(Book) - q.disjunction() - .add( eq( "title", "The Stand" ) ) - .add( eq( "title", "It" ) ) - q.projections().count() - - assert 2 == q.singleResult() - } - - @Test - void testSimpleQueryAndCount() { - ds.mappingContext.addPersistentEntity(Author) - session.getNativeInterface().flushall() - - def a = new Author(name:"Stephen King") - a.books = [ - new Book(title:"The Stand"), - new Book(title:"It") - ] - - session.persist(a) - - Query q = session.createQuery(Book) - q.eq("title", "It") - q.projections().count() - - def result = q.singleResult() - - assert 1 == result - - q = session.createQuery(Book) - - q.eq("title", "The Stand") - q.projections().count() - - result = q.singleResult() - - assert 1 == result - } -} diff --git a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/LazyLoadedOneToOneTests.java b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/LazyLoadedOneToOneTests.java deleted file mode 100644 index 4b12bbfe2..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/LazyLoadedOneToOneTests.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.grails.datastore.mapping.redis; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; -import javassist.util.proxy.ProxyObject; - -import org.grails.datastore.mapping.proxy.EntityProxy; -import org.junit.Test; - -public class LazyLoadedOneToOneTests extends AbstractRedisTest { - - @Test - public void testLazyLoadedOneToOne() { - ds.getMappingContext().addPersistentEntity(Person.class); - - Person p = new Person(); - p.setName("Bob"); - Address a = new Address(); - a.setNumber("22"); - a.setPostCode("308420"); - p.setAddress(a); - session.persist(a); - session.persist(p); - session.flush(); - - session.clear(); - - p = session.retrieve(Person.class, p.getId()); - - Address proxy = p.getAddress(); - - assertTrue(proxy instanceof ProxyObject); - assertTrue(proxy instanceof EntityProxy); - - EntityProxy ep = (EntityProxy) proxy; - assertFalse(ep.isInitialized()); - assertEquals(a.getId(), proxy.getId()); - - assertFalse(ep.isInitialized()); - assertEquals("22", a.getNumber()); - } - - @Test - public void testProxyMethod() { - ds.getMappingContext().addPersistentEntity(Person.class); - - Person p = new Person(); - p.setName("Bob"); - Address a = new Address(); - a.setNumber("22"); - a.setPostCode("308420"); - p.setAddress(a); - session.persist(p); - session.flush(); - session.clear(); - - Person personProxy = session.proxy(Person.class, p.getId()); - - EntityProxy proxy = (EntityProxy) personProxy; - - assertFalse(proxy.isInitialized()); - assertEquals(p.getId(), personProxy.getId()); - - assertFalse(proxy.isInitialized()); - - assertEquals("Bob", personProxy.getName()); - - assertTrue(proxy.isInitialized()); - } -} diff --git a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/ListQueryTests.groovy b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/ListQueryTests.groovy deleted file mode 100644 index 37c8eeb99..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/ListQueryTests.groovy +++ /dev/null @@ -1,125 +0,0 @@ -package org.grails.datastore.mapping.redis - -import static org.grails.datastore.mapping.query.Restrictions.* - -import org.junit.Test -import org.grails.datastore.mapping.query.Query - -/** - * @author Graeme Rocher - * @since 1.1 - */ -class ListQueryTests extends AbstractRedisTest { - - @Test - void testListQuery() { - ds.mappingContext.addPersistentEntity(Author) - session.getNativeInterface().flushall() - - def a = new Author(name:"Stephen King") - a.books = [ - new Book(title:"The Stand"), - new Book(title:"It") - ] - - session.persist(a) - - Query q = session.createQuery(Book) - - def results = q.list() - - assert 2 == results.size() - - assert null != results.find { it.title == "The Stand" } - assert null != results.find { it.title == "It" } - - q.max 1 - - results = q.list() - - assert 1 == results.size() - assert "The Stand" == results[0].title - } - - @Test - void testDisjunction() { - ds.mappingContext.addPersistentEntity(Author) - session.getNativeInterface().flushall() - - def a = new Author(name:"Stephen King") - a.books = [ - new Book(title:"The Stand"), - new Book(title:"It") , - new Book(title:"The Shining") - ] - - session.persist(a) - - Query q = session.createQuery(Book) - q.disjunction() - .add(eq("title", "The Stand")) - .add(eq("title", "It")) - - def results = q.list() - - assert 2 == results.size() - } - - @Test - void testIdProjection() { - ds.mappingContext.addPersistentEntity(Author) - session.getNativeInterface().flushall() - - def a = new Author(name:"Stephen King") - a.books = [ - new Book(title:"The Stand"), - new Book(title:"It") , - new Book(title:"The Shining") - ] - - session.persist(a) - - Query q = session.createQuery(Book) - q.disjunction() - .add(eq("title", "The Stand")) - .add(eq("title", "It")) - q.projections().id() - - def results = q.list() - - assert 2 == results.size() - assert results[0] instanceof Long - } - - @Test - void testSimpleQuery() { - ds.mappingContext.addPersistentEntity(Author) - session.getNativeInterface().flushall() - - def a = new Author(name:"Stephen King") - a.books = [ - new Book(title:"The Stand"), - new Book(title:"It") - ] - - session.persist(a) - - Query q = session.createQuery(Book) - - q.eq("title", "It") - - def results = q.list() - - assert 1 == results.size() - assert "It" == results[0].title - - q = session.createQuery(Book) - - q.eq("title", "The Stand") - - results = q.list() - - assert 1 == results.size() - assert "The Stand" == results[0].title - } -} diff --git a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/LockTests.groovy b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/LockTests.groovy deleted file mode 100644 index 4f9d80913..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/LockTests.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package org.grails.datastore.mapping.redis - -import org.junit.After -import org.junit.Test -import org.grails.datastore.mapping.core.Session - -/** - * Tests for locking - */ -class LockTests extends AbstractRedisTest { - - private Session s2 - - @Test - void testLock() { - return // not yet implemented - ds.mappingContext.addPersistentEntity(Candidate) - session.getNativeInterface().flushdb() - - def c = new Candidate() - session.persist(c) - session.flush() - - int x = 5 - int y = 3 - def threads = [] - s2 = ds.connect() - x.times { - threads << Thread.start { - y.times { - def c2 = s2.lock(Candidate, c.id) - c2.votes++ - s2.persist(c2) - s2.flush() - s2.unlock c2 - } - } - } - - threads.each { Thread t -> t.join() } - - c = session.retrieve(Candidate, c.id) - - assert x * y == c.votes - } - - @After - void after() { - s2?.disconnect() - } -} - -class Candidate { - Long id - String name - int votes -} diff --git a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/OneToManyAssociationTests.groovy b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/OneToManyAssociationTests.groovy deleted file mode 100644 index f2802471e..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/OneToManyAssociationTests.groovy +++ /dev/null @@ -1,53 +0,0 @@ -package org.grails.datastore.mapping.redis - -import grails.persistence.Entity - -import org.junit.Test -import org.grails.datastore.mapping.core.Session - -/** - * @author Graeme Rocher - * @since 1.0 - */ -class OneToManyAssociationTests extends AbstractRedisTest { - - @Test - void testOneToManyAssociation() { - ds.mappingContext.addPersistentEntity(Author) - - def a = new Author(name:"Stephen King") - a.books = [ new Book(title:"The Stand"), new Book(title:"It")] - - session.persist(a) - - a = session.retrieve(Author, a.id) - - assert a != null - assert "Stephen King" == a.name - assert a.books != null - assert 2 == a.books.size() - - def b1 = a.books.find { it.title == 'The Stand'} - assert b1 != null - assert b1.id != null - assert "The Stand" == b1.title - } -} - -@Entity -class Author { - Long id - String name - List books - static hasMany = [books:Book] -} - -@Entity -class Book { - Long id - String title - - static mapping = { - title index:true - } -} diff --git a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/OneToManyLazyAssociationTests.groovy b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/OneToManyLazyAssociationTests.groovy deleted file mode 100644 index 4b3b6a7d7..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/OneToManyLazyAssociationTests.groovy +++ /dev/null @@ -1,55 +0,0 @@ -package org.grails.datastore.mapping.redis - -import grails.persistence.Entity - -import org.junit.Test -import org.grails.datastore.mapping.collection.PersistentList -import org.grails.datastore.mapping.core.Session - -class OneToManyLazyAssociationTests extends AbstractRedisTest { - - @Test - void testOneToManyAssociation() { - return - - ds.mappingContext.addPersistentEntity(LazyAuthor) - session.nativeInterface.flushall() - - def a = new LazyAuthor(name:"Stephen King") - a.books = [ new LazyBook(title:"The Stand"), new LazyBook(title:"It")] - - session.persist(a) - session.flush() - - session.clear() - - a = session.retrieve(LazyAuthor, a.id) - - assert a != null - assert "Stephen King" == a.name - assert a.books != null - assert a.books instanceof PersistentList - assert !a.books.isInitialized() - assert 2 == a.books.size() - assert a.books.isInitialized() - - def b1 = a.books.find { it.title == 'The Stand'} - assert b1 != null - assert b1.id != null - assert "The Stand" == b1.title - } -} - -@Entity -class LazyAuthor { - Long id - String name - List books - static hasMany = [books:LazyBook] -} - -@Entity -class LazyBook { - Long id - String title -} diff --git a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/OneToOneAssociationTests.groovy b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/OneToOneAssociationTests.groovy deleted file mode 100644 index 40c980496..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/OneToOneAssociationTests.groovy +++ /dev/null @@ -1,44 +0,0 @@ -package org.grails.datastore.mapping.redis - -import grails.persistence.Entity - -import org.junit.Test -import org.grails.datastore.mapping.core.Session - -/** - * @author Graeme Rocher - * @since 1.1 - */ -class OneToOneAssociationTests extends AbstractRedisTest { - - @Test - void testPersistOneToOneAssociation() { - ds.mappingContext.addPersistentEntity(Person) - - def p = new Person(name:"Bob") - p.address = new Address(number:"20", postCode:"39847") - - session.persist(p) - - p = session.retrieve(Person, p.id) - - assert p != null - assert "Bob" == p.name - assert p.address != null - assert "20" == p.address.number - } -} - -@Entity -class Person { - Long id - String name - Address address -} - -@Entity -class Address { - Long id - String number - String postCode -} diff --git a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/RedisEntityPesisterTests.groovy b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/RedisEntityPesisterTests.groovy deleted file mode 100644 index df24b43ff..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/RedisEntityPesisterTests.groovy +++ /dev/null @@ -1,75 +0,0 @@ -package org.grails.datastore.mapping.redis - -import org.junit.Test -import org.grails.datastore.mapping.core.Session - -/** - * @author Graeme Rocher - * @since 1.1 - */ -class RedisEntityPesisterTests extends AbstractRedisTest { - - @Test - void testPersistObject() { - - session.nativeInterface.flushdb() - ds.getMappingContext().addPersistentEntity(TestEntity) - -// assert session.retrieve(TestEntity, new RedisKey(1)) == null - - TestEntity t = new TestEntity() - t.name = "bob" - session.persist(t) - - assert t.id != null - - def key = t.id - t = session.retrieve(TestEntity, key) - - assert t != null - assert "bob" == t.name - - session.delete(t) - session.flush() - - t = session.retrieve(TestEntity, key) - assert t == null - } - - @Test - void testTransactions() { - if (true) return - // doesn't work right now - ds.getMappingContext().addPersistentEntity(TestEntity) - - assert 0 == session.size() - - def t = session.beginTransaction() - TestEntity te = new TestEntity() - te.name = "bob" - session.persist(te) - TestEntity te2 = new TestEntity() - te2.name = "frank" - session.persist(te2) - t.commit() - - assert 2 == session.size() - - t = session.beginTransaction() - TestEntity te3 = new TestEntity() - te3.name = "joe" - session.persist(te3) - TestEntity te4 = new TestEntity() - te4.name = "jack" - session.persist(te4) - - t.rollback() - - assert 2 == session.size() - } -} - -class TestEntity { - Long id - String name -} diff --git a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/collection/RedisListTests.groovy b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/collection/RedisListTests.groovy deleted file mode 100644 index 72dc2debc..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/collection/RedisListTests.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package org.grails.datastore.mapping.redis.collection - -import org.grails.datastore.mapping.redis.util.JedisTemplate -import org.grails.datastore.mapping.redis.util.RedisTemplate -import org.junit.Before -import org.junit.Test - -import redis.clients.jedis.Jedis - -class RedisListTests { - - def template - - @Before - void setupRedis() { - template = createTemplate() - template.flushdb() - } - - @Test - void testSize() { - def list = new RedisList(template, "test.list") - - assert 0 == list.size() - assert list.empty - - list.add("test") - assert !list.empty - assert 1 == list.size() - } - - @Test - void testIndex() { - def list = new RedisList(template, "test.list") - - assert 0 == list.size() - assert list.empty - - list.add("test") - assert "test" == list[0].toString() - - list[0] = "changed" - assert list[0] == "changed" - - list << 10 - assert list[1].toLong() == 10 - } - - private RedisTemplate createTemplate() { - return new JedisTemplate(new Jedis("localhost")) - } -} diff --git a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/collection/RedisMapTests.groovy b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/collection/RedisMapTests.groovy deleted file mode 100644 index 5c011a23b..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/collection/RedisMapTests.groovy +++ /dev/null @@ -1,32 +0,0 @@ -package org.grails.datastore.mapping.redis.collection - -import org.grails.datastore.mapping.redis.util.JedisTemplate -import org.junit.Before -import org.junit.Test - -import redis.clients.jedis.Jedis - -class RedisMapTests { - - private JedisTemplate template - - @Before - void setupRedis() { - template = new JedisTemplate(new Jedis("localhost")) - template.flushdb() - } - - @Test - void testSize() { - - def map = new RedisMap(template, "test.map") - - assert 0 == map.size() - assert map.isEmpty() - map["foo"] = "bar" - - assert 1 == map.size() - assert !map.isEmpty() - assert map["foo"] == "bar" - } -} diff --git a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/collection/RedisSetTests.groovy b/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/collection/RedisSetTests.groovy deleted file mode 100644 index f4f839b95..000000000 --- a/grails-datastore-redis/src/test/groovy/org/grails/datastore/mapping/redis/collection/RedisSetTests.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package org.grails.datastore.mapping.redis.collection - -import org.junit.Before -import org.junit.Test -import org.grails.datastore.mapping.redis.util.JedisTemplate - -import redis.clients.jedis.Jedis - -class RedisSetTests { - - def template - - @Before - void setupRedis() { - template = createTemplate() - template.flushdb() - } - - @Test - void testSize() { - - def set = new RedisSet(template, "test.set") - - assert 0 == set.size() - assert set.empty - set.add("test") - - assert 1 == set.size() - assert !set.empty - } - - @Test - void testContains() { - def set = new RedisSet(template, "test.set") - - assert !set.contains("test") - - set << "test" - - assert set.contains("test") - - set << 1 - - assert !set.contains(2) - assert set.contains(1) - - set.remove(1) - assert !set.contains(1) - } - - @Test - void testIterator() { - def set = new RedisSet(template, "test.set") - - set << 1 << 2 << 3 - - def count = 0 - set.each { count += it.toLong()} - - assert 6 == count - } - - private createTemplate() { - return new JedisTemplate(new Jedis("localhost")) - } -} diff --git a/grails-datastore-rest-client/build.gradle b/grails-datastore-rest-client/build.gradle deleted file mode 100644 index 0333652d9..000000000 --- a/grails-datastore-rest-client/build.gradle +++ /dev/null @@ -1,69 +0,0 @@ -version = "1.0.0.M2" -dependencies { - compile 'javax.servlet:javax.servlet-api:3.0.1' -// compile("org.grails:grails-plugin-codecs:$grailsVersion") { -// exclude group:'org.grails', module:'grails-plugin-converters' -// exclude group:'org.grails', module:'grails-web' -// } - compile('commons-codec:commons-codec:1.5') - compile("org.grails:grails-plugin-converters:$grailsVersion") { - exclude group:'org.grails', module:'grails-plugin-datasource' - exclude group:'org.grails', module:'grails-plugin-controllers' - exclude group:'org.grails', module:'grails-plugin-domain-class' - exclude group:'org.grails', module:'grails-web' - } -// compile("org.grails:grails-plugin-rest:$grailsVersion") { -// exclude group:'org.grails', module:'grails-plugin-datasource' -// exclude group:'org.grails', module:'grails-plugin-controllers' -// exclude group:'org.grails', module:'grails-web' -// } - compile("org.grails:grails-core:$grailsVersion") { - exclude group:'commons-collections', module:'commons-collections' - exclude group:'com.googlecode.concurrentlinkedhashmap', module:'concurrentlinkedhashmap-lru' - exclude group:'xalan', module:'serializer' - exclude group:'org.springframework', module:'spring-aspects' - exclude group:'org.springframework', module:'spring-context-support' - exclude group:'org.springframework', module:'spring-aop' - exclude group:'org.springframework', module:'spring-tx' - exclude group:'org.springframework', module:'spring-expression' - exclude group:'org.grails', module:'grails-spring' - exclude group:'org.aspectj', module:'aspectjrt' - exclude group:'org.aspectj', module:'aspectjweaver' - exclude group:'oro', module:'oro' - exclude group:'asm', module:'asm' - exclude group:'aopalliance', module:'aopalliance' - exclude group:'cglib', module:'cglib' - exclude group:'commons-validator', module:'commons-validator' - exclude group:'org.hibernate.javax.persistence', module:'hibernate-jpa-2.0-api' - } - compile("org.grails:grails-web:$grailsVersion") { - exclude group:'org.grails', module:'grails-databinding' - exclude group:'org.grails', module:'grails-core' - exclude group:'org.grails', module:'grails-spring' - exclude group:'com.googlecode.concurrentlinkedhashmap', module:'concurrentlinkedhashmap-lru' - exclude group:'commons-collections', module:'commons-collections' - exclude group:'commons-beanutils', module:'commons-beanutils' - exclude group:'commons-lang', module:'commons-lang' - exclude group:'commons-fileupload', module:'commons-fileupload' - exclude group:'xpp3', module:'xpp3_min' - exclude group:'commons-el', module:'commons-el' - exclude group:'org.springframework', module:'spring-webmvc' - exclude group:'opensymphony', module:'sitemesh' - exclude group:'javax.servlet', module:'jstl' - exclude group:'taglibs', module:'standard' - exclude group:'junit', module:'junit' - exclude group:'commons-io', module:'commons-io' - exclude group:'org.objenesis', module:'objenesis' - } - - testCompile("org.springframework:spring-test:$springVersion") -// compile("org.grails:grails-databinding:$grailsVersion") { -// exclude group:'junit', module:'junit' -// } -// compile project(":grails-datastore-gorm"), -// project(":grails-datastore-gorm-plugin-support"), -// project(":grails-datastore-core") - -} - - 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 deleted file mode 100644 index 4b7dac4b3..000000000 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RequestCustomizer.groovy +++ /dev/null @@ -1,392 +0,0 @@ -/* Copyright (C) 2013 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 grails.plugins.rest.client - -import grails.converters.JSON -import grails.converters.XML -import grails.web.JSONBuilder -import groovy.transform.CompileStatic -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.springframework.core.io.FileSystemResource -import org.springframework.core.io.InputStreamResource -import org.springframework.core.io.UrlResource -import org.springframework.http.HttpEntity -import org.springframework.http.HttpHeaders -import org.springframework.http.MediaType -import org.springframework.util.LinkedMultiValueMap -import org.springframework.util.MultiValueMap - -import static org.codehaus.groovy.grails.web.servlet.HttpHeaders.* - -/** - * Core of the DSL for building REST requests - * - * @since 1.0 - * @author Graeme Rocher - */ -@CompileStatic -class RequestCustomizer { - - HttpHeaders headers = new HttpHeaders() - - Class acceptType = String - def body - - MultiValueMap mvm = new LinkedMultiValueMap() - - Map urlVariables = [:] - - /** - * Used to configure BASIC authentication. Example: - * - *
    
    -     * builder.put("http://..") {
    -     *      auth "myuser", "mypassword"
    -     * }
    -     * 
    - * - * @param username The username - * @param password The password - * @return The customizer - */ - RequestCustomizer auth(String username, String password) { - String usernameAndPassword = "$username:$password" - String encoded = new String(Base64.encodeBase64(usernameAndPassword.bytes)) - headers.add AUTHORIZATION, "Basic $encoded".toString() - return this - } - - /** - * Sets the Authorization HTTP header to the given value. Used typically to pass OAuth access tokens. - * - *
    
    -     * builder.put("http://..") {
    -     *      auth myToken
    -     * }
    -     * 
    - * - * @param accessToken The access token - * @return The customizer - */ - RequestCustomizer auth(String accessToken) { - headers.add AUTHORIZATION, accessToken - return this - } - - /** - * Sets the Content-Type HTTP header to the given value. Example: - * - *
    
    -     * restBuilder.put("http://..") {
    -     *      contentType "application/xml"
    -     * }
    -     * 
    - * - * @param contentType The content type - * @return The customizer - */ - RequestCustomizer contentType(String contentType) { - headers.setContentType(MediaType.valueOf(contentType)) - return this - } - - /** - * Sets the Accept HTTP header to the given value. Example: - * - *
    
    -     * restBuilder.get("http://..") {
    -     *      accept "application/xml"
    -     * }
    -     * 
    - * - * @param contentTypes The content types - * @return The customizer - */ - RequestCustomizer accept(String... contentTypes) { - def list = contentTypes.collect { String it -> MediaType.valueOf(it) } - headers.setAccept(list) - return this - } - - /** - * Sets the Accept HTTP header to the given value. Example: - * - *
    
    -     * restBuilder.get("http://..") {
    -     *      accept XML
    -     * }
    -     * 
    - * - * @param responseType The expected response type - * @param contentTypes The content types - * @return The customizer - */ - RequestCustomizer accept(Class responseType, String... contentTypes) { - if(responseType == JSON) { - if(!contentTypes) - accept(MediaType.APPLICATION_JSON_VALUE) - acceptType = JSON - } - else if (responseType == XML) { - if(!contentTypes) - accept(MediaType.APPLICATION_XML_VALUE) - acceptType = XML - - } - else { - acceptType = responseType - } - if(contentTypes) { - accept(contentTypes) - } - return this - } - - /** - * Sets an HTTP header to the given name and value. Example: - * - *
    
    -     * restBuilder.get("http://..") {
    -     *      header "Accept", "text/xml"
    -     * }
    -     * 
    - * - * @param name The name of the header - * @param value The value of the header - * @return The customizer - */ - RequestCustomizer header(String name, String value) { - headers[name] = value - return this - } - - /** - * Sets the body of the request to the JSON defined by the closure. The closure uses JSONBuilder to product a JSON object. Example: - * - *
    
    -     * restBuilder.put("http://..") {
    -     *     json {
    -     *        name = "test-group"
    -     *        description = "A temporary test group"
    -     *     }
    -     * }
    -     * 
    - * - * @param callable The callable closure - * @return This customizer - */ - RequestCustomizer json(@DelegatesTo(JSONBuilder) Closure callable) { - callable.resolveStrategy = Closure.DELEGATE_FIRST - JSON j = new JSONBuilder().build(callable) - json(j) - } - - /** - * Sets the body of the request to the passed JSON - * - * @param json The JSON object - * @return this customizer - */ - RequestCustomizer json(JSON json) { - body = json - if (!headers.contentType) { - contentType MediaType.APPLICATION_JSON_VALUE - } - return this - } - - /** - * Sets the body of the request to the passed JSON - * - * @param json The JSON object - * @return this customizer - */ - RequestCustomizer json(JSONElement json) { - body = json - if (!headers.contentType) { - contentType MediaType.APPLICATION_JSON_VALUE - } - return this - } - - /** - * Sets the body of the request to the passed JSON string - * - * @param json The JSON object - * @return this customizer - */ - RequestCustomizer json(String json) { - body = json - if (!headers.contentType) { - contentType MediaType.APPLICATION_JSON_VALUE - } - return this - } - - /** - * Converts the given object to JSON and sets the body to the converted JSON object - * - * @param object The object to convert to JSON - * @return this customizer - */ - RequestCustomizer json(object) { - json(object as JSON) - } - - /** - * Sets the body of the request to the XML defined by the closure. Uses {@link StreamingMarkupBuilder} to produce the XML - * - * @param closure The closure that defines the XML - * @return This customizer - */ - RequestCustomizer xml(@DelegatesTo(StreamingMarkupBuilder)Closure closure) { - def b = new StreamingMarkupBuilder() - Writable markup = (Writable)b.bind(closure) - body = markup - if (!headers.contentType) { - contentType MediaType.APPLICATION_XML_VALUE - } - return this - } - - /** - * Sets the body of the request to the XML converter argument. - * - * @param xml The XML to be used as the body of the request - * @return This customizer - */ - RequestCustomizer xml(XML xml) { - body = xml - if (!headers.contentType) { - contentType MediaType.APPLICATION_XML_VALUE - } - return this - } - - /** - * Sets the body of the request to the XML string argument. - * - * @param xml The XML to be used as the body of the request - * @return This customizer - */ - RequestCustomizer xml(String xml) { - body = xml - if (!headers.contentType) { - contentType MediaType.APPLICATION_XML_VALUE - } - return this - } - - /** - * Sets the body of the request to the XML GPathResult argument. - * - * @param xml The XML to be used as the body of the request - * @return This customizer - */ - RequestCustomizer xml(GPathResult xml) { - body = xml - if (!headers.contentType) { - contentType MediaType.APPLICATION_XML_VALUE - } - return this - } - - /** - * Converts the given object to XML using Grails' converters and sets the XML as the body of the request - * - * @param object The object - * @return This customizer - */ - RequestCustomizer xml(object) { - xml(object as XML) - } - - /** - * Configures any variables used in the case of a templated URL. Example: - * - *
    
    -     * restBuilder.get("http://../book/{id}") {
    -     *      urlVariables id:1
    -     * }
    -     * 
    - * - * @param variables The URL variables - * @return - */ - RequestCustomizer urlVariables(Map variables) { - if (variables != null) { - this.urlVariables = variables - } - return this - } - - /** - * Sets the body of the request to the given argument. Note that if you argument is not convertable to a message body an exception will be thrown. - * You can register new converters using restBuilder.restTemplate.getMessageConverters().add(..) - * - * @param content The body content - * @return This customizer - */ - RequestCustomizer body(content) { - if ( (content instanceof JSON) || (content instanceof JSONElement)) { - if (!headers.contentType) { - contentType MediaType.APPLICATION_JSON_VALUE - } - body = content - } - else if( (content instanceof XML) || (content instanceof GPathResult)) { - if (!headers.contentType) { - contentType MediaType.APPLICATION_XML_VALUE - } - body = content - } - else { - body = content - } - - return this - } - - HttpEntity createEntity() { - return mvm ? new HttpEntity(mvm, headers) : new HttpEntity(body, headers) - } - - /** - * Sets multipart values within the request body - * - * @param name The name of the multipart - * @param value The value of the multipart - */ - void setProperty(String name, value) { - if (value instanceof File) { - value = new FileSystemResource(value) - } - else if (value instanceof URL) { - value = new UrlResource(value) - } - else if (value instanceof InputStream) { - value = new InputStreamResource(value) - } - if( mvm[name] ) { - mvm[name].add value - } - else { - mvm.put(name, [value]) - } - } -} 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 deleted file mode 100644 index e01f69b4f..000000000 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RestBuilder.groovy +++ /dev/null @@ -1,314 +0,0 @@ -/* Copyright (C) 2013 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 grails.plugins.rest.client - -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.springframework.http.HttpMethod -import org.springframework.http.converter.HttpMessageConverter -import org.springframework.http.converter.StringHttpMessageConverter -import org.springframework.util.ClassUtils - -import static org.springframework.http.HttpMethod.* - -import org.springframework.http.ResponseEntity -import org.springframework.http.client.SimpleClientHttpRequestFactory -import org.springframework.web.client.HttpStatusCodeException -import org.springframework.web.client.RestTemplate - - -/** - * Main API entry to the synchronous version of the REST low-level client API - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class RestBuilder { - - RestTemplate restTemplate = new RestTemplate() - - RestBuilder() { - this(Collections.emptyMap()) - } - - RestBuilder(Map settings) { - - if(ConvertersConfigurationHolder.getConverterConfiguration(JSON) instanceof DefaultConverterConfiguration) { - // init manually - new ConvertersConfigurationInitializer().initialize(new DefaultGrailsApplication()) - } - - Proxy proxyFromSystemProperties = getProxyForSystemProperties() - if (proxyFromSystemProperties && settings.proxy == null) { - settings.proxy = proxyFromSystemProperties - } - - if (settings.proxy instanceof Map) { - def ps = ((Map)settings.proxy).entrySet().iterator().next() - if (ps.value) { - def proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ps.key.toString(), ps.value.toString().toInteger())) - settings.proxy = proxy - } - } - - final customRequestFactory = new SimpleClientHttpRequestFactory() - final metaClass = GroovySystem.metaClassRegistry.getMetaClass(SimpleClientHttpRequestFactory) - for(key in settings.keySet()) { - final prop = key.toString() - if(customRequestFactory.hasProperty(prop)) { - metaClass.setProperty(customRequestFactory, prop, settings.get(key)) - } - } - restTemplate.setRequestFactory(customRequestFactory) - registerMessageConverters(restTemplate) - } - - static Proxy getProxyForSystemProperties() { - def proxyHost = System.getProperty("http.proxyHost") - def proxyPort = System.getProperty("http.proxyPort") - - Proxy proxyFromSystemProperties = null - if (proxyHost && proxyPort) { - proxyFromSystemProperties = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort.toInteger())) - } - proxyFromSystemProperties - } - - RestBuilder(RestTemplate restTemplate) { - this.restTemplate = restTemplate - registerMessageConverters(restTemplate) - } - /** - * Issues a GET request and returns the response in the most appropriate type - * @param url The URL - * @param url The closure customizer used to customize request attributes - */ - RestResponse get(String url, @DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, GET - } - - /** - * Issues a GET request and returns the response in the most appropriate type - * @param url The URL - * @paral urlVariables The urlVariables required by the URL pattern - * @param url The closure customizer used to customize request attributes - */ - RestResponse get(String url, Map urlVariables, @DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, GET, urlVariables - } - - - /** - * Issues a PUT request and returns the response in the most appropriate type - * - * @param url The URL - * @param customizer The clouser customizer - */ - RestResponse put(String url, @DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, PUT - } - - /** - * Issues a PUT request and returns the response in the most appropriate type - * - * @param url The URL - * @param customizer The clouser customizer - */ - RestResponse put(String url, Map urlVariables, @DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, PUT, urlVariables - } - - /** - * Issues a POST request and returns the response - * @param url The URL - * @param customizer (optional) The closure customizer - */ - - RestResponse post(String url, @DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, POST - } - - /** - * Issues a POST request and returns the response - * @param url The URL - * @param customizer (optional) The closure customizer - */ - - RestResponse post(String url, Map urlVariables, @DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, POST, urlVariables - } - - /** - * Issues a PATCH request and returns the response - * @param url The URL - * @param customizer (optional) The closure customizer - */ - - RestResponse patch(String url, @DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, PATCH - } - - /** - * Issues a PATCH request and returns the response - * @param url The URL - * @param customizer (optional) The closure customizer - */ - - RestResponse patch(String url, Map urlVariables, @DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, PATCH, urlVariables - } - - /** - * Issues DELETE a request and returns the response - - * @param url The URL - * @param customizer (optional) The closure customizer - */ - RestResponse delete(String url, @DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, DELETE - } - - /** - * Issues DELETE a request and returns the response - - * @param url The URL - * @param customizer (optional) The closure customizer - */ - RestResponse delete(String url, Map urlVariables,@DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, DELETE, urlVariables - } - - - /** - * Issues HEAD a request and returns the response - - * @param url The URL - * @param customizer (optional) The closure customizer - */ - RestResponse head(String url, Map urlVariables,@DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, HEAD, urlVariables - } - - /** - * Issues HEAD a request and returns the response - - * @param url The URL - * @param customizer (optional) The closure customizer - */ - RestResponse head(String url, @DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, HEAD - } - - /** - * Issues OPTIONS a request and returns the response - - * @param url The URL - * @param customizer (optional) The closure customizer - */ - RestResponse options(String url, Map urlVariables,@DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, OPTIONS, urlVariables - } - - /** - * Issues OPTIONS a request and returns the response - - * @param url The URL - * @param customizer (optional) The closure customizer - */ - RestResponse options(String url, @DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, OPTIONS - } - - /** - * Issues TRACE a request and returns the response - - * @param url The URL - * @param customizer (optional) The closure customizer - */ - RestResponse trace(String url, Map urlVariables,@DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, TRACE, urlVariables - } - - /** - * Issues TRACE a request and returns the response - - * @param url The URL - * @param customizer (optional) The closure customizer - */ - RestResponse trace(String url, @DelegatesTo(RequestCustomizer) Closure customizer = null) { - doRequestInternal url, customizer, TRACE - } - - protected RestResponse doRequestInternal(String url, Closure customizer, HttpMethod method, Map urlVariables = Collections.emptyMap()) { - - def requestCustomizer = new RequestCustomizer() - if(urlVariables) - requestCustomizer.urlVariables.putAll(urlVariables) - if (customizer != null) { - customizer.delegate = requestCustomizer - customizer.resolveStrategy = Closure.DELEGATE_FIRST - customizer.call() - } - - try { - ResponseEntity responseEntity = invokeRestTemplate(url, method, requestCustomizer) - handleResponse(responseEntity) - } - catch (HttpStatusCodeException e) { - return new RestResponse(new ResponseEntity(e.getResponseBodyAsString(), e.responseHeaders, e.statusCode)) - } - } - - protected void registerMessageConverters(RestTemplate restTemplate) { - final messageConverters = restTemplate.getMessageConverters() - final stringConverter = messageConverters.find { HttpMessageConverter httpMessageConverter -> httpMessageConverter instanceof StringHttpMessageConverter } - if(stringConverter) { - messageConverters.remove(stringConverter) - } - if(ClassUtils.isPresent("com.google.gson.Gson", getClass().getClassLoader())) { - messageConverters.add(new GsonHttpMessageConverter()) - } - messageConverters.add(new NullSafeStringHttpMessageConverter()) - messageConverters.add(new JsonHttpMessageConverter()) - messageConverters.add(new GPathXmlHttpMessageConverter()) - messageConverters.add(new GrailsConverterHttpMessageConverter()) - messageConverters.add(new WritableHttpMessageConverter()) - } - - - protected ResponseEntity invokeRestTemplate(String url, HttpMethod method, RequestCustomizer requestCustomizer) { - def responseEntity = restTemplate.exchange(url, method, requestCustomizer.createEntity(), - requestCustomizer.acceptType, requestCustomizer.getUrlVariables()) - responseEntity - } - - protected RestResponse handleResponse(ResponseEntity responseEntity) { - return new RestResponse(responseEntity) - } -} 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 deleted file mode 100644 index d21b4cb36..000000000 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/RestResponse.groovy +++ /dev/null @@ -1,89 +0,0 @@ -/* Copyright (C) 2013 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 grails.plugins.rest.client - -import grails.converters.JSON -import grails.converters.XML -import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode -import groovy.util.slurpersupport.GPathResult -import groovy.xml.StreamingMarkupBuilder -import org.codehaus.groovy.grails.web.json.JSONElement -import org.springframework.http.ResponseEntity -import org.springframework.web.client.HttpStatusCodeException - -/** - * - * Wraps a {@link ResponseEntity} allowing easy access to the underlying JSON or XML response. All methods of {@link ResponseEntity} are available on this class - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class RestResponse { - - @Delegate ResponseEntity responseEntity - String encoding = "UTF-8" - - RestResponse(ResponseEntity responseEntity) { - this.responseEntity = responseEntity - } - - @Lazy JSONElement json = { - def body = responseEntity.body - if(body instanceof JSONElement) { - return (JSONElement)body - } - else if (body) { - return (JSONElement)JSON.parse(body.toString()) - } - }() - - @Lazy GPathResult xml = { - def body = responseEntity.body - if(body instanceof GPathResult) { - return (GPathResult)body - } - else if (body) { - return (GPathResult)XML.parse(body.toString()) - } - }() - - @Lazy String text = { - def body = responseEntity.body - if( body instanceof GPathResult ) { - return convertGPathResultToString(body) - } - else if (body) { - return body.toString() - } - else { - return responseEntity.statusCode.reasonPhrase - } - }() - - @CompileStatic(TypeCheckingMode.SKIP) - protected String convertGPathResultToString(body) { - return new StreamingMarkupBuilder().bind { - out << body - }.toString() - } - - int getStatus() { - responseEntity?.statusCode?.value() ?: 200 - } - - -} diff --git a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/AbstractAsyncResourcesClient.groovy b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/AbstractAsyncResourcesClient.groovy deleted file mode 100644 index 898d4d9cf..000000000 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/AbstractAsyncResourcesClient.groovy +++ /dev/null @@ -1,295 +0,0 @@ -/* Copyright (C) 2013 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 grails.plugins.rest.client.async - -import grails.async.Promise -import grails.plugins.rest.client.RequestCustomizer -import grails.plugins.rest.client.RestBuilder -import grails.plugins.rest.client.RestResponse -import groovy.transform.CompileStatic -import static grails.async.Promises.* - -/** - * Abstract base class for Asynchronous resource clients - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -abstract class AbstractAsyncResourcesClient { - - String url - AsyncRestBuilder restBuilder - - protected String templatedUrl - protected Closure customizer - - /** - * @param url The base URL. Example http://localhost:8080/books - */ - AbstractAsyncResourcesClient(String url) { - this.url = url - this.templatedUrl = "${url}/{id}" - this.restBuilder = new AsyncRestBuilder() - } - - - AbstractAsyncResourcesClient(String url, AsyncRestBuilder restBuilder) { - this(url) - this.restBuilder = restBuilder - } - - void customize(@DelegatesTo( RequestCustomizer ) Closure customizer) { - this.customizer = customizer - } - - /** - * Issues a GET request for the given id - * - * @param id The id - * @param acceptContentType The content type to pass in the ACCEPT header - * - * @return The result - */ - Promise get(Object id, String acceptContentType = getAcceptContentType()) { - task { - RestBuilder syncRestBuilder = restBuilder.restBuilder - final response = syncRestBuilder.get(templatedUrl, [id: id]) { - accept getAcceptType(), acceptContentType - if (customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - return (T)response.body - } - } - - /** - * Issues a DELETE request for the given id - * - * @param id The id - * @return The result - */ - Promise delete(Object id) { - restBuilder.delete(templatedUrl, [id: id]) { - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - - /** - * Issues a HEAD request for the given id - * - * @param id The id - * @return The result - */ - Promise head(Object id) { - restBuilder.head(templatedUrl, [id: id]) { - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a HEAD request for the given id - * - * @param id The id - * @return The result - */ - Promise head() { - restBuilder.head(url) { - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a OPTIONS request for the given id - * - * @param id The id - * @return The result - */ - Promise options(Object id) { - restBuilder.options(templatedUrl, [id: id]) { - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a OPTIONS request for the given id - * - * @param id The id - * @return The result - */ - Promise options() { - restBuilder.options(url) { - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a POST request for the given id - * - * @param requestBody The requestBody of the request - * @return The result - */ - Promise post(T requestBody, String bodyContentType = getAcceptContentType()) { - restBuilder.post(url) { - body requestBody - contentType bodyContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a PUT request for the given id - * - * @param requestBody The requestBody of the request - * @return The result - */ - Promise put(Object id, String requestBody, String bodyContentType = getAcceptContentType()) { - restBuilder.put(templatedUrl, [id:id]) { - body requestBody - contentType bodyContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - - /** - * Issues a PATCH request for the given id - * - * @param requestBody The requestBody of the request - * @return The result - */ - Promise patch(Object id, String requestBody, String bodyContentType = getAcceptContentType()) { - restBuilder.patch(templatedUrl, [id:id]) { - body requestBody - contentType bodyContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a POST request for the given id - * - * @param requestBody The requestBody of the request - * @return The result - */ - Promise post(String requestBody, String bodyContentType = getAcceptContentType()) { - restBuilder.post(url) { - body requestBody - contentType bodyContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a PUT request for the given id - * - * @param requestBody The requestBody of the request - * @return The result - */ - Promise put(Object id, T requestBody, String bodyContentType = getAcceptContentType()) { - restBuilder.put(templatedUrl, [id:id]) { - body requestBody - contentType bodyContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a PATCH request for the given id - * - * @param requestBody The requestBody of the request - * @return The result - */ - Promise patch(Object id, T requestBody, String bodyContentType = getAcceptContentType()) { - restBuilder.patch(templatedUrl, [id:id]) { - body requestBody - contentType bodyContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - - - /** - * Issues a GET request to the configured URL - * - * @param acceptContentType The content type to pass in the ACCEPT header - * - * @return The result - */ - Promise getAll(String acceptContentType = getAcceptContentType()) { - task { - final syncRestBuilder = restBuilder.restBuilder - final response = syncRestBuilder.get(url) { - accept getAcceptType(), acceptContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - - return (T)response.body - - } - } - - /** - * Subclasses should implement to provide the conversion to the target representation (JSON, XML etc.) - * @param restResponse The RestResponse - * @return The converted type - */ - Class getAcceptType() { String } - - /** - * @return Subclasses should implement to provide the default content type used to exchange resources - */ - abstract String getAcceptContentType() -} diff --git a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/AsyncRestBuilder.groovy b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/AsyncRestBuilder.groovy deleted file mode 100644 index c85ef52f4..000000000 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/AsyncRestBuilder.groovy +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2013 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 grails.plugins.rest.client.async - -import grails.async.DelegateAsync -import grails.plugins.rest.client.RestBuilder -import org.springframework.web.client.RestTemplate - -/** - * Asynchronous version of the {@link RestBuilder} class. Uses the {@DelegateAsync} annotation to provide the same API - * - * @author Graeme Rocher - * @since 1.0 - */ -class AsyncRestBuilder { - - @DelegateAsync RestBuilder restBuilder - - AsyncRestBuilder(Map settings) { - this.restBuilder = new RestBuilder(settings) - } - AsyncRestBuilder() { - this.restBuilder = new RestBuilder() - } - - AsyncRestBuilder(RestBuilder restBuilder) { - this.restBuilder = restBuilder - } - - RestTemplate getRestTemplate() { - return restBuilder.restTemplate - } -} 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 deleted file mode 100644 index 01ed517d3..000000000 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/templated/AsyncJsonResourcesClient.groovy +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (C) 2013 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 grails.plugins.rest.client.async.templated - -import grails.converters.JSON -import grails.plugins.rest.client.async.AbstractAsyncResourcesClient -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.springframework.http.MediaType - -/** - * Asynchronous version of the {@link JsonResourcesClient} class - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class AsyncJsonResourcesClient extends AbstractAsyncResourcesClient{ - - /** - * @param url The base URL. Example http://localhost:8080/books - */ - AsyncJsonResourcesClient(String url) { - super(url) - } - - AsyncJsonResourcesClient(String url, AsyncRestBuilder restBuilder) { - super(url, restBuilder) - } - - @Override - Class getAcceptType() { JSON } - - @Override - String getAcceptContentType() { MediaType.APPLICATION_JSON_VALUE } -} diff --git a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/templated/AsyncXmlResourcesClient.groovy b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/templated/AsyncXmlResourcesClient.groovy deleted file mode 100644 index c005eec33..000000000 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/async/templated/AsyncXmlResourcesClient.groovy +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 2013 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 grails.plugins.rest.client.async.templated - -import grails.converters.XML -import grails.plugins.rest.client.async.AbstractAsyncResourcesClient -import grails.plugins.rest.client.async.AsyncRestBuilder -import groovy.transform.CompileStatic -import groovy.util.slurpersupport.GPathResult -import org.springframework.http.MediaType - -/** - * Asynchronous version of the {@link grails.plugins.rest.client.templated.XmlResourcesClient} class - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class AsyncXmlResourcesClient extends AbstractAsyncResourcesClient { - /** - * @param url The base URL. Example http://localhost:8080/books - */ - AsyncXmlResourcesClient(String url) { - super(url) - } - - AsyncXmlResourcesClient(String url, AsyncRestBuilder restBuilder) { - super(url, restBuilder) - } - - @Override - Class getAcceptType() { XML } - - @Override - String getAcceptContentType() { MediaType.APPLICATION_XML_VALUE } -} diff --git a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/AbstractResourcesClient.groovy b/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/AbstractResourcesClient.groovy deleted file mode 100644 index 3eb637dd9..000000000 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/AbstractResourcesClient.groovy +++ /dev/null @@ -1,298 +0,0 @@ -/* Copyright (C) 2013 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 grails.plugins.rest.client.templated - -import grails.plugins.rest.client.RequestCustomizer -import grails.plugins.rest.client.RestBuilder -import grails.plugins.rest.client.RestResponse -import groovy.transform.CompileStatic - -/** - * Provides a simple client to resources exposed using Grails' REST support. Following the same conventions for URI scheme as Grails does - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -abstract class AbstractResourcesClient { - - String url - RestBuilder restBuilder - - protected String templatedUrl - protected Closure customizer - - /** - * @param url The base URL. Example http://localhost:8080/books - */ - AbstractResourcesClient(String url) { - this.url = url - this.templatedUrl = "${url}/{id}" - this.restBuilder = new RestBuilder() - } - - - AbstractResourcesClient(String url, RestBuilder restBuilder) { - this(url) - this.restBuilder = restBuilder - } - - void customize(@DelegatesTo( RequestCustomizer ) Closure customizer) { - this.customizer = customizer - } - - /** - * Issues a GET request to the configured URL - * - * @param acceptContentType The content type to pass in the ACCEPT header - * - * @return The result - */ - T get(String acceptContentType = getAcceptContentType()) { - final response = restBuilder.get(url) { - accept getAcceptType(), acceptContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - - return (T)response.body - } - - /** - * Issues a GET request for the given id - * - * @param id The id - * @param acceptContentType The content type to pass in the ACCEPT header - * - * @return The result - */ - T get(Object id, String acceptContentType = getAcceptContentType()) { - final response = restBuilder.get(templatedUrl, [id:id]) { - accept getAcceptType(), acceptContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - - return (T)response.body - } - - /** - * Issues a DELETE request for the given id - * - * @param id The id - * @return The result - */ - RestResponse delete(Object id) { - restBuilder.delete(templatedUrl, [id: id]) { - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a HEAD request for the given id - * - * @param id The id - * @return The result - */ - RestResponse head(Object id) { - restBuilder.head(templatedUrl, [id: id]) { - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a HEAD request for the given id - * - * @param id The id - * @return The result - */ - RestResponse head() { - restBuilder.head(url) { - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a OPTIONS request for the given id - * - * @param id The id - * @return The result - */ - RestResponse options(Object id) { - restBuilder.options(templatedUrl, [id: id]) { - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a OPTIONS request for the given id - * - * @param id The id - * @return The result - */ - RestResponse options() { - restBuilder.options(url) { - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - - /** - * Issues a POST request for the given id - * - * @param requestBody The requestBody of the request - * @return The result - */ - RestResponse post(Object requestBody, String bodyContentType = getAcceptContentType()) { - restBuilder.post(url) { - body convertBody(requestBody) - contentType bodyContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a PUT request for the given id - * - * @param requestBody The requestBody of the request - * @return The result - */ - RestResponse put(Object id, String requestBody, String bodyContentType = getAcceptContentType()) { - restBuilder.put(templatedUrl, [id:id]) { - body requestBody - contentType bodyContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a PATCH request for the given id - * - * @param requestBody The requestBody of the request - * @return The result - */ - RestResponse patch(Object id, String requestBody, String bodyContentType = getAcceptContentType()) { - restBuilder.patch(templatedUrl, [id:id]) { - body requestBody - contentType bodyContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a POST request for the given id - * - * @param requestBody The requestBody of the request - * @return The result - */ - RestResponse post(String requestBody, String bodyContentType = getAcceptContentType()) { - restBuilder.post(url) { - body requestBody - contentType bodyContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - /** - * Issues a PUT request for the given id - * - * @param requestBody The requestBody of the request - * @return The result - */ - RestResponse put(Object id, Object requestBody, String bodyContentType = getAcceptContentType()) { - restBuilder.put(templatedUrl, [id:id]) { - body convertBody(requestBody) - contentType bodyContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - - /** - * Issues a PATCH request for the given id - * - * @param requestBody The requestBody of the request - * @return The result - */ - RestResponse patch(Object id, Object requestBody, String bodyContentType = getAcceptContentType()) { - restBuilder.patch(templatedUrl, [id:id]) { - body convertBody(requestBody) - contentType bodyContentType - if(customizer) { - this.customizer.delegate = delegate - this.customizer.call() - } - } - } - - - - /** - * Subclasses should implement to provide the conversion to the target representation (JSON, XML etc.) - * @param restResponse The RestResponse - * @return The converted type - */ - Class getAcceptType() { String } - - /** - * @return Subclasses should implement to provide the default content type used to exchange resources - */ - abstract String getAcceptContentType() - - /** - * Subclasses can optionally override to provide conversion - * @param requestBody The request body - * @return The converted body - */ - protected Object convertBody(Object requestBody) { - requestBody - } - - -} 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 deleted file mode 100644 index 7164e697c..000000000 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/JsonResourcesClient.groovy +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (C) 2013 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 grails.plugins.rest.client.templated - -import grails.converters.JSON -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 - -/** - * A simple client for interacting with a REST web service exposed by a Grails application - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class JsonResourcesClient extends AbstractResourcesClient { - /** - * @param url The base URL. Example http://localhost:8080/books - */ - JsonResourcesClient(String url) { - super(url) - } - - - JsonResourcesClient(String url, RestBuilder restBuilder) { - super(url, restBuilder) - } - - @Override - protected Object convertBody(Object requestBody) { - if( (requestBody instanceof JSON) || (requestBody instanceof JSONElement) ) { - return requestBody - } - try { - return requestBody as JSON - } catch (GroovyCastException e) { - return ConverterUtil.createConverter(JSON, requestBody) - } - } - - @Override - Class getAcceptType() { JSON } - - @Override - String getAcceptContentType() { "application/json" } -} 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 deleted file mode 100644 index f6937bdf5..000000000 --- a/grails-datastore-rest-client/src/main/groovy/grails/plugins/rest/client/templated/XmlResourcesClient.groovy +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2013 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 grails.plugins.rest.client.templated - -import grails.converters.XML -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 - -/** - * - * A simple client for interacting with a REST web service exposed by a Grails application using XML as an interchange format - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class XmlResourcesClient extends AbstractResourcesClient{ - /** - * @param url The base URL. Example http://localhost:8080/books - */ - XmlResourcesClient(String url) { - super(url) - } - - XmlResourcesClient(String url, RestBuilder restBuilder) { - super(url, restBuilder) - } - - @Override - protected Object convertBody(Object requestBody) { - if( (requestBody instanceof XML) || (requestBody instanceof GPathResult) ) { - return requestBody - } - try { - return requestBody as XML - } catch (GroovyCastException e) { - return ConverterUtil.createConverter(XML, requestBody) - } - } - - @Override - Class getAcceptType() { XML } - - @Override - String getAcceptContentType() { "application/xml" } -} diff --git a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/json/GsonHttpMessageConverter.groovy b/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/json/GsonHttpMessageConverter.groovy deleted file mode 100644 index d59a06c96..000000000 --- a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/json/GsonHttpMessageConverter.groovy +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client.json - -import com.google.gson.JsonElement -import com.google.gson.JsonParser -import com.google.gson.internal.Streams -import com.google.gson.stream.JsonReader -import com.google.gson.stream.JsonWriter -import grails.converters.JSON -import groovy.transform.CompileStatic -import org.springframework.http.HttpInputMessage -import org.springframework.http.HttpOutputMessage -import org.springframework.http.MediaType -import org.springframework.http.converter.AbstractHttpMessageConverter -import org.springframework.http.converter.HttpMessageNotReadableException -import org.springframework.http.converter.HttpMessageNotWritableException - -import java.nio.charset.Charset - -/** - * A message converter for Google's GSON - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class GsonHttpMessageConverter extends AbstractHttpMessageConverter { - - GsonHttpMessageConverter() { - super(MediaType.APPLICATION_JSON) - } - - @Override - protected boolean supports(Class clazz) { - return JsonElement.isAssignableFrom(clazz) - } - - @Override - protected JsonElement readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - final contentType = inputMessage.headers.getContentType() - final charSet = getCharSetForMediaType(contentType) - - final inputStream = inputMessage.body - if(inputStream) { - return new JsonParser().parse(new JsonReader(new InputStreamReader(inputStream, charSet))) - } - return null - } - - @Override - protected void writeInternal(JsonElement t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { - final body = outputMessage.body - if(body) { - JsonWriter jsonWriter = new JsonWriter(new OutputStreamWriter(body, getCharSetForMediaType(outputMessage.headers.getContentType()))); - jsonWriter.setLenient(true); - Streams.write(t, jsonWriter); - } - } - - protected Charset getCharSetForMediaType(MediaType contentType) { - contentType ? (contentType.charSet ? contentType.charSet : Charset.forName("UTF-8")) : Charset.forName("UTF-8") - } - -} 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 deleted file mode 100644 index ac9d31932..000000000 --- a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/json/JsonHttpMessageConverter.groovy +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client.json - -import grails.converters.JSON -import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.web.json.JSONElement -import org.springframework.http.HttpInputMessage -import org.springframework.http.HttpOutputMessage -import org.springframework.http.MediaType -import org.springframework.http.converter.AbstractHttpMessageConverter -import org.springframework.http.converter.HttpMessageNotReadableException -import org.springframework.http.converter.HttpMessageNotWritableException -import org.springframework.util.StreamUtils - -import java.nio.charset.Charset - -/** - * A message converter that supports JSON - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class JsonHttpMessageConverter extends AbstractHttpMessageConverter{ - - JsonHttpMessageConverter() { - super(MediaType.APPLICATION_JSON) - } - - @Override - protected boolean supports(Class clazz) { - return JSON.isAssignableFrom(clazz) || JSONElement.isAssignableFrom(clazz) - } - - @Override - boolean canWrite(Class clazz, MediaType mediaType) { - return super.canWrite(clazz, mediaType) && !JSON.isAssignableFrom(clazz) - } - - @Override - protected JSONElement readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - final contentType = inputMessage.headers.getContentType() - final body = inputMessage.body - if(body) { - return JSON.parse(body, getCharSetForMediaType(contentType).toString()) - } - return null - } - - protected Charset getCharSetForMediaType(MediaType contentType) { - contentType ? (contentType.charSet ? contentType.charSet : Charset.forName("UTF-8")) : Charset.forName("UTF-8") - } - - @Override - protected void writeInternal(JSONElement t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { - StreamUtils.copy(toString(), getCharSetForMediaType(outputMessage.headers.getContentType()), outputMessage.body) - } -} 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 deleted file mode 100644 index ce52b1594..000000000 --- a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/utils/GrailsConverterHttpMessageConverter.groovy +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client.utils - -import groovy.transform.CompileStatic -import org.codehaus.groovy.grails.web.converters.Converter -import org.springframework.http.HttpInputMessage -import org.springframework.http.HttpOutputMessage -import org.springframework.http.MediaType -import org.springframework.http.converter.AbstractHttpMessageConverter -import org.springframework.http.converter.HttpMessageNotReadableException -import org.springframework.http.converter.HttpMessageNotWritableException - -import java.nio.charset.Charset - -/** - * A message converter that is capable of using Grails' converters API to write messages - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class GrailsConverterHttpMessageConverter extends AbstractHttpMessageConverter{ - - GrailsConverterHttpMessageConverter() { - super(MediaType.ALL) - } - - @Override - protected boolean supports(Class clazz) { - return Converter.isAssignableFrom(clazz) - } - - @Override - boolean canRead(Class clazz, MediaType mediaType) { - return false; - } - - @Override - protected Converter readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - throw new UnsupportedOperationException("Reading not supported by GrailsConverterHttpMessageConverter") - } - - @Override - protected void writeInternal(Converter t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { - t.render(new OutputStreamWriter(outputMessage.body, getCharSetForMediaType(outputMessage.headers.getContentType()))) - } - - protected Charset getCharSetForMediaType(MediaType contentType) { - contentType ? (contentType.charSet ? contentType.charSet : Charset.forName("UTF-8")) : Charset.forName("UTF-8") - } -} diff --git a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/utils/NullSafeStringHttpMessageConverter.groovy b/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/utils/NullSafeStringHttpMessageConverter.groovy deleted file mode 100644 index 06741f2c6..000000000 --- a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/utils/NullSafeStringHttpMessageConverter.groovy +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client.utils - -import groovy.transform.CompileStatic -import org.springframework.http.HttpInputMessage -import org.springframework.http.MediaType -import org.springframework.http.converter.StringHttpMessageConverter -import org.springframework.util.StreamUtils - -import java.nio.charset.Charset - -/** - * String converter that takes into account a null body - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class NullSafeStringHttpMessageConverter extends StringHttpMessageConverter { - - @Override - protected String readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException { - Charset charset = getCharSetForMediaType(inputMessage.getHeaders().getContentType()); - final body = inputMessage.getBody() - if(body) { - return StreamUtils.copyToString(body, charset); - } - return null - } - - protected Charset getCharSetForMediaType(MediaType contentType) { - contentType ? (contentType.charSet ? contentType.charSet : Charset.forName("UTF-8")) : Charset.forName("UTF-8") - } - -} diff --git a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/utils/WritableHttpMessageConverter.groovy b/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/utils/WritableHttpMessageConverter.groovy deleted file mode 100644 index bf8836c8c..000000000 --- a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/utils/WritableHttpMessageConverter.groovy +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client.utils - -import groovy.transform.CompileStatic -import org.springframework.http.HttpInputMessage -import org.springframework.http.HttpOutputMessage -import org.springframework.http.MediaType -import org.springframework.http.converter.AbstractHttpMessageConverter -import org.springframework.http.converter.HttpMessageNotReadableException -import org.springframework.http.converter.HttpMessageNotWritableException - -import java.nio.charset.Charset - -/** - * A message converter capable of using a Groovy Writable to write to the HttpOutputMessage - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class WritableHttpMessageConverter extends AbstractHttpMessageConverter { - - WritableHttpMessageConverter() { - super(MediaType.ALL) - } - - @Override - protected boolean supports(Class clazz) { - return Writable.isAssignableFrom(clazz) - } - - @Override - boolean canRead(Class clazz, MediaType mediaType) { - false - } - - @Override - protected Writable readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - throw new UnsupportedOperationException("Reading not supported by WritableHttpMessageConverter") - } - - @Override - protected void writeInternal(Writable t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { - t.writeTo(new OutputStreamWriter(outputMessage.body, getCharSetForMediaType(outputMessage.headers.getContentType()))) - } - - protected Charset getCharSetForMediaType(MediaType contentType) { - contentType ? (contentType.charSet ? contentType.charSet : Charset.forName("UTF-8")) : Charset.forName("UTF-8") - } - -} diff --git a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/xml/GPathXmlHttpMessageConverter.groovy b/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/xml/GPathXmlHttpMessageConverter.groovy deleted file mode 100644 index a4ead74e3..000000000 --- a/grails-datastore-rest-client/src/main/groovy/org/grails/datastore/gorm/rest/client/xml/GPathXmlHttpMessageConverter.groovy +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (C) 2013 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.grails.datastore.gorm.rest.client.xml - -import grails.converters.XML -import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode -import groovy.util.slurpersupport.GPathResult -import groovy.xml.StreamingMarkupBuilder -import org.springframework.http.HttpInputMessage -import org.springframework.http.HttpOutputMessage -import org.springframework.http.MediaType -import org.springframework.http.converter.AbstractHttpMessageConverter -import org.springframework.http.converter.HttpMessageNotReadableException -import org.springframework.http.converter.HttpMessageNotWritableException - -import java.nio.charset.Charset - -/** - * A {@link org.springframework.http.converter.HttpMessageConverter} for converting responses to a GPathResult - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -class GPathXmlHttpMessageConverter extends AbstractHttpMessageConverter{ - @Override - protected boolean supports(Class clazz) { - return XML - } - - @Override - protected GPathResult readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - final body = inputMessage.body - if(body) { - return (GPathResult)XML.parse(body, getCharSetForMediaType(inputMessage.headers.getContentType()).toString()) - } - else { - return null - } - } - - @Override - protected void writeInternal(GPathResult t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { - Writable w = getWritablePathResult(t) - w.writeTo(new OutputStreamWriter(outputMessage.body, getCharSetForMediaType(outputMessage.headers.getContentType()))) - } - - @CompileStatic(TypeCheckingMode.SKIP) - protected Writable getWritablePathResult(GPathResult t) { - (Writable) new StreamingMarkupBuilder().bind { - out << t - } - } - - protected Charset getCharSetForMediaType(MediaType contentType) { - contentType ? (contentType.charSet ? contentType.charSet : Charset.forName("UTF-8")) : Charset.forName("UTF-8") - } -} 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 deleted file mode 100644 index e0864866f..000000000 --- a/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/AsyncRestBuilderSpec.groovy +++ /dev/null @@ -1,249 +0,0 @@ -package grails.plugins.rest.client - -import grails.async.Promise -import grails.converters.JSON -import grails.plugins.rest.client.async.AsyncRestBuilder -import grails.web.JSONBuilder -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 spock.lang.Issue -import spock.lang.Specification - -import static org.hamcrest.CoreMatchers.anything -import static org.springframework.test.web.client.match.MockRestRequestMatchers.* -import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess -import org.springframework.test.web.client.MockRestServiceServer -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 -import org.springframework.http.HttpStatus - -/** - * @author Graeme Rocher - */ -class AsyncRestBuilderSpec extends Specification{ - def "Test that a basic GET request returns a JSON result of the response type is JSON"(){ - given:"A rest client instance" - def rest = new AsyncRestBuilder() - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://grails.org/api/v1.0/plugin/acegi/")) - .andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess('{"name":"acegi"}', MediaType.APPLICATION_JSON)) - - - when:"A get request is issued for a response that returns XML" - Promise resp = rest.get("http://grails.org/api/v1.0/plugin/acegi/") - - then:"The response is a gpath result" - resp != null - resp.get().json instanceof JSONObject - resp.get().json.name == 'acegi' - } - - def "Test that obtaining a 404 response doesn't throw an exception but instead returns the response object for inspection"() { - given:"A rest client instance" - def rest = new AsyncRestBuilder() - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://grails.org/api/v1.0/plugin/nonsense")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, "application/xml")) - .andRespond(withStatus(HttpStatus.NOT_FOUND)) - - when:"A get request is issued to a URL that returns a 404" - Promise resp = rest.get("http://grails.org/api/v1.0/plugin/nonsense") { - accept "application/xml" - } - - then:"Check the status" - resp.get().status == 404 - resp.get().text instanceof String - } - - def "Test that a basic GET request returns a JSON result of the response type is JSON with custom settings"(){ - given:"A rest client instance" - def rest = new AsyncRestBuilder(connectTimeout:1000, readTimeout:20000) - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://grails.org/api/v1.0/plugin/acegi/")) - .andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess('{"name":"acegi"}', MediaType.APPLICATION_JSON)) - - - when:"A get request is issued for a response that returns XML" - Promise resp = rest.get("http://grails.org/api/v1.0/plugin/acegi/") - - then:"The response is a gpath result" - resp != null - resp.get().json instanceof JSONObject - resp.get().json.name == 'acegi' - } - - def "Test that a basic GET request returns a XML result of the response type is XML"(){ - given:"A rest client instance" - def rest = new AsyncRestBuilder() - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://grails.org/api/v1.0/plugin/acegi/")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, "application/xml")) - .andRespond(withSuccess('acegi', MediaType.APPLICATION_XML)) - - - when:"A get request is issued for a response that returns XML" - Promise resp = rest.get("http://grails.org/api/v1.0/plugin/acegi/") { - accept 'application/xml' - } - - then:"The response is a gpath result" - resp != null - resp.get().xml instanceof GPathResult - resp.get().xml.name == 'acegi' - } - - def "Test basic authentication with GET request"() { - given:"A rest client instance" - def rest = new AsyncRestBuilder() - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://repo.grails.org/grails/api/security/users")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.AUTHORIZATION, anything())) - .andRespond(withSuccess('["foo", "bar"]', MediaType.APPLICATION_JSON)) - - - when:"A get request is issued for a response that returns XML" - Promise resp = rest.get("http://repo.grails.org/grails/api/security/users"){ - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The response is a gpath result" - resp != null - resp.get().json instanceof JSONArray - } - - def "Test basic authentication with PUT request"() { - given:"A rest client instance" - def rest = new AsyncRestBuilder() - RestBuilderSpec.mockArtifactoryUserGroupApi(rest.restBuilder) - - when:"A get request is issued for a response that returns XML" - Promise resp = rest.put("http://repo.grails.org/grails/api/security/groups/test-group"){ - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - contentType "application/vnd.org.jfrog.artifactory.security.Group+json" - json { - name = "test-group" - description = "A temporary test group" - } - } - then:"The response is a gpath result" - resp != null - resp.get().status == 201 - resp.get().text == "Created" - - when:"The resource contents are requested" - resp = rest.get("http://repo.grails.org/grails/api/security/groups/test-group") { - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The contents are valid" - resp != null - resp.get().json.name == 'test-group' - - when:"The resource is deleted" - resp = rest.delete("http://repo.grails.org/grails/api/security/groups/test-group") { - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The resource is gone" - resp != null - resp.get().status == 200 - } - - def "Test basic authentication with PUT request and JSON body"() { - given:"A rest client instance" - def rest = new AsyncRestBuilder() - RestBuilderSpec.mockArtifactoryUserGroupApi(rest.restBuilder) - - when:"A get request is issued for a response that returns XML" - def builder = new JSONBuilder() - JSON j = builder.build { - name = "test-group" - description = "A temporary test group" - } - Promise resp = rest.put("http://repo.grails.org/grails/api/security/groups/test-group"){ - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - contentType "application/vnd.org.jfrog.artifactory.security.Group+json" - body j - } - then:"The response is a gpath result" - resp != null - resp.get().status == 201 - resp.get().text == "Created" - - when:"The resource contents are requested" - resp = rest.get("http://repo.grails.org/grails/api/security/groups/test-group") { - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The contents are valid" - resp != null - resp.get().json.name == 'test-group' - - when:"The resource is deleted" - resp = rest.delete("http://repo.grails.org/grails/api/security/groups/test-group") { - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The resource is gone" - resp != null - resp.get().status == 200 - } - - def "Test basic authentication with PUT request and JSON as map"() { - given:"A rest client instance" - def rest = new AsyncRestBuilder() - RestBuilderSpec.mockArtifactoryUserGroupApi(rest.restBuilder) - - when:"A get request is issued for a response that returns XML" - def builder = new JSONBuilder() - def j = [ - name : "test-group", - description : "A temporary test group" - ] - Promise resp = rest.put("http://repo.grails.org/grails/api/security/groups/test-group"){ - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - contentType "application/vnd.org.jfrog.artifactory.security.Group+json" - json j - } - then:"The response is a gpath result" - resp != null - resp.get().status == 201 - resp.get().text == "Created" - - when:"The resource contents are requested" - resp = rest.get("http://repo.grails.org/grails/api/security/groups/test-group") { - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The contents are valid" - resp != null - resp.get().json.name == 'test-group' - - when:"The resource is deleted" - resp = rest.delete("http://repo.grails.org/grails/api/security/groups/test-group") { - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The resource is gone" - resp != null - resp.get().status == 200 - } - - -} 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 deleted file mode 100644 index 7651cd487..000000000 --- a/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/RestBuilderSpec.groovy +++ /dev/null @@ -1,330 +0,0 @@ -package grails.plugins.rest.client - -import grails.converters.JSON -import grails.web.JSONBuilder -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.springframework.http.HttpMethod -import org.springframework.http.HttpStatus -import org.springframework.http.MediaType -import org.springframework.test.web.client.MockRestServiceServer -import spock.lang.Issue -import spock.lang.Specification - -import static org.hamcrest.CoreMatchers.anything -import static org.springframework.test.web.client.match.MockRestRequestMatchers.* -import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess - -class RestBuilderSpec extends Specification { - - - def "Test proxy configuration"() { - when:"RestBuilder is configured with proxy settings" - def rest = new RestBuilder(proxy:['localhost':8888]) - def proxyAddress = rest.restTemplate.requestFactory?.@proxy?.address() - - then:"The proxy settings are correct" - proxyAddress != null - proxyAddress.hostName == "localhost" - proxyAddress.port == 8888 - } - - def "Test that a basic GET request returns a JSON result of the response type is JSON"(){ - given:"A rest client instance" - def rest = new RestBuilder() - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://grails.org/api/v1.0/plugin/acegi/")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, "application/json")) - .andRespond(withSuccess('{"name":"acegi"}', MediaType.APPLICATION_JSON)) - - - when:"A get request is issued for a response that returns XML" - def resp = rest.get("http://grails.org/api/v1.0/plugin/acegi/") { - accept "application/json" - } - - then:"The response is a gpath result" - mockServer.verify() - resp != null - resp.json instanceof JSONObject - resp.json.name == 'acegi' - } - - def "Test that a basic GET request returns a JSON result of the response type is JSON and accept JSON is passed"(){ - given:"A rest client instance" - def rest = new RestBuilder() - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://grails.org/api/v1.0/plugin/acegi/")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, "application/json")) - .andRespond(withSuccess('{"name":"acegi"}', MediaType.APPLICATION_JSON)) - - - when:"A get request is issued for a response that returns XML" - def resp = rest.get("http://grails.org/api/v1.0/plugin/acegi/") { - accept JSON - } - - then:"The response is a gpath result" - mockServer.verify() - resp != null - resp.json instanceof JSONObject - resp.json.name == 'acegi' - } - - def "Test that obtaining a 404 response doesn't throw an exception but instead returns the response object for inspection"() { - given:"A rest client instance" - def rest = new RestBuilder() - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://grails.org/api/v1.0/plugin/nonsense")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, "application/xml")) - .andRespond(withStatus(HttpStatus.NOT_FOUND)) - - when:"A get request is issued to a URL that returns a 404" - def resp = rest.get("http://grails.org/api/v1.0/plugin/nonsense") { - accept "application/xml" - } - - then:"Check the status" - mockServer.verify() - resp.status == 404 - resp.text instanceof String - } - - def "Test that a basic GET request returns a JSON result of the response type is JSON with custom settings"(){ - given:"A rest client instance" - def rest = new RestBuilder(connectTimeout:1000, readTimeout:20000) - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://grails.org/api/v1.0/plugin/acegi/")) - .andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess('{"name":"acegi"}', MediaType.APPLICATION_JSON)) - - - when:"A get request is issued for a response that returns XML" - def resp = rest.get("http://grails.org/api/v1.0/plugin/acegi/") - - then:"The response is a gpath result" - mockServer.verify() - resp != null - resp.json instanceof JSONObject - resp.json.name == 'acegi' - } - - def "Test that a basic GET request returns a XML result of the response type is XML"(){ - given:"A rest client instance" - def rest = new RestBuilder() - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://grails.org/api/v1.0/plugin/acegi/")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, "application/xml")) - .andRespond(withSuccess('acegi', MediaType.APPLICATION_XML)) - - - when:"A get request is issued for a response that returns XML" - def resp = rest.get("http://grails.org/api/v1.0/plugin/acegi/") { - accept 'application/xml' - } - - then:"The response is a gpath result" - mockServer.verify() - resp != null - resp.xml instanceof GPathResult - resp.xml.name == 'acegi' - } - - def "Test basic authentication with GET request"() { - given:"A rest client instance" - def rest = new RestBuilder() - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://repo.grails.org/grails/api/security/users")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.AUTHORIZATION, anything())) - .andRespond(withSuccess('["foo", "bar"]', MediaType.APPLICATION_JSON)) - - - when:"A get request is issued for a response that returns XML" - def resp = rest.get("http://repo.grails.org/grails/api/security/users"){ - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The response is a gpath result" - resp != null - resp.json instanceof JSONArray - mockServer.verify() - } - - def "Test basic authentication with PUT request"() { - given:"A rest client instance" - def rest = new RestBuilder() - MockRestServiceServer mockServer = mockArtifactoryUserGroupApi(rest) - - - - when:"A get request is issued for a response that returns XML" - def resp = rest.put("http://repo.grails.org/grails/api/security/groups/test-group"){ - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - contentType "application/vnd.org.jfrog.artifactory.security.Group+json" - json { - name = "test-group" - description = "A temporary test group" - } - } - then:"The response is a gpath result" - resp != null - resp.status == 201 - - when:"The resource contents are requested" - resp = rest.get("http://repo.grails.org/grails/api/security/groups/test-group") { - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The contents are valid" - resp != null - resp.json.name == 'test-group' - - when:"The resource is deleted" - resp = rest.delete("http://repo.grails.org/grails/api/security/groups/test-group") { - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The resource is gone" - resp != null - resp.status == 200 - mockServer.verify() - } - - public static MockRestServiceServer mockArtifactoryUserGroupApi(RestBuilder rest) { - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://repo.grails.org/grails/api/security/groups/test-group")) - .andExpect(method(HttpMethod.PUT)) - .andExpect(content().contentType("application/vnd.org.jfrog.artifactory.security.Group+json")) - .andExpect(content().string('{"name":"test-group","description":"A temporary test group"}')) - .andExpect(header(HttpHeaders.AUTHORIZATION, anything())) - .andRespond(withStatus(HttpStatus.CREATED)) - - mockServer.expect(requestTo("http://repo.grails.org/grails/api/security/groups/test-group")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.AUTHORIZATION, anything())) - .andRespond(withSuccess('{"name":"test-group","description":"A temporary test group"}', MediaType.valueOf("application/vnd.org.jfrog.artifactory.security.Group+json"))) - - mockServer.expect(requestTo("http://repo.grails.org/grails/api/security/groups/test-group")) - .andExpect(method(HttpMethod.DELETE)) - .andExpect(header(HttpHeaders.AUTHORIZATION, anything())) - .andRespond(withSuccess()) - mockServer - } - - def "Test basic authentication with PUT request and JSON body"() { - given:"A rest client instance" - def rest = new RestBuilder() - MockRestServiceServer mockServer = mockArtifactoryUserGroupApi(rest) - - when:"A get request is issued for a response that returns XML" - def builder = new JSONBuilder() - JSON j = builder.build { - name = "test-group" - description = "A temporary test group" - } - def resp = rest.put("http://repo.grails.org/grails/api/security/groups/test-group"){ - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - contentType "application/vnd.org.jfrog.artifactory.security.Group+json" - body j - } - then:"The response is a gpath result" - resp != null - resp.status == 201 - resp.text == "Created" - - when:"The resource contents are requested" - resp = rest.get("http://repo.grails.org/grails/api/security/groups/test-group") { - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The contents are valid" - resp != null - resp.json.name == 'test-group' - - when:"The resource is deleted" - resp = rest.delete("http://repo.grails.org/grails/api/security/groups/test-group") { - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The resource is gone" - resp != null - resp.status == 200 - mockServer.verify() - } - - def "Test basic authentication with PUT request and JSON as map"() { - given:"A rest client instance" - def rest = new RestBuilder() - MockRestServiceServer mockServer = mockArtifactoryUserGroupApi(rest) - - when:"A get request is issued for a response that returns XML" - def builder = new JSONBuilder() - def j = [ - name : "test-group", - description : "A temporary test group" - ] - def resp = rest.put("http://repo.grails.org/grails/api/security/groups/test-group"){ - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - contentType "application/vnd.org.jfrog.artifactory.security.Group+json" - json j - } - then:"The response is a gpath result" - resp != null - resp.status == 201 - resp.text == "Created" - - when:"The resource contents are requested" - resp = rest.get("http://repo.grails.org/grails/api/security/groups/test-group") { - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The contents are valid" - resp != null - resp.json.name == 'test-group' - - when:"The resource is deleted" - resp = rest.delete("http://repo.grails.org/grails/api/security/groups/test-group") { - auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass") - } - - then:"The resource is gone" - resp != null - resp.status == 200 - mockServer.verify() - } - - - - // Note that this test uses JSON query parameters, but they are not actually validated due to the call - // not using them. If a call that processes JSON URL parameters if used, this test would mean much more. - @Issue("https://github.com/grails-plugins/grails-rest-client-builder/issues/3") - def "Test URL variables"() { - given:"A rest client instance" - def rest = new RestBuilder() - final mockServer = MockRestServiceServer.createServer(rest.restTemplate) - mockServer.expect(requestTo("http://grails.org/api/v1.0/plugin/acegi")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, "application/json")) - .andRespond(withSuccess('{"name":"acegi"}', MediaType.APPLICATION_JSON)) - - - when:"A get request is issued for a response that returns XML" - def resp = rest.get("http://grails.org/api/v1.0/plugin/{name}", [name: 'acegi']) { - accept "application/json" - } - - then:"The response is a gpath result" - mockServer.verify() - resp != null - resp.json instanceof JSONObject - resp.json.name == 'acegi' - } -} 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 deleted file mode 100644 index 622008a8e..000000000 --- a/grails-datastore-rest-client/src/test/groovy/grails/plugins/rest/client/templated/JsonResourcesClientSpec.groovy +++ /dev/null @@ -1,112 +0,0 @@ -package grails.plugins.rest.client.templated - -import grails.plugins.rest.client.RestBuilder -import org.codehaus.groovy.grails.web.json.JSONObject -import org.springframework.http.HttpMethod -import org.springframework.http.HttpStatus -import org.springframework.http.MediaType -import org.springframework.test.web.client.MockRestServiceServer -import spock.lang.Specification - -import static org.springframework.test.web.client.match.MockRestRequestMatchers.content -import static org.springframework.test.web.client.match.MockRestRequestMatchers.method -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo -import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess - -/** - * @author Graeme Rocher - */ -class JsonResourcesClientSpec extends Specification { - - void "Test that the get method submits a GET request to the correct URL"() { - setup: - RestBuilder restBuilder = new RestBuilder() - final mockServer = MockRestServiceServer.createServer(restBuilder.restTemplate) - mockServer.expect(requestTo("http://localhost:8080/books/1")).andExpect(method(HttpMethod.GET)).andRespond(withSuccess('{"title":"The Stand"}', MediaType.APPLICATION_JSON)) - - - when:"A new JsonResourceClient is constructed and the get method invoked" - def jsonResourceClient = new JsonResourcesClient("http://localhost:8080/books", restBuilder) - final result = jsonResourceClient.get(1) - - then:"The result is correct" - result != null - result instanceof JSONObject - result.title == "The Stand" - - } - - - void "Test that the delete method submits a DELETE request to the correct URL"() { - setup: - RestBuilder restBuilder = new RestBuilder() - final mockServer = MockRestServiceServer.createServer(restBuilder.restTemplate) - mockServer.expect(requestTo("http://localhost:8080/books/1")).andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.OK)) - - when:"A new JsonResourceClient is constructed and the get method invoked" - def jsonResourceClient = new JsonResourcesClient("http://localhost:8080/books", restBuilder) - final result = jsonResourceClient.delete(1) - - then:"The result is correct" - result != null - result.statusCode == HttpStatus.OK - - } - - void "Test that the head method with an id submits a HEAD request to the correct URL"() { - setup: - RestBuilder restBuilder = new RestBuilder() - final mockServer = MockRestServiceServer.createServer(restBuilder.restTemplate) - mockServer.expect(requestTo("http://localhost:8080/books/1")).andExpect(method(HttpMethod.HEAD)).andRespond(withStatus(HttpStatus.OK)) - - - when:"A new JsonResourceClient is constructed and the get method invoked" - def jsonResourceClient = new JsonResourcesClient("http://localhost:8080/books", restBuilder) - final result = jsonResourceClient.head(1) - - then:"The result is correct" - result != null - result.statusCode == HttpStatus.OK - - } - - void "Test that the head method submits a HEAD request to the correct URL"() { - setup: - RestBuilder restBuilder = new RestBuilder() - final mockServer = MockRestServiceServer.createServer(restBuilder.restTemplate) - mockServer.expect(requestTo("http://localhost:8080/books")).andExpect(method(HttpMethod.HEAD)).andRespond(withStatus(HttpStatus.OK)) - - when:"A new JsonResourceClient is constructed and the get method invoked" - def jsonResourceClient = new JsonResourcesClient("http://localhost:8080/books", restBuilder) - final result = jsonResourceClient.head() - - then:"The result is correct" - result != null - result.statusCode == HttpStatus.OK - - } - - void "Test that the post method correctly sends JSON to the appropriate URL"() { - setup: - RestBuilder restBuilder = new RestBuilder() - final mockServer = MockRestServiceServer.createServer(restBuilder.restTemplate) - mockServer.expect(requestTo("http://localhost:8080/books")) - .andExpect(method(HttpMethod.POST)) - .andExpect(content().string('{"title":"The Stand"}')) - .andExpect(content().contentType("application/json")) - .andRespond(withStatus(HttpStatus.CREATED)) - - when:"A new JsonResourceClient is constructed and the get method invoked" - def jsonResourceClient = new JsonResourcesClient("http://localhost:8080/books", restBuilder) - final result = jsonResourceClient.post(new Book(title:"The Stand")) - - then:"The result is correct" - result != null - result.statusCode == HttpStatus.CREATED - - } -} -class Book { - String title -} diff --git a/grails-datastore-riak/build.gradle b/grails-datastore-riak/build.gradle deleted file mode 100644 index 7b4bda7f9..000000000 --- a/grails-datastore-riak/build.gradle +++ /dev/null @@ -1,8 +0,0 @@ -version = "1.0.0.BUILD-SNAPSHOT" - -dependencies { - compile project(":grails-datastore-core"), - 'org.codehaus.jackson:jackson-core-asl:1.6.1', - 'org.codehaus.jackson:jackson-mapper-asl:1.6.1', - 'org.springframework.data:spring-data-riak:1.0.0.M3' -} diff --git a/grails-datastore-riak/src/main/groovy/log4j.xml b/grails-datastore-riak/src/main/groovy/log4j.xml deleted file mode 100644 index 32afd1380..000000000 --- a/grails-datastore-riak/src/main/groovy/log4j.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/RiakDatastore.java b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/RiakDatastore.java deleted file mode 100644 index 2bd15e46a..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/RiakDatastore.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak; - -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.data.keyvalue.riak.core.RiakTemplate; -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.riak.util.Ignore404sErrorHandler; - -/** - * A {@link org.grails.datastore.mapping.core.Datastore} implemenation for the Riak - * Key/Value store. - * - * @author J. Brisbin - */ -public class RiakDatastore extends AbstractDatastore implements InitializingBean, DisposableBean { - - public static final String CONFIG_DEFAULT_URI = "defaultUri"; - public static final String CONFIG_MAPRED_URI = "mapReduceUri"; - public static final String CONFIG_USE_CACHE = "useCache"; - - public static final String DEFAULT_URI = "http://localhost:8098/riak/{bucket}/{key}"; - public static final String DEFAULT_MAPRED_URI = "http://localhost:8098/mapred"; - public static final boolean DEFAULT_USE_CACHE = true; - - private final Logger log = LoggerFactory.getLogger(getClass()); - - /** - * The full URI to use on the {@link org.springframework.data.keyvalue.riak.core.RiakTemplate}. - */ - private String defaultUri = DEFAULT_URI; - /** - * The Map/Reduce URI to use on the {@link org.springframework.data.keyvalue.riak.core.RiakTemplate}. - */ - private String mapReduceUri = DEFAULT_MAPRED_URI; - /** - * Whether or not to use the internal, ETag-based object cache. - */ - private boolean useCache = DEFAULT_USE_CACHE; - - public RiakDatastore() { - this(new KeyValueMappingContext("")); - } - - public RiakDatastore(MappingContext mappingContext) { - this(mappingContext, null, null); - } - - public RiakDatastore(MappingContext mappingContext, Map connectionDetails, - ConfigurableApplicationContext ctx) { - super(mappingContext, connectionDetails, ctx); - initializeConverters(mappingContext); - if (connectionDetails != null) { - defaultUri = connectionDetails.containsKey(CONFIG_DEFAULT_URI) ? connectionDetails.get( - CONFIG_DEFAULT_URI) : DEFAULT_URI; - mapReduceUri = connectionDetails.containsKey(CONFIG_MAPRED_URI) ? connectionDetails.get( - CONFIG_MAPRED_URI) : DEFAULT_MAPRED_URI; - useCache = connectionDetails.containsKey(CONFIG_USE_CACHE) ? Boolean.parseBoolean( - connectionDetails.get( - CONFIG_USE_CACHE).toString()) : DEFAULT_USE_CACHE; - } - } - - @Override - protected Session createSession(Map connDetails) { - @SuppressWarnings("hiding") String defaultUri = this.defaultUri; - if (connDetails != null) { - defaultUri = connDetails.containsKey(CONFIG_DEFAULT_URI) ? connDetails.get( - CONFIG_DEFAULT_URI) : DEFAULT_URI; - mapReduceUri = connDetails.containsKey(CONFIG_MAPRED_URI) ? connDetails.get( - CONFIG_MAPRED_URI) : DEFAULT_MAPRED_URI; - useCache = connDetails.containsKey(CONFIG_USE_CACHE) ? Boolean.parseBoolean( - connDetails.get( - CONFIG_USE_CACHE).toString()) : DEFAULT_USE_CACHE; - } - RiakTemplate riak = new RiakTemplate(defaultUri, mapReduceUri); - riak.setUseCache(useCache); - riak.getRestTemplate().setErrorHandler(new Ignore404sErrorHandler()); - try { - riak.afterPropertiesSet(); - } catch (Exception e) { - log.error(e.getMessage(), e); - } - return new RiakSession(this, mappingContext, riak, getApplicationEventPublisher()); - } - - public void destroy() throws Exception { - } - - public void afterPropertiesSet() throws Exception { - } -} diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/RiakEntry.java b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/RiakEntry.java deleted file mode 100644 index 1dd2666d4..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/RiakEntry.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak; - -import java.util.LinkedHashMap; - -/** - * @author J. Brisbin - */ -@SuppressWarnings("rawtypes") -public class RiakEntry extends LinkedHashMap { - - private static final long serialVersionUID = 1; - - private String family; - - public RiakEntry(String family) { - this.family = family; - } - - public String getFamily() { - return family; - } -} diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/RiakSession.java b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/RiakSession.java deleted file mode 100644 index 50eb20562..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/RiakSession.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak; - -import java.math.BigInteger; - -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.core.convert.converter.Converter; -import org.springframework.data.keyvalue.riak.core.QosParameters; -import org.springframework.data.keyvalue.riak.core.RiakTemplate; -import org.grails.datastore.mapping.core.AbstractSession; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.riak.engine.RiakEntityPersister; -import org.grails.datastore.mapping.transactions.Transaction; - -/** - * A {@link org.grails.datastore.mapping.core.Session} implementation for the Riak - * Key/Value store. - * - * @author J. Brisbin - */ -@SuppressWarnings({"unchecked", "rawtypes"}) -public class RiakSession extends AbstractSession { - - private RiakTemplate riakTemplate; - private QosParameters qosParameters; - - public RiakSession(Datastore datastore, MappingContext mappingContext, - RiakTemplate riakTemplate, ApplicationEventPublisher publisher) { - super(datastore, mappingContext, publisher); - this.riakTemplate = riakTemplate; - mappingContext.addTypeConverter(new BigIntegerToLongConverter()); - } - - @Override - protected Persister createPersister(Class cls, MappingContext mappingContext) { - PersistentEntity entity = mappingContext.getPersistentEntity(cls.getName()); - if (null == entity) { - return null; - } - return new RiakEntityPersister(mappingContext, entity, this, riakTemplate, publisher); - } - - @Override - protected Transaction beginTransactionInternal() { - return new RiakTransaction(riakTemplate); - } - - public Object getNativeInterface() { - return riakTemplate; - } - - public QosParameters getQosParameters() { - return qosParameters; - } - - /** - * Set the Riak Quality Of Service parameters to use during this session. - * - * @param qosParameters - */ - public void setQosParameters(QosParameters qosParameters) { - this.qosParameters = qosParameters; - } - - protected class BigIntegerToLongConverter implements Converter { - public Long convert(BigInteger integer) { - return Long.valueOf(integer.longValue()); - } - } -} diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/RiakTransaction.java b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/RiakTransaction.java deleted file mode 100644 index 2d923b226..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/RiakTransaction.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak; - -import org.springframework.data.keyvalue.riak.core.RiakTemplate; -import org.grails.datastore.mapping.transactions.Transaction; -import org.springframework.transaction.IllegalTransactionStateException; - -/** - * A {@link org.grails.datastore.mapping.transactions.Transaction} - * implemenatation for Riak. - *

    - * Note that this implementation doesn't do any real transaction processing - * because Riak doesn't have native transaction support. - * - * @author J. Brisbin - */ -public class RiakTransaction implements Transaction { - - private RiakTemplate riakTemplate; - private boolean committed = false; - private boolean rolledBack = false; - - public RiakTransaction(RiakTemplate riakTemplate) { - this.riakTemplate = riakTemplate; - } - - public void commit() { - if (rolledBack) { - throw new IllegalTransactionStateException("This transaction has already been rolled back!"); - } - committed = true; - } - - public void rollback() { - if (committed) { - throw new IllegalTransactionStateException("This transaction has already been committed!"); - } - rolledBack = true; - } - - public RiakTemplate getNativeTransaction() { - return riakTemplate; - } - - public boolean isActive() { - return !committed && !rolledBack; - } - - public void setTimeout(int timeout) { - throw new UnsupportedOperationException("Transaction timeouts do not apply to the Riak support."); - } -} diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/collection/AbstractRiakCollection.java b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/collection/AbstractRiakCollection.java deleted file mode 100644 index 1a21ef20a..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/collection/AbstractRiakCollection.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak.collection; - -import java.util.Collection; -import java.util.List; - -import org.springframework.data.keyvalue.riak.core.RiakTemplate; - -/** - * @author J. Brisbin - */ -@SuppressWarnings("rawtypes") -public abstract class AbstractRiakCollection implements Collection, RiakCollection { - - protected RiakTemplate riakTemplate; - protected String bucket; - - public AbstractRiakCollection(RiakTemplate riakTemplate, String bucket) { - this.riakTemplate = riakTemplate; - this.bucket = bucket; - } - - public String getBucket() { - return bucket; - } - - public int size() { - List keys = (List) riakTemplate.getBucketSchema(bucket, true).get("keys"); - return keys.size(); - } - - public boolean isEmpty() { - return size() == 0; - } -} diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/collection/RiakCollection.java b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/collection/RiakCollection.java deleted file mode 100644 index 1de0fc8cc..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/collection/RiakCollection.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak.collection; - -import java.util.Collection; - -/** - * @author J. Brisbin - */ -@SuppressWarnings("rawtypes") -public interface RiakCollection extends Collection { - String getBucket(); -} diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/collection/RiakEntityIndex.java b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/collection/RiakEntityIndex.java deleted file mode 100644 index e64ee22cf..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/collection/RiakEntityIndex.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak.collection; - -import java.util.AbstractList; -import java.util.List; -import java.util.Map; - -import org.springframework.data.keyvalue.riak.core.RiakTemplate; -import org.springframework.data.keyvalue.riak.mapreduce.JavascriptMapReduceOperation; -import org.springframework.data.keyvalue.riak.mapreduce.MapReduceJob; -import org.springframework.data.keyvalue.riak.mapreduce.MapReduceOperation; -import org.springframework.data.keyvalue.riak.mapreduce.MapReducePhase; -import org.springframework.data.keyvalue.riak.mapreduce.RiakMapReduceJob; -import org.springframework.data.keyvalue.riak.mapreduce.RiakMapReducePhase; - -/** - * @author J. Brisbin - */ -@SuppressWarnings({ "hiding", "rawtypes" }) -public class RiakEntityIndex extends AbstractList implements List, RiakCollection { - - private RiakTemplate riakTemplate; - private String bucket; - - public RiakEntityIndex(RiakTemplate riakTemplate, String bucket) { - this.riakTemplate = riakTemplate; - this.bucket = bucket; - } - - @Override - public Object get(int i) { - return riakTemplate.execute(createFetchAtJob(i), Map.class); - } - - @Override - public int size() { - return riakTemplate.execute(createCountJob(), Integer.class); - } - - @Override - public boolean isEmpty() { - return size() == 0; - } - - public String getBucket() { - return bucket; - } - - private MapReduceJob createFetchAtJob(int i) { - MapReduceJob mapReduceJob = new RiakMapReduceJob(riakTemplate); - MapReduceOperation mapJs = new JavascriptMapReduceOperation( - "function(values){ var row=Riak.mapValuesJson(values); return [row]; }"); - MapReducePhase mapPhase = new RiakMapReducePhase(MapReducePhase.Phase.MAP, - "javascript", - mapJs); - mapReduceJob.addPhase(mapPhase); - MapReduceOperation reduceJs = new JavascriptMapReduceOperation(String.format( - "function(values){ return values[%s]; }", - i)); - MapReducePhase reducePhase = new RiakMapReducePhase(MapReducePhase.Phase.REDUCE, - "javascript", - reduceJs); - mapReduceJob.addPhase(reducePhase); - - return mapReduceJob; - } - - private MapReduceJob createCountJob() { - MapReduceJob mapReduceJob = new RiakMapReduceJob(riakTemplate); - MapReduceOperation mapJs = new JavascriptMapReduceOperation( - "function(values){ var row=Riak.mapValuesJson(values); return [row]; }"); - MapReducePhase mapPhase = new RiakMapReducePhase(MapReducePhase.Phase.MAP, - "javascript", - mapJs); - mapReduceJob.addPhase(mapPhase); - MapReduceOperation reduceJs = new JavascriptMapReduceOperation( - "function(values){ return values.length; }"); - MapReducePhase reducePhase = new RiakMapReducePhase(MapReducePhase.Phase.REDUCE, - "javascript", - reduceJs); - mapReduceJob.addPhase(reducePhase); - - return mapReduceJob; - } -} diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/collection/RiakList.java b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/collection/RiakList.java deleted file mode 100644 index 4937996bd..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/collection/RiakList.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak.collection; - -import java.util.AbstractList; - -/** - * @author J. Brisbin - */ -@SuppressWarnings("rawtypes") -public class RiakList extends AbstractList { - @Override - public Object get(int i) { - return null; - } - - @Override - public int size() { - return 0; - } -} diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/engine/RiakAssociationIndexer.java b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/engine/RiakAssociationIndexer.java deleted file mode 100644 index b3b55d991..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/engine/RiakAssociationIndexer.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak.engine; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Pattern; - -import org.springframework.core.convert.ConversionService; -import org.springframework.data.keyvalue.riak.core.RiakTemplate; -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.types.Association; - -/** - * @author J. Brisbin - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class RiakAssociationIndexer implements AssociationIndexer { - - @SuppressWarnings("unused") - private static final Pattern linkPattern = Pattern.compile( - "^<(.+)/(.+)/(.+)>; riaktag=\"(.+)\""); - private RiakTemplate riakTemplate; - @SuppressWarnings("unused") - private ConversionService conversionService; - private Association association; - PersistentEntity owner; - PersistentEntity child; - - public RiakAssociationIndexer(RiakTemplate riakTemplate, ConversionService conversionService, Association association) { - this.riakTemplate = riakTemplate; - this.conversionService = conversionService; - this.association = association; - this.owner = association.getOwner(); - this.child = association.getAssociatedEntity(); - } - - public void index(Long primaryKey, List foreignKeys) { - for (Long foreignKey : foreignKeys) { - link(foreignKey, primaryKey); - } - } - - public void index(Long primaryKey, Long foreignKey) { - link(foreignKey, primaryKey); - } - - protected void link(Long childKey, Long ownerKey) { - String bucketName = String.format("%s.%s.%s", - owner.getName(), - association.getName(), - ownerKey); - riakTemplate.set(bucketName, childKey, ""); - riakTemplate.link(child.getName(), childKey, bucketName, childKey, "target"); - //SimpleBucketKeyPair bkpOwner = new SimpleBucketKeyPair(owner.getName(), ownerKey); - //riakTemplate.link(bkpChild, bkpOwner, "owner"); - } - - public List query(Long primaryKey) { - String bucketName = String.format("%s.%s.%s", - owner.getName(), - association.getName(), - primaryKey); - Object obj = riakTemplate.getBucketSchema(bucketName, true).get("keys"); - List keys = new ArrayList(); - if (obj instanceof List) { - for (String key : (List) obj) { - keys.add(Long.parseLong(key)); - } - } - return keys; - } - - public PersistentEntity getIndexedEntity() { - return association.getAssociatedEntity(); - } -} diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/engine/RiakEntityPersister.java b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/engine/RiakEntityPersister.java deleted file mode 100644 index a5d8dba9b..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/engine/RiakEntityPersister.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak.engine; - -import java.io.Serializable; -import java.util.Calendar; -import java.util.Date; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.core.convert.ConversionService; -import org.springframework.data.keyvalue.riak.core.QosParameters; -import org.springframework.data.keyvalue.riak.core.RiakTemplate; -import org.springframework.data.keyvalue.riak.core.RiakValue; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.PropertyValueIndexer; -import org.grails.datastore.mapping.keyvalue.engine.AbstractKeyValueEntityPersister; -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.Association; -import org.grails.datastore.mapping.proxy.EntityProxy; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.riak.RiakEntry; -import org.grails.datastore.mapping.riak.RiakSession; -import org.grails.datastore.mapping.riak.collection.RiakEntityIndex; -import org.grails.datastore.mapping.riak.query.RiakQuery; - -/** - * An {@link org.grails.datastore.mapping.engine.EntityPersister} implementation for - * the Riak Key/Value store. - * - * @author J. Brisbin - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class RiakEntityPersister extends AbstractKeyValueEntityPersister { - - private final static String DISCRIMINATOR = "__entity__"; - private final static String DESCENDANTS = "descendants"; - private final Logger log = LoggerFactory.getLogger(getClass()); - private RiakTemplate riakTemplate; - - public RiakEntityPersister(MappingContext context, PersistentEntity entity, Session session, - final RiakTemplate riakTemplate, ApplicationEventPublisher publisher) { - super(context, entity, session, publisher); - this.riakTemplate = riakTemplate; - } - - @Override - protected void deleteEntry(String family, Long key, Object entry) { - riakTemplate.deleteKeys(String.format("%s:%s", family, key)); - } - - @Override - protected Long generateIdentifier(PersistentEntity persistentEntity, Map id) { - return UUID.randomUUID().getLeastSignificantBits(); - } - - public RiakEntityIndex getAllEntityIndex() { - return new RiakEntityIndex(riakTemplate, getEntityFamily()); - } - - @Override - public PropertyValueIndexer getPropertyIndexer(PersistentProperty property) { - return new RiakPropertyValueIndexer(riakTemplate, getMappingContext(), this, property); - } - - @Override - public AssociationIndexer getAssociationIndexer(Map nativeEntry, Association association) { - return new RiakAssociationIndexer(riakTemplate, - getMappingContext().getConversionService(), - association); - } - - @Override - protected Map createNewEntry(String family) { - return new RiakEntry(family); - } - - @Override - protected Object getEntryValue(Map nativeEntry, String property) { - PersistentProperty prop = getPersistentEntity().getPropertyByName(property); - if (null != prop) { - if (prop.getType() == Date.class) { - // If this property is a Date object, we need to handle it as a Long, - // otherwise it will get improperly formatted in the Query implementation. - return new Date(Long.parseLong(nativeEntry.get(property).toString())); - } - if (prop.getType() == Calendar.class) { - // If this property is a Calendar object, we need to handle it as a Long, - // otherwise it will get improperly formatted in the Query implementation. - Calendar c = Calendar.getInstance(); - c.setTime(new Date(Long.parseLong(nativeEntry.get(property).toString()))); - return c; - } - if (prop.getType() == Boolean.class) { - return (nativeEntry.containsKey(property) ? - Boolean.valueOf(nativeEntry.get(property).toString()) : - false); - } - } - return nativeEntry.get(property); - } - - @Override - protected void setEntryValue(Map nativeEntry, String key, Object value) { - if (null == value) { - return; - } - - if (value instanceof Date) { - // Date handling again, like above - nativeEntry.put(key, ((Date) value).getTime()); - } else if (value instanceof Calendar) { - // Calendar handling again, like above - nativeEntry.put(key, ((Calendar) value).getTime().getTime()); - } else if (value instanceof Boolean) { - nativeEntry.put(key, value); - } else if (value instanceof Enum) { - nativeEntry.put(key, value.toString()); - } else if (shouldConvert(value)) { - final ConversionService conversionService = getMappingContext().getConversionService(); - nativeEntry.put(key, conversionService.convert(value, String.class)); - } - } - - @Override - protected PersistentEntity discriminatePersistentEntity(PersistentEntity persistentEntity, Map nativeEntry) { - if (nativeEntry.containsKey(DISCRIMINATOR)) { - PersistentEntity e = getMappingContext().getChildEntityByDiscriminator(persistentEntity.getRootEntity(), - nativeEntry.get(DISCRIMINATOR).toString()); - if (null != e) { - return e; - } - return persistentEntity; - } - return persistentEntity; - } - - @Override - protected Map retrieveEntry(PersistentEntity persistentEntity, String family, Serializable key) { - // Not sure this check is actually necessary, but I was seeing null keys being passed - // during tests, so handle it explicitly. - if (null == key) { - return null; - } - - Set descendants = null; - RiakValue v = null; - - // Check for any descendants this entity might have. - String bucket = persistentEntity.getName() + ".metadata"; - if (riakTemplate.containsKey(bucket, DESCENDANTS)) { - descendants = riakTemplate.getAsType(bucket, DESCENDANTS, Set.class); - v = riakTemplate.getWithMetaData(family, - (key instanceof Long ? (Long) key : Long.parseLong(key.toString())), - Map.class); - if (log.isDebugEnabled()) { - log.debug(String.format("retrieveEntry(): entity=%s, family=%s, key=%s, values=%s", - persistentEntity.getName(), family, key, v)); - } - } - - if (null == v && null != descendants) { - // Search through all descendants, as well. - for (String d : descendants) { - v = riakTemplate.getWithMetaData(d, - (key instanceof Long ? (Long) key : Long.parseLong(key.toString())), - Map.class); - if (null != v) { - break; - } - } - } - - return (null != v ? v.get() : null); - } - - @Override - protected Long storeEntry(final PersistentEntity persistentEntity, final EntityAccess entityAccess, - final Long storeId, final Map nativeEntry) { - Map metaData = null; - - // Quality Of Service parameters (r, w, dw) - QosParameters qosParams = ((RiakSession) getSession()).getQosParameters(); - - if (!persistentEntity.isRoot()) { - // This is a subclass, find our ancestry. - List ancestors = getAncestors(persistentEntity); - if (log.isDebugEnabled()) { - log.debug("Storing entity ancestor metadata for " + ancestors); - } - - for (String s : ancestors) { - String bucket = s + ".metadata"; - if (riakTemplate.containsKey(bucket, DESCENDANTS)) { - // Build up a list of our ancestors and store it with the special metadata on this entity. - Set descendants = riakTemplate.getAsType(bucket, DESCENDANTS, Set.class); - if (null == descendants) { - descendants = new LinkedHashSet(); - } - descendants.add(persistentEntity.getName()); - - riakTemplate.set(bucket, DESCENDANTS, descendants); - } - } - - metaData = new LinkedHashMap(); - - // Also save this information into a metadata entry for use down the road. - metaData.put("X-Riak-Meta-Entity", persistentEntity.getName()); - // Save discriminator information - nativeEntry.put(DISCRIMINATOR, persistentEntity.getDiscriminator()); - } - - riakTemplate.setWithMetaData(persistentEntity.getName(), - storeId, nativeEntry, metaData, qosParams); - - return storeId; - } - - @Override - protected void updateEntry(final PersistentEntity persistentEntity, final EntityAccess entityAccess, - final Long key, final Map entry) { - storeEntry(persistentEntity, entityAccess, key, entry); - } - - @Override - protected void deleteEntries(String family, List keys) { - for (Long key : keys) { - riakTemplate.delete(family, key); - } - } - - protected boolean shouldConvert(Object value) { - return !getMappingContext().isPersistentEntity(value) && !(value instanceof EntityProxy); - } - - public Query createQuery() { - return new RiakQuery(session, getPersistentEntity(), riakTemplate); - } - - protected String getRootFamily(PersistentEntity entity) { - String family = getFamily(entity, entity.getMapping()); - if (!entity.isRoot()) { - PersistentEntity root = entity.getRootEntity(); - family = getFamily(root, root.getMapping()); - } - return family; - } - - protected List getAncestors(PersistentEntity entity) { - List ancestors = new LinkedList(); - PersistentEntity parent = entity.getParentEntity(); - ancestors.add(parent.getName()); - if (!parent.isRoot()) { - ancestors.addAll(getAncestors(parent)); - } - return ancestors; - } -} diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/engine/RiakPropertyValueIndexer.java b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/engine/RiakPropertyValueIndexer.java deleted file mode 100644 index 480f4df34..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/engine/RiakPropertyValueIndexer.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak.engine; - -import org.grails.datastore.mapping.engine.PropertyValueIndexer; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.springframework.data.keyvalue.riak.core.RiakTemplate; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author J. Brisbin - */ -@SuppressWarnings("rawtypes") -public class RiakPropertyValueIndexer implements PropertyValueIndexer { - - @SuppressWarnings("unused") - private RiakTemplate riakTemplate; - @SuppressWarnings("unused") - private MappingContext mappingContext; - @SuppressWarnings("unused") - private RiakEntityPersister riakEntityPersister; - @SuppressWarnings("unused") - private PersistentProperty property; - - public RiakPropertyValueIndexer(RiakTemplate riakTemplate, MappingContext mappingContext, - RiakEntityPersister riakEntityPersister, PersistentProperty property) { - this.riakTemplate = riakTemplate; - this.mappingContext = mappingContext; - this.riakEntityPersister = riakEntityPersister; - this.property = property; - } - - public void index(Object value, Long primaryKey) { - } - - public List query(Object value) { - return query(value, 0, -1); - } - - public List query(Object value, int offset, int max) { - @SuppressWarnings("unused") - String js = "function(sdata) {\n" + - " var data = Riak.mapValuesJson(sdata);\n" + - " ejsLog(\"/tmp/mapred.log\", JSON.stringify(sdata));\n" + - " ejsLog(\"/tmp/mapred.log\", JSON.stringify(data));\n" + - " return [data];\n" + - "}"; - return new ArrayList(); - } - - public String getIndexName(Object value) { - return null; - } - - public void deindex(Object value, Long primaryKey) { - } -} diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/query/RiakQuery.groovy b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/query/RiakQuery.groovy deleted file mode 100644 index 1959a5167..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/query/RiakQuery.groovy +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak.query - -import org.codehaus.groovy.runtime.typehandling.GroovyCastException -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.data.keyvalue.riak.core.RiakTemplate -import org.springframework.data.keyvalue.riak.mapreduce.* -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.query.Query - -/** - * A {@link Query} implementation for the Riak Key/Value store. - *

    - * This query implementation relies heavily on Riak's native Map/Reduce functionality. It - * expects data to be stored as JSON documents, which is how GORM stores objects into Riak. - * - * @author J. Brisbin - */ -class RiakQuery extends Query { - - static Logger log = LoggerFactory.getLogger(RiakQuery) - - static queryHandlers - static { - queryHandlers = [ - (Query.Equals): { Query.Equals equals, PersistentEntity entity, buff -> - def val = checkForDate(equals.value) - if (val instanceof Boolean) { - // If we're comparing booleans, we need to see what format the entry property - // is in. If it's not already a boolean, make it one. - buff << "(typeof entry.${equals.name} === 'boolean' ? " + (val ? "entry.${equals.name}" : "!entry.${equals.name}") + " : " + (val ? "Boolean(entry.${equals.name})" : "!Boolean(entry.${equals.name})") + ")" - } else if (val instanceof Integer || val instanceof Double || val instanceof Long) { - if ("id" == equals.name) { - // Handle object IDs by comparing to Riak's key field. - buff << "v.key === \"${val}\"" - } else { - // All else must be a number, don't use quotes. - buff << "entry.${equals.name} == ${val}" - } - } else { - // Compare with quotes. - buff << "entry.${equals.name} === \"${val}\"" - } - }, - (Query.IdEquals): { Query.IdEquals idEquals, PersistentEntity entity, buff -> - buff << "v.key === \"${idEquals.value}\"" - }, - (Query.NotEquals): { Query.NotEquals notEquals, PersistentEntity entity, buff -> - def val = checkForDate(notEquals.value) - if (val instanceof Boolean) { - buff << "(typeof entry.${notEquals.name} === 'boolean' ? " + (val ? "entry.${notEquals.name}" : "!entry.${notEquals.name}") + " : " + (val ? "Boolean(entry.${notEquals.name})" : "!Boolean(entry.${notEquals.name})") + ")" - } else if (val instanceof Integer || val instanceof Double || val instanceof Long) { - if ("id" == equals.name) { - buff << "v.key !== \"${val}\"" - } else { - buff << "entry.${notEquals.name} != ${val}" - } - } else { - buff << "entry.${notEquals.name} !== \"${val}\"" - } - }, - (Query.GreaterThan): { Query.GreaterThan gt, PersistentEntity entity, buff -> - def val = checkForDate(gt.value) - buff << "entry.${gt.name} > ${val}" - }, - (Query.GreaterThanEquals): { Query.GreaterThanEquals gte, PersistentEntity entity, buff -> - def val = checkForDate(gte.value) - buff << "entry.${gte.name} >= ${val}" - }, - (Query.LessThan): { Query.LessThan lt, PersistentEntity entity, buff -> - def val = checkForDate(lt.value) - buff << "entry.${lt.name} < ${val}" - }, - (Query.LessThanEquals): { Query.LessThanEquals lte, PersistentEntity entity, buff -> - def val = checkForDate(lte.value) - buff << "entry.${lte.name} <= ${val}" - }, - (Query.Between): { Query.Between between, PersistentEntity entity, buff -> - def to = checkForDate(between.to) - def from = checkForDate(between.from) - buff << "(entry.${between.property} <= ${to}) && (entry.${between.property} >= ${from})" - }, - (Query.Like): { Query.Like like, PersistentEntity entity, buff -> - def regexp = like.value.toString().replaceAll("%", "(.+)") - buff << "/^$regexp/.test(\"\"+entry.${like.name})" - }, - (Query.Conjunction): { Query.Conjunction and, PersistentEntity entity, buff -> - def conjunc = RiakQuery.handleJunction(and, entity).collect { "(" + it + ")"}.join("&&") - buff << "($conjunc)" - }, - (Query.Disjunction): { Query.Disjunction or, PersistentEntity entity, buff -> - def disjunc = RiakQuery.handleJunction(or, entity).collect { "(" + it + ")"}.join("||") - buff << "($disjunc)" - }, - (Query.Negation): { Query.Negation not, PersistentEntity entity, buff -> - def neg = RiakQuery.handleJunction(not, entity).collect { "!(" + it + ")"}.join("&&") - buff << neg - }, - (Query.In): { Query.In qin, PersistentEntity entity, buff -> - def inClause = qin.values.collect { - "(entry.${qin.name} === \"$it\")" - }.join("||") - buff << "($inClause)" - } - ] - } - - RiakTemplate riak - - RiakQuery(Session session, PersistentEntity ent, RiakTemplate riak) { - super(session, ent); - this.riak = riak - } - - protected List executeQuery(PersistentEntity entity, Query.Junction criteria) { - def buff = [] - criteria.criteria.each { criterion -> - if (log.debugEnabled) { - log.debug "Found criteria: ${criterion}" - } - def handler = queryHandlers[criterion.class] - if (handler) { - handler(criterion, entity, buff) - } else { - return [] - } - } - // If any criteria exist, join them together into a meaningful if clause. - def joinStr = (criteria && criteria instanceof Query.Disjunction ? "||" : "&&") - def ifclause = buff.join(joinStr) ?: "true" - StringBuilder mapJs = new StringBuilder("function(v){ var uuid='%UUID%'; var r=[];") - if (log.debugEnabled) { - mapJs << "ejsLog('/tmp/mapred.log', 'map input: '+JSON.stringify(v));" - } - if (ifclause != "true") { - // All this mess is to catch as many weird cases as possible. If I check for it here, - // I've seen it in testing and thought it prudent to catch as many errors as possible - // until I don't need to check for them any more. - mapJs << "try{if(v === [] || typeof v['values'] == \"undefined\" || v.values[0].data === \"\"){return [];}}catch(e){return [];};var o=Riak.mapValuesJson(v);for(i in o){var entry=o[i];" - if (ifclause != "true") { - mapJs << "if(${ifclause}){" - } - mapJs << "o[i].id=v.key;r.push(o[i]);}" - if (log.debugEnabled) { - mapJs << "} ejsLog('/tmp/mapred.log', 'map return: '+JSON.stringify(r)); return r;}" - } else { - mapJs << "} return r;}" - } - } else { - // Just copy all values to output, adding the key as the 'id' property. - mapJs << " var row = Riak.mapValuesJson(v); row[0].id = v.key; ejsLog('/tmp/mapred.log', 'map return: '+JSON.stringify(row)); return row; }" - } - def reduceJs - // Property projections. Implemented as Riak reduce functions. - List propProjs = new ArrayList() - def projectionList = projections() - if (projectionList.projections) { - StringBuilder jsbuff = new StringBuilder("function(reduced){ var uuid='%UUID%'; var r=[];") - if (log.debugEnabled) { - jsbuff << "ejsLog('/tmp/mapred.log', 'reduce input: '+JSON.stringify(reduced));" - } - projectionList.projectionList.each { proj -> - if (proj instanceof Query.CountProjection) { - // Since I'm not emitting a [1] from the map function, I have to interrogate - // every input element to see whether it's a count from a previous reduce call - // or whether it's unprocessed data coming from a map function. The input array - // contains both all mixed up. Arg! :/ - jsbuff << "var count=0; if(typeof reduced['vclock'] != 'undefined'){return [1];} for(i in reduced){ if(typeof reduced[i] === 'object'){ count += 1; } else { count += reduced[i]; }} r.push(count);" - } else if (proj instanceof Query.AvgProjection) { - // I don't actually average anything until I get ready to return the value below. - jsbuff << "var total=0.0; var count=0; for(i in reduced) { if(typeof reduced[i]['age'] !== 'undefined') { count += 1; total += parseFloat(reduced[i].age); } else { total += reduced[i].total; count += reduced[i].count; } } r.push({total: total, count: count});" - } else if (proj instanceof Query.MaxProjection) { - // Find the max for this step, keeping in mind the real max won't be found until - // the end of the processing, right before the return below. - jsbuff << "var max = false; for(i in reduced){ var d; if(typeof reduced[i] === 'object'){ d = parseFloat(reduced[i].${proj.propertyName}); }else{ d = reduced[i]; } if(!max || d > max){ max = d; }} if(!max === false){ r.push(max); }" - } else if (proj instanceof Query.MinProjection) { - // Find the min for this step, keeping in mind the real min won't be found until - // the end of the processing, right before the return below. - jsbuff << "var min = false; for(i in reduced){ var d; if(typeof reduced[i] === 'object'){ d = parseFloat(reduced[i].${proj.propertyName}); }else{ d = reduced[i]; } if(!min || d < min){ min = d; }} if(!min === false){ r.push(min); }" - } else if (proj instanceof Query.IdProjection) { - // This just returns the object ID. - jsbuff << "for(i in reduced){ if(typeof reduced[i] === 'object'){ r.push(parseFloat(reduced[i].id)); }else{ r.push(reduced[i]); }}" - } else if (proj instanceof Query.PropertyProjection) { - // Property projections are handled below. - propProjs << proj - jsbuff << "r = reduced;" - } - } - if (log.debugEnabled) { - jsbuff << "ejsLog('/tmp/mapred.log', 'reduce return: '+JSON.stringify(r));" - } - jsbuff << " return r;}" - reduceJs = jsbuff.toString() - } - - MapReduceJob mr = new RiakMapReduceJob(riak) - JavascriptMapReduceOperation mapOper = new JavascriptMapReduceOperation(mapJs.toString()) - MapReducePhase mapPhase = new RiakMapReducePhase(MapReducePhase.Phase.MAP, "javascript", mapOper) - mr.addPhase(mapPhase) - - JavascriptMapReduceOperation reduceOper - if (reduceJs) { - reduceOper = new JavascriptMapReduceOperation(reduceJs) - MapReducePhase reducePhase = new RiakMapReducePhase(MapReducePhase.Phase.REDUCE, "javascript", reduceOper) - mr.addPhase(reducePhase) - } - - // For sure process the bucket of the entity I'm working with... - def inputBuckets = [entity.name] - // Check for any descendants I also need to be aware of... - if (riak.containsKey(entity.name + ".metadata", "descendants")) { - def descendants = riak.getAsType(entity.name + ".metadata", "descendants", Set) - if (descendants) { - // ...and run this M/R against the buckets of any descendants I might have. - inputBuckets.addAll(descendants) - } - } - - def results = [] - inputBuckets.each { - mr.getInputs().clear() - mr.getInputs().add(it) - // For busting internal caching - def uuid = UUID.randomUUID().toString() - if (mapOper) { - def js = mapOper.source.replaceAll("%UUID%", uuid) - mapOper.source = js - } - if (reduceOper) { - def js = reduceOper.source.replaceAll("%UUID%", uuid) - reduceOper.source = js - } - - if (log.debugEnabled) { - log.debug("Running M/R: \n${mr.toJson()}") - } - def l = riak.execute(mr) - if (l) { - results.addAll(l) - } - } - // This portion shamelessly absconded from Graeme's RedisQuery.java - if (results) { - if (log.debugEnabled) { - log.debug("Got results: \n" + results) - } - final total = results.size() - if (offset > total) { - return Collections.emptyList() - } - def max = this.max // 20 - def from = offset // 10 - def to = max == -1 ? -1 : (offset + max) - 1 // 15 - if (to >= total) { - to = -1 - } - def finalResult = results[from..to] - if (orderBy) { - orderBy.each { Query.Order order -> - def sorted = finalResult.sort { - it."${order.property}" - } - final def os = order.direction.toString() - finalResult = os == "DESC" ? sorted.reverse() : sorted - } - } - - if (projectionList.projections) { - // I don't really like checking for projections again... - if (propProjs) { - // Pull out the property needed here. - if (propProjs.size() != 1) { - // Is this necessary? - log.warn "Only the first PropertyProjection is used: " + propProjs[0] - } - final propProj = propProjs[0] - String propName = propProj.propertyName - final collectedResults = finalResult.collect { entry -> - try { - // Try to return the object as the right data type. - entry."${propName}".asType(entity.getPropertyByName(propName).type) - } catch (GroovyCastException e) { - // If I can't do that... - if (entry."${propName}".isLong()) { - // Maybe I have an object ID? Try to look it up. - getSession().retrieve(entity.getPropertyByName(propName).type, entry."${propName}".toLong()) - } else { - // Otherwise, just return it, as I'm guessing this will be fine. - entry."${propName}" - } - } - } - - if(propProj instanceof Query.CountDistinctProjection) { - return [collectedResults.unique().size()] - } - else { - return collectedResults - } - } else { - // Use the built-in Groovy functions to operate on the List returned - // from the Map/Reduce step. - def projResult = projectionList.projectionList.collect { proj -> - if (proj instanceof Query.CountProjection) { - return finalResult.sum() - } - if (proj instanceof Query.AvgProjection) { - return finalResult.collect { it.total / it.count } - } - if (proj instanceof Query.MaxProjection) { - return finalResult.max() - } - if (proj instanceof Query.MinProjection) { - return finalResult.min() - } - return finalResult - } - // I might have a List of Lists because of the way I'm processing the - // projections and descendants. If so, I need a flat list. - if (projResult && projResult.size() == 1 && projResult.get(0) instanceof List) { - return projResult.get(0) - } - return projResult ?: finalResult - } - } else { - // I've got a list of object IDs. Go get all of them... - getSession().retrieveAll(getEntity().getJavaClass(), finalResult.collect { it.id?.toLong() }) - } - } else { - return Collections.emptyList() - } - } - - static handleJunction(Query.Junction junc, PersistentEntity entity) { - def buff = [] - junc.criteria.each { crit -> - def handler = queryHandlers[crit.class] - if (handler) { - handler(crit, entity, buff) - } - } - buff - } - - static checkForDate(val) { - if (val instanceof Date) { - ((Date) val).time - } else if (val instanceof Calendar) { - ((Calendar) val).time.time - } else { - val - } - } -} diff --git a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/util/Ignore404sErrorHandler.java b/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/util/Ignore404sErrorHandler.java deleted file mode 100644 index b39bfc1af..000000000 --- a/grails-datastore-riak/src/main/groovy/org/grails/datastore/mapping/riak/util/Ignore404sErrorHandler.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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.mapping.riak.util; - -import org.springframework.http.HttpStatus; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.web.client.DefaultResponseErrorHandler; - -import java.io.IOException; - -/** - * @author J. Brisbin - */ -public class Ignore404sErrorHandler extends DefaultResponseErrorHandler { - - @Override - protected boolean hasError(HttpStatus statusCode) { - if (statusCode != HttpStatus.NOT_FOUND) { - return super.hasError(statusCode); - } - return false; - } - - @Override - public void handleError(ClientHttpResponse response) throws IOException { - // Ignore 404s entirely - if (response.getStatusCode() != HttpStatus.NOT_FOUND) { - super.handleError(response); - } - } -} diff --git a/grails-datastore-simple/build.gradle b/grails-datastore-simple/build.gradle deleted file mode 100644 index dceb1528c..000000000 --- a/grails-datastore-simple/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - compile project(":grails-datastore-core") -} diff --git a/grails-datastore-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapDatastore.java b/grails-datastore-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapDatastore.java deleted file mode 100644 index cf739cf35..000000000 --- a/grails-datastore-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapDatastore.java +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (C) 2010 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.mapping.simple; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext; -import org.grails.datastore.mapping.model.MappingContext; -import org.springframework.context.ConfigurableApplicationContext; - -/** - * A simple implementation of the {@link org.grails.datastore.mapping.core.Datastore} interface that backs onto an in-memory map. - * Mainly used for mocking and testing scenarios. - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class SimpleMapDatastore extends AbstractDatastore { - private Map datastore = new ConcurrentHashMap(); - private Map indices = new ConcurrentHashMap(); - - /** - * Creates a map based datastore backing onto the specified map - * - * @param datastore The datastore to back on to - * @param ctx the application context - */ - public SimpleMapDatastore(Map datastore, ConfigurableApplicationContext ctx) { - this(); - this.datastore = datastore; - setApplicationContext(ctx); - } - - /** - * Creates a map based datastore for the specified mapping context - * - * @param mappingContext The mapping context - */ - public SimpleMapDatastore(MappingContext mappingContext, ConfigurableApplicationContext ctx) { - super(mappingContext, null, ctx); - initializeConverters(getMappingContext()); - } - - public SimpleMapDatastore() { - this(null); - } - - public SimpleMapDatastore(ConfigurableApplicationContext ctx) { - this(new KeyValueMappingContext(""), ctx); - } - - public Map getIndices() { - return indices; - } - - @Override - protected Session createSession(Map connectionDetails) { - return new SimpleMapSession(this, getMappingContext(), getApplicationEventPublisher()); - } - - public Map getBackingMap() { - return datastore; - } - - public void clearData() { - datastore.clear(); - indices.clear(); - } -} diff --git a/grails-datastore-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapSession.java b/grails-datastore-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapSession.java deleted file mode 100644 index 75b6e4691..000000000 --- a/grails-datastore-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapSession.java +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2010 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.mapping.simple; - -import java.util.Map; - -import org.springframework.context.ApplicationEventPublisher; -import org.grails.datastore.mapping.core.AbstractSession; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.simple.engine.SimpleMapEntityPersister; -import org.grails.datastore.mapping.transactions.Transaction; - -/** - * A simple implementation of the {@link org.grails.datastore.mapping.core.Session} interface that backs onto an in-memory map. - * Mainly used for mocking and testing scenarios - * - * @author Graeme Rocher - * @since 1.0 - */ -@SuppressWarnings("rawtypes") -public class SimpleMapSession extends AbstractSession { - private Map datastore; - - public SimpleMapSession(SimpleMapDatastore datastore, MappingContext mappingContext, - ApplicationEventPublisher publisher) { - super(datastore, mappingContext, publisher); - this.datastore = datastore.getBackingMap(); - } - - @Override - protected Persister createPersister(Class cls, MappingContext mappingContext) { - PersistentEntity entity = mappingContext.getPersistentEntity(cls.getName()); - if (entity == null) { - return null; - } - return new SimpleMapEntityPersister(mappingContext, entity, this, - (SimpleMapDatastore) getDatastore(), publisher); - } - - public Map getBackingMap() { - return datastore; - } - - @Override - protected Transaction beginTransactionInternal() { - return new MockTransaction(this); - } - - public Map getNativeInterface() { - return datastore; - } - - private class MockTransaction implements Transaction { - public MockTransaction(SimpleMapSession simpleMapSession) { - } - - public void commit() { - // do nothing - } - - public void rollback() { - // do nothing - } - - public Object getNativeTransaction() { - return this; - } - - public boolean isActive() { - return true; - } - - public void setTimeout(int timeout) { - // do nothing - } - } -} diff --git a/grails-datastore-simple/src/main/groovy/org/grails/datastore/mapping/simple/engine/SimpleMapEntityPersister.groovy b/grails-datastore-simple/src/main/groovy/org/grails/datastore/mapping/simple/engine/SimpleMapEntityPersister.groovy deleted file mode 100644 index a49ebe8c8..000000000 --- a/grails-datastore-simple/src/main/groovy/org/grails/datastore/mapping/simple/engine/SimpleMapEntityPersister.groovy +++ /dev/null @@ -1,348 +0,0 @@ -/* Copyright (C) 2010 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.mapping.simple.engine - -import org.grails.datastore.mapping.config.Property -import org.grails.datastore.mapping.core.IdentityGenerationException -import org.grails.datastore.mapping.core.OptimisticLockingException -import org.grails.datastore.mapping.core.Session -import org.grails.datastore.mapping.engine.AssociationIndexer -import org.grails.datastore.mapping.engine.EntityAccess -import org.grails.datastore.mapping.engine.EntityPersister -import org.grails.datastore.mapping.engine.PropertyValueIndexer -import org.grails.datastore.mapping.keyvalue.engine.AbstractKeyValueEntityPersister -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.Association -import org.grails.datastore.mapping.model.types.ManyToMany -import org.grails.datastore.mapping.query.Query -import org.grails.datastore.mapping.simple.SimpleMapDatastore -import org.grails.datastore.mapping.simple.query.SimpleMapQuery -import org.springframework.context.ApplicationEventPublisher - -/** - * A simple implementation of the {@link org.grails.datastore.mapping.engine.EntityPersister} abstract class that backs onto an in-memory map. - * Mainly used for mocking and testing scenarios - * - * @author Graeme Rocher - * @since 1.0 - */ -class SimpleMapEntityPersister extends AbstractKeyValueEntityPersister { - - Map datastore - Map indices - def lastKey - String family - - SimpleMapEntityPersister(MappingContext context, PersistentEntity entity, Session session, - SimpleMapDatastore datastore, ApplicationEventPublisher publisher) { - super(context, entity, session, publisher) - this.datastore = datastore.backingMap - this.indices = datastore.indices - family = getFamily(entity, entity.getMapping()) - final identity = entity.getIdentity() - def idType = identity?.type - if (idType == Integer) { - lastKey = 0 - } - else { - lastKey = 0L - } - if (this.datastore[family] == null) this.datastore[family] = [:] - } - - protected PersistentEntity discriminatePersistentEntity(PersistentEntity persistentEntity, Map nativeEntry) { - def disc = nativeEntry?.discriminator - if (disc) { - def childEntity = getMappingContext().getChildEntityByDiscriminator(persistentEntity.rootEntity, disc) - if (childEntity) return childEntity - } - return persistentEntity - } - - Query createQuery() { - return new SimpleMapQuery(session, getPersistentEntity(), this) - } - - protected void deleteEntry(String family, key, entry) { - datastore[family].remove(key) - } - - @Override - protected boolean isPropertyIndexed(Property mappedProperty) { - return true // index all - } - - PropertyValueIndexer getPropertyIndexer(PersistentProperty property) { - return new PropertyValueIndexer() { - - String getIndexRoot() { - return "~${property.owner.rootEntity.name}:${property.name}" - } - - void deindex(value, primaryKey) { - def index = getIndexName(value) - def indexed = indices[index] - if (indexed) { - indexed.remove(primaryKey) - } - } - - void index(value, primaryKey) { - - def index = getIndexName(value) - def indexed = indices[index] - if (indexed == null) { - indexed = [] - indices[index] = indexed - } - if (!indexed.contains(primaryKey)) { - indexed << primaryKey - } - } - - List query(value) { - query(value, 0, -1) - } - - List query(value, int offset, int max) { - def index = getIndexName(value) - - def indexed = indices[index] - if (!indexed) { - return Collections.emptyList() - } - return indexed[offset..max] - } - - String getIndexName(value) { - return "${indexRoot}:$value" - } - } - } - - AssociationIndexer getAssociationIndexer(Map nativeEntry, Association association) { - return new AssociationIndexer() { - - private getIndexName(primaryKey) { - "~${association.owner.name}:${association.name}:$primaryKey" - } - - @Override - void preIndex(Object primaryKey, List foreignKeys) { - // handled by index below. - } - - void index(primaryKey, List foreignKeys) { - def indexed = getIndex(primaryKey) - - indexed.addAll(foreignKeys) - def index = getIndexName(primaryKey) - indexed = indexed.unique() - indices[index] = indexed - } - - private List getIndex(primaryKey) { - def index = getIndexName(primaryKey) - def indexed = indices[index] - if (indexed == null) { - indexed = [] - indices[index] = indexed - } - return indexed - } - - void index(primaryKey, foreignKey) { - def indexed = getIndex(primaryKey) - if (!indexed.contains(foreignKey)) - indexed.add(foreignKey) - } - - List query(primaryKey) { - def index = getIndexName(primaryKey) - def indexed = indices[index] - if (indexed == null) { - return Collections.emptyList() - } - return indexed - } - - PersistentEntity getIndexedEntity() { - return association.associatedEntity - } - } - } - - @Override - protected void setManyToMany(PersistentEntity persistentEntity, Object obj, Map nativeEntry, ManyToMany manyToMany, Collection associatedObjects, Map> toManyKeys) { - - def identifiers - if (manyToMany.isOwningSide()) { - identifiers = session.persist(associatedObjects) - } - else { - identifiers = associatedObjects.collect { - EntityPersister persister = session.getPersister(it) - persister.getObjectIdentifier(it) - } - } - toManyKeys.put(manyToMany, identifiers) - } - - @Override - protected Collection getManyToManyKeys(PersistentEntity persistentEntity, Object obj, Serializable nativeKey, Map nativeEntry, ManyToMany manyToMany) { - final indexer = getAssociationIndexer(nativeEntry, manyToMany) - final primaryKey = getObjectIdentifier(obj) - indexer.query(primaryKey) - } - - protected Map createNewEntry(String family) { - return [:] - } - - protected getEntryValue(Map nativeEntry, String property) { - return nativeEntry[property] - } - - protected void setEntryValue(Map nativeEntry, String key, value) { - if (mappingContext.isPersistentEntity(value)) { - EntityPersister persister = session.getPersister(value) - value = persister.getObjectIdentifier(value) - } - nativeEntry[key] = value - } - - protected void setEmbedded(Map nativeEntry, String key, Map values) { - nativeEntry[key] = values - } - - protected Map getEmbedded( Map nativeEntry, String key) { - nativeEntry[key] - } - - protected Map retrieveEntry(PersistentEntity persistentEntity, String family, Serializable key) { - Map entry = datastore[family].get(key) - if (entry != null) { - // returning a copy is important here so that updates are applied to the copy and not the original - return new LinkedHashMap<>(entry) - } - return null - } - - protected generateIdentifier(PersistentEntity persistentEntity, Map id) { - final isRoot = persistentEntity.root - final type = isRoot ? persistentEntity.identity.type : persistentEntity.rootEntity.identity.type - if ((String.isAssignableFrom(type)) || (Number.isAssignableFrom(type))) { - def key - if (isRoot) { - key = ++lastKey - - } - else { - def root = persistentEntity.rootEntity - session.getPersister(root).lastKey++ - key = session.getPersister(root).lastKey - } - return type == String ? key.toString() : key - } - else { - try { - return type.newInstance() - } catch (e) { - throw new IdentityGenerationException("Cannot generator identity for entity $persistentEntity with type $type") - } - } - } - - protected storeEntry(PersistentEntity persistentEntity, EntityAccess entityAccess, storeId, Map nativeEntry) { - if (!persistentEntity.root) { - nativeEntry.discriminator = persistentEntity.discriminator - } - datastore[family].put(storeId, nativeEntry) - indexIdentifier(persistentEntity, storeId) - updateInheritanceHierarchy(persistentEntity, storeId, nativeEntry) - return storeId - } - - protected def indexIdentifier(PersistentEntity persistentEntity, storeId) { - final indexer = getPropertyIndexer(persistentEntity.identity) - indexer.index(storeId, storeId) - } - - private updateInheritanceHierarchy(PersistentEntity persistentEntity, storeId, Map nativeEntry) { - def parent = persistentEntity.parentEntity - while (parent != null) { - - def f = getFamily(parent, parent.mapping) - def parentEntry = datastore[f] - if (parentEntry == null) { - parentEntry = [:] - datastore[f] = parentEntry - } - parentEntry.put(storeId, nativeEntry) - parent = parent.parentEntity - } - } - - protected void updateEntry(PersistentEntity persistentEntity, EntityAccess entityAccess, key, Map entry) { - def family = getFamily(persistentEntity, persistentEntity.getMapping()) - def existing = datastore[family].get(key) - - if (isVersioned(entityAccess)) { - if (existing == null) { - setVersion entityAccess - } - else { - def oldVersion = existing.version - def currentVersion = entityAccess.getProperty('version') - if (Number.isAssignableFrom(entityAccess.getPropertyType('version'))) { - oldVersion = existing.version?.toLong() - currentVersion = entityAccess.getProperty('version')?.toLong() - if (currentVersion == null && oldVersion == null) { - currentVersion = 0L - entityAccess.setProperty("version", currentVersion) - entry["version"] = currentVersion - } - } - if (oldVersion != null && currentVersion != null && !oldVersion.equals(currentVersion)) { - throw new OptimisticLockingException(persistentEntity, key) - } - incrementVersion(entityAccess) - } - } - - indexIdentifier(persistentEntity, key) - if (existing == null) { - datastore[family].put(key, entry) - } - else { - existing.putAll(entry) - } - updateInheritanceHierarchy(persistentEntity, key, entry) - } - - protected void deleteEntries(String family, List keys) { - keys?.each { - datastore[family].remove(it) - def parent = persistentEntity.parentEntity - while (parent != null) { - def f = getFamily(parent, parent.mapping) - datastore[f].remove(it) - parent = parent.parentEntity - } - } - } -} diff --git a/grails-datastore-simple/src/main/groovy/org/grails/datastore/mapping/simple/query/SimpleMapQuery.groovy b/grails-datastore-simple/src/main/groovy/org/grails/datastore/mapping/simple/query/SimpleMapQuery.groovy deleted file mode 100644 index a4386d642..000000000 --- a/grails-datastore-simple/src/main/groovy/org/grails/datastore/mapping/simple/query/SimpleMapQuery.groovy +++ /dev/null @@ -1,781 +0,0 @@ -/* Copyright (C) 2010 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.mapping.simple.query - -import java.util.regex.Pattern - -import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValue -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.Custom -import org.grails.datastore.mapping.model.types.ToOne -import org.grails.datastore.mapping.query.AssociationQuery -import org.grails.datastore.mapping.query.Query -import org.grails.datastore.mapping.query.Restrictions -import org.grails.datastore.mapping.query.api.QueryableCriteria -import org.grails.datastore.mapping.query.criteria.FunctionCallingCriterion -import org.grails.datastore.mapping.simple.SimpleMapSession -import org.grails.datastore.mapping.simple.engine.SimpleMapEntityPersister -import org.springframework.dao.InvalidDataAccessResourceUsageException -import org.springframework.util.Assert - -/** - * Simple query implementation that queries a map of objects. - * - * @author Graeme Rocher - * @since 1.0 - */ -class SimpleMapQuery extends Query { - - Map datastore - private String family - private SimpleMapEntityPersister entityPersister - - SimpleMapQuery(SimpleMapSession session, PersistentEntity entity, SimpleMapEntityPersister entityPersister) { - super(session, entity) - this.datastore = session.getBackingMap() - family = getFamily(entity) - this.entityPersister = entityPersister - } - - protected List executeQuery(PersistentEntity entity, Query.Junction criteria) { - def results = [] - def entityMap = [:] - if (criteria.isEmpty()) { - populateQueryResult(datastore[family].keySet().toList(), entityMap) - } - else { - def criteriaList = criteria.getCriteria() - entityMap = executeSubQuery(criteria, criteriaList) - if (!entity.isRoot()) { - def childKeys = datastore[family].keySet() - entityMap = entityMap.subMap(childKeys) - } - } - - def nullEntries = entityMap.entrySet().findAll { it.value == null } - entityMap.keySet().removeAll(nullEntries.collect { it.key }) - - if (orderBy) { - orderBy.reverseEach { Query.Order order -> - boolean desc = order.direction == Query.Order.Direction.DESC - entityMap = entityMap.sort { a, b -> - int cmp = (a.value."${order.property}" <=> b.value."${order.property}") - return desc ? -cmp : cmp - } - } - } - if (projections.isEmpty()) { - results = entityMap.values() as List - } - else { - def projectionList = projections.projectionList - def projectionCount = projectionList.size() - def entityList = entityMap.values() - - projectionList.each { Query.Projection p -> - - if (p instanceof Query.IdProjection) { - if (projectionCount == 1) { - results = entityMap.keySet().toList() - } - else { - results.add(entityMap.keySet().toList()) - } - } - else if (p instanceof Query.CountProjection) { - results.add(entityList.size()) - } - else if (p instanceof Query.CountDistinctProjection) { - final uniqueList = new ArrayList(entityList).unique { it."$p.propertyName"} - results.add(uniqueList.size() ) - } - else if (p instanceof Query.PropertyProjection) { - def propertyValues = entityList.collect { it."$p.propertyName"} - if (p instanceof Query.MaxProjection) { - results.add(propertyValues.max()) - } - else if (p instanceof Query.MinProjection) { - results.add(propertyValues.min()) - } - else if (p instanceof Query.SumProjection) { - results.add(propertyValues.sum()) - } - else if (p instanceof Query.AvgProjection) { - def average = propertyValues.sum() / propertyValues.size() - results.add(average) - } - else { - PersistentProperty prop = entity.getPropertyByName(p.propertyName) - boolean distinct = p instanceof Query.DistinctPropertyProjection - if (distinct) { - propertyValues = propertyValues.unique() - } - - if (prop) { - if (prop instanceof ToOne) { - propertyValues = propertyValues.collect { - if (prop.associatedEntity.isInstance(it)) { - return it - } - session.retrieve(prop.type, it) - } - } - if (projectionCount == 1) { - results.addAll(propertyValues) - } - else { - results.add(propertyValues) - } - } - } - } - } - if (results.size() <= 1) // [] - results - else if (projectionCount == 1) // [, , ...] - results - else if (!(results[0] instanceof Collection)) // [, , ...] - results = [results] - else // [[, , ...], ...] - results = results.transpose() - } - if (results) { - return applyMaxAndOffset(results) - } - return Collections.emptyList() - } - - private List applyMaxAndOffset(List sortedResults) { - final def total = sortedResults.size() - if (offset > total) return Collections.emptyList() - - // 0..3 - // 0..-1 - // 1..1 - def max = this.max // 20 - def from = offset // 10 - def to = max == -1 ? -1 : (offset + max) - 1 // 15 - if (to >= total) to = -1 - - return sortedResults[from..to] - } - - def associationQueryHandlers = [ - (AssociationQuery): { allEntities, Association association, AssociationQuery aq-> - Query.Junction queryCriteria = aq.criteria - return executeAssociationSubQuery(datastore[getFamily(association.associatedEntity)], association.associatedEntity,queryCriteria, aq.association) - }, - - (FunctionCallingCriterion): { allEntities, Association association, FunctionCallingCriterion fcc -> - def criterion = fcc.propertyCriterion - def handler = associationQueryHandlers[criterion.class] - def function = functionHandlers[fcc.functionName] - if (handler != null && function != null) { - try { - return handler.call(allEntities, association,criterion, function) - } - catch(MissingMethodException ignored) { - throw new InvalidDataAccessResourceUsageException("Unsupported function '$function' used in query") - } - } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function '$function' used in query") - } - }, - (Query.Like): { allEntities, Association association, Query.Like like, Closure function = {it} -> - queryAssociation(allEntities, association) { - def regexFormat = like.pattern.replaceAll('%', '.*?') - function(resolveIfEmbedded(like.property, it)) ==~ regexFormat - } - }, - (Query.RLike): { allEntities, Association association, Query.RLike like, Closure function = {it} -> - queryAssociation(allEntities, association) { - def regexFormat = like.pattern - function(resolveIfEmbedded(like.property, it)) ==~ regexFormat - } - }, - (Query.ILike): { allEntities, Association association, Query.Like like, Closure function = {it} -> - queryAssociation(allEntities, association) { - def regexFormat = like.pattern.replaceAll('%', '.*?') - def pattern = Pattern.compile(regexFormat, Pattern.CASE_INSENSITIVE) - pattern.matcher(function(resolveIfEmbedded(like.property, it))).find() - } - }, - (Query.Equals): { allEntities, Association association, Query.Equals eq, Closure function = {it} -> - queryAssociation(allEntities, association) { - final value = subqueryIfNecessary(eq) - function(resolveIfEmbedded(eq.property, it)) == value - } - }, - (Query.IsNull): { allEntities, Association association, Query.IsNull eq, Closure function = {it} -> - queryAssociation(allEntities, association) { - function(resolveIfEmbedded(eq.property, it)) == null - } - }, - (Query.NotEquals): { allEntities, Association association, Query.NotEquals eq , Closure function = {it}-> - queryAssociation(allEntities, association) { - final value = subqueryIfNecessary(eq) - function(resolveIfEmbedded(eq.property, it)) != value - } - }, - (Query.IsNotNull): { allEntities, Association association, Query.IsNotNull eq , Closure function = {it}-> - queryAssociation(allEntities, association) { - function(resolveIfEmbedded(eq.property, it)) != null - } - }, - (Query.IdEquals): { allEntities, Association association, Query.IdEquals eq , Closure function = {it}-> - queryAssociation(allEntities, association) { - function(resolveIfEmbedded(eq.property, it)) == eq.value - } - }, - (Query.Between): { allEntities, Association association, Query.Between between, Closure function = {it} -> - queryAssociation(allEntities, association) { - def from = between.from - def to = between.to - function(resolveIfEmbedded(between.property, it)) >= from && function(resolveIfEmbedded(between.property, it)) <= to - } - }, - (Query.GreaterThan):{ allEntities, Association association, Query.GreaterThan gt, Closure function = {it} -> - queryAssociation(allEntities, association) { - final value = subqueryIfNecessary(gt) - function(resolveIfEmbedded(gt.property, it)) > value - } - }, - (Query.LessThan):{ allEntities, Association association, Query.LessThan lt, Closure function = {it} -> - queryAssociation(allEntities, association) { - final value = subqueryIfNecessary(lt) - function(resolveIfEmbedded(lt.property, it)) < value - } - }, - (Query.GreaterThanEquals):{ allEntities, Association association, Query.GreaterThanEquals gt, Closure function = {it} -> - queryAssociation(allEntities, association) { - final value = subqueryIfNecessary(gt) - function(resolveIfEmbedded(gt.property, it)) >= value - } - }, - (Query.LessThanEquals):{ allEntities, Association association, Query.LessThanEquals lt, Closure function = {it} -> - queryAssociation(allEntities, association) { - final value = subqueryIfNecessary(lt) - function(resolveIfEmbedded(lt.property, it)) <= value - } - }, - (Query.In):{ allEntities, Association association, Query.In inList, Closure function = {it} -> - queryAssociation(allEntities, association) { - inList.values?.contains function(resolveIfEmbedded(inList.property, it)) - } - } - ] - - protected queryAssociation(allEntities, Association association, Closure callable) { - allEntities.findAll { - def propertyName = association.name - if (association instanceof ToOne) { - - def id = it.value[propertyName] - - // If the entity isn't mocked properly this will happen and can cause a NPE. - PersistentEntity associatedEntity = association.associatedEntity - if( associatedEntity == null ) { - throw new IllegalStateException("No associated entity found for ${association.owner}.${association.name}") - } - - def associated = session.retrieve(associatedEntity.javaClass, id) - if (associated) { - callable.call(associated) - } - } - else { - def indexer = entityPersister.getAssociationIndexer(it.value, association) - def results = indexer.query(it.key) - if (results) { - def associatedEntities = session.retrieveAll(association.associatedEntity.javaClass, results) - return associatedEntities.any(callable) - } - } - }.keySet().toList() - } - - protected queryAssociationList(allEntities, Association association, Closure callable) { - allEntities.findAll { - def indexer = entityPersister.getAssociationIndexer(it.value, association) - def results = indexer.query(it.key) - callable.call(results) - }.keySet().toList() - } - - def executeAssociationSubQuery(allEntities, PersistentEntity associatedEntity, Query.Junction queryCriteria, PersistentProperty property) { - List resultList = [] - for (Query.Criterion criterion in queryCriteria.getCriteria()) { - def handler = associationQueryHandlers[criterion.getClass()] - - if (handler) { - resultList << handler.call(allEntities, property, criterion) - } - else if (criterion instanceof Query.Junction) { - Query.Junction junction = criterion - resultList << executeAssociationSubQuery(allEntities,associatedEntity, junction, property) - } - } - return applyJunctionToResults(queryCriteria, resultList) - } - - def functionHandlers = [ - second: { it[Calendar.SECOND] }, - minute: { it[Calendar.MINUTE] }, - hour: { it[Calendar.HOUR_OF_DAY] }, - year: { it[Calendar.YEAR] }, - month: { it[Calendar.MONTH] }, - day: { it[Calendar.DAY_OF_MONTH] }, - lower: { it.toString().toLowerCase() }, - upper: { it.toString().toUpperCase() }, - trim: { it.toString().trim() }, - length: { it.toString().size() } - ] - def handlers = [ - (FunctionCallingCriterion): { FunctionCallingCriterion fcc, PersistentProperty property -> - def criterion = fcc.propertyCriterion - def handler = handlers[criterion.class] - def function = functionHandlers[fcc.functionName] - if (handler != null && function != null) { - try { - handler.call(criterion, property, function, fcc.onValue) - } - catch(MissingMethodException e) { - throw new InvalidDataAccessResourceUsageException("Unsupported function '$function' used in query") - } - } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function '$function' used in query") - } - }, - (AssociationQuery): { AssociationQuery aq, PersistentProperty property -> - Query.Junction queryCriteria = aq.criteria - return executeAssociationSubQuery(datastore[family], aq.association.associatedEntity, queryCriteria, property) - }, - (Query.EqualsAll):{ Query.EqualsAll equalsAll, PersistentProperty property, Closure function=null, boolean onValue = false -> - def name = equalsAll.property - final values = subqueryIfNecessary(equalsAll, false) - Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") - def allEntities = datastore[family] - allEntities.findAll { entry -> - values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) == it } - } - .collect { it.key } - }, - (Query.NotEqualsAll):{ Query.NotEqualsAll notEqualsAll, PersistentProperty property, Closure function=null, boolean onValue = false -> - def name = notEqualsAll.property - final values = subqueryIfNecessary(notEqualsAll, false) - Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") - def allEntities = datastore[family] - allEntities.findAll { entry -> - values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) != it } - } - .collect { it.key } - }, - (Query.GreaterThanAll):{ Query.GreaterThanAll greaterThanAll, PersistentProperty property, Closure function=null, boolean onValue = false -> - def name = greaterThanAll.property - final values = subqueryIfNecessary(greaterThanAll, false) - Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") - def allEntities = datastore[family] - allEntities.findAll { entry -> - values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) > it } - } - .collect { it.key } - }, - (Query.LessThanAll):{ Query.LessThanAll lessThanAll, PersistentProperty property, Closure function=null, boolean onValue = false -> - def name = lessThanAll.property - final values = subqueryIfNecessary(lessThanAll, false) - Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") - def allEntities = datastore[family] - allEntities.findAll { entry -> - values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) < it } - } - .collect { it.key } - }, - (Query.LessThanEqualsAll):{ Query.LessThanEqualsAll lessThanEqualsAll, PersistentProperty property, Closure function=null, boolean onValue = false -> - def name = lessThanEqualsAll.property - final values = subqueryIfNecessary(lessThanEqualsAll, false) - Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") - def allEntities = datastore[family] - allEntities.findAll { entry -> - values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) <= it } - } - .collect { it.key } - }, - (Query.GreaterThanEqualsAll):{ Query.GreaterThanEqualsAll greaterThanAll, PersistentProperty property, Closure function=null, boolean onValue = false -> - def name = greaterThanAll.property - final values = subqueryIfNecessary(greaterThanAll, false) - Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") - def allEntities = datastore[family] - allEntities.findAll { entry -> - values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) >= it } - } - .collect { it.key } - }, - (Query.Equals): { Query.Equals equals, PersistentProperty property, Closure function = null, boolean onValue = false -> - def indexer = entityPersister.getPropertyIndexer(property) - final value = subqueryIfNecessary(equals) - - if (function != null) { - def allEntities = datastore[family] - allEntities.findAll { - def calculatedValue = function(it.value[property.name]) - calculatedValue == value - }.collect { it.key } - } - else { - if (value == null && (property instanceof ToOne)) { - def allEntities = datastore[family] - return allEntities.findAll { it.value[property.name] == null }.collect { it.key } - } - else if (equals.property.contains('.')) { - def allEntities = datastore[family] - return allEntities.findAll { resolveIfEmbedded(equals.property, it.value) == value }.collect { it.key } - } - else { - return indexer.query(value) - } - } - }, - (Query.IsNull): { Query.IsNull equals, PersistentProperty property, Closure function = null , boolean onValue = false-> - handlers[Query.Equals].call(new Query.Equals(equals.property, null), property, function) - }, - (Query.IdEquals): { Query.IdEquals equals, PersistentProperty property -> - def indexer = entityPersister.getPropertyIndexer(property) - return indexer.query(equals.value) - }, - (Query.NotEquals): { Query.NotEquals equals, PersistentProperty property, Closure function = null, boolean onValue = false -> - def indexed = handlers[Query.Equals].call(new Query.Equals(equals.property, equals.value), property, function) - return negateResults(indexed) - }, - (Query.IsNotNull): { Query.IsNotNull equals, PersistentProperty property, Closure function = null, boolean onValue = false -> - def indexed = handlers[Query.Equals].call(new Query.Equals(equals.property, null), property, function) - return negateResults(indexed) - }, - (Query.Like): { Query.Like like, PersistentProperty property -> - def indexer = entityPersister.getPropertyIndexer(property) - - def root = indexer.indexRoot - def regexFormat = like.pattern.replaceAll('%', '.*?') - def pattern = "${root}:${regexFormat}" - def matchingIndices = entityPersister.indices.findAll { key, value -> - key ==~ pattern - } - - Set result = [] - for (indexed in matchingIndices) { - result.addAll(indexed.value) - } - - return result.toList() - }, - (Query.ILike): { Query.ILike like, PersistentProperty property -> - def regexFormat = like.pattern.replaceAll('%', '.*?') - return executeLikeWithRegex(entityPersister, property, regexFormat) - }, - (Query.RLike): { Query.RLike like, PersistentProperty property -> - def regexFormat = like.pattern - return executeLikeWithRegex(entityPersister, property, regexFormat) - }, - (Query.In): { Query.In inList, PersistentProperty property -> - def disjunction = new Query.Disjunction() - for (value in inList.values) { - disjunction.add(Restrictions.eq(inList.name, value)) - } - - executeSubQueryInternal(disjunction, disjunction.criteria) - }, - (Query.Between): { Query.Between between, PersistentProperty property, Closure function = null, boolean onValue = false -> - def from = between.from - def to = between.to - def name = between.property - def allEntities = datastore[family] - - if (function != null) { - allEntities.findAll { function(resolveIfEmbedded(name, it.value)) >= from && function(resolveIfEmbedded(name, it.value)) <= to }.collect { it.key } - } - else { - allEntities.findAll { resolveIfEmbedded(name, it.value) >= from && resolveIfEmbedded(name, it.value) <= to }.collect { it.key } - } - }, - (Query.GreaterThan): { Query.GreaterThan gt, PersistentProperty property, Closure function = null, boolean onValue = false -> - def name = gt.property - final value = subqueryIfNecessary(gt) - def allEntities = datastore[family] - - allEntities.findAll { (function != null ? function(resolveIfEmbedded(name, it.value)) : resolveIfEmbedded(name, it.value)) > value }.collect { it.key } - }, - (Query.GreaterThanProperty): { Query.GreaterThanProperty gt, PersistentProperty property, Closure function = null, boolean onValue = false -> - def name = gt.property - def other = gt.otherProperty - def allEntities = datastore[family] - - allEntities.findAll { (function != null ? function(resolveIfEmbedded(name, it.value)) : resolveIfEmbedded(name, it.value)) > it.value[other] }.collect { it.key } - }, - (Query.GreaterThanEqualsProperty): { Query.GreaterThanEqualsProperty gt, PersistentProperty property, Closure function = null, boolean onValue = false -> - def name = gt.property - def other = gt.otherProperty - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) >= it.value[other] }.collect { it.key } - }, - (Query.LessThanProperty): { Query.LessThanProperty gt, PersistentProperty property -> - def name = gt.property - def other = gt.otherProperty - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) < it.value[other] }.collect { it.key } - }, - (Query.LessThanEqualsProperty): { Query.LessThanEqualsProperty gt, PersistentProperty property -> - def name = gt.property - def other = gt.otherProperty - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) <= it.value[other] }.collect { it.key } - }, - (Query.EqualsProperty): { Query.EqualsProperty gt, PersistentProperty property -> - def name = gt.property - def other = gt.otherProperty - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) == it.value[other] }.collect { it.key } - }, - (Query.NotEqualsProperty): { Query.NotEqualsProperty gt, PersistentProperty property -> - def name = gt.property - def other = gt.otherProperty - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) != it.value[other] }.collect { it.key } - }, - (Query.SizeEquals): { Query.SizeEquals se, PersistentProperty property -> - def allEntities = datastore[family] - final value = subqueryIfNecessary(se) - queryAssociationList(allEntities, property) { it.size() == value } - }, - (Query.SizeNotEquals): { Query.SizeNotEquals se, PersistentProperty property -> - def allEntities = datastore[family] - final value = subqueryIfNecessary(se) - queryAssociationList(allEntities, property) { it.size() != value } - }, - (Query.SizeGreaterThan): { Query.SizeGreaterThan se, PersistentProperty property -> - def allEntities = datastore[family] - final value = subqueryIfNecessary(se) - queryAssociationList(allEntities, property) { it.size() > value } - }, - (Query.SizeGreaterThanEquals): { Query.SizeGreaterThanEquals se, PersistentProperty property -> - def allEntities = datastore[family] - final value = subqueryIfNecessary(se) - queryAssociationList(allEntities, property) { it.size() >= value } - }, - (Query.SizeLessThan): { Query.SizeLessThan se, PersistentProperty property -> - def allEntities = datastore[family] - final value = subqueryIfNecessary(se) - queryAssociationList(allEntities, property) { it.size() < value } - }, - (Query.SizeLessThanEquals): { Query.SizeLessThanEquals se, PersistentProperty property -> - def allEntities = datastore[family] - final value = subqueryIfNecessary(se) - queryAssociationList(allEntities, property) { it.size() <= value } - }, - (Query.GreaterThanEquals): { Query.GreaterThanEquals gt, PersistentProperty property -> - def name = gt.property - final value = subqueryIfNecessary(gt) - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) >= value }.collect { it.key } - }, - (Query.LessThan): { Query.LessThan lt, PersistentProperty property -> - def name = lt.property - final value = subqueryIfNecessary(lt) - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) < value }.collect { it.key } - }, - (Query.LessThanEquals): { Query.LessThanEquals lte, PersistentProperty property -> - def name = lte.property - final value = subqueryIfNecessary(lte) - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) <= value }.collect { it.key } - } - ] - - protected def subqueryIfNecessary(Query.PropertyCriterion pc, boolean uniqueResult = true) { - def value = pc.value - if (value instanceof QueryableCriteria) { - QueryableCriteria criteria = value - if (uniqueResult) { - value = criteria.find() - } - else { - value = criteria.list() - } - } - - return value - } - - /** - * If the property name refers to an embedded property like 'foo.startDate', then we need - * resolve the value of startDate by walking through the key list. - * - * @param propertyName the full property name - * @return - */ - protected resolveIfEmbedded(propertyName, obj) { - if( propertyName.contains('.') ) { - def (embeddedProperty, nestedProperty) = propertyName.tokenize('.') - obj?."${embeddedProperty}"?."${nestedProperty}" - } - else { - obj?."${propertyName}" - } - } - - protected List executeLikeWithRegex(SimpleMapEntityPersister entityPersister, PersistentProperty property, regexFormat) { - def indexer = entityPersister.getPropertyIndexer(property) - - def root = indexer.indexRoot - def pattern = Pattern.compile("${root}:${regexFormat}", Pattern.CASE_INSENSITIVE) - def matchingIndices = entityPersister.indices.findAll { key, value -> - pattern.matcher(key).matches() - } - - Set result = [] - for (indexed in matchingIndices) { - result.addAll(indexed.value) - } - - return result.toList() - } - - private ArrayList negateResults(List results) { - def entityMap = datastore[family] - def allIds = new ArrayList(entityMap.keySet()) - allIds.removeAll(results) - return allIds - } - - Map executeSubQuery(criteria, criteriaList) { - - def finalIdentifiers = executeSubQueryInternal(criteria, criteriaList) - - Map queryResult = [:] - populateQueryResult(finalIdentifiers, queryResult) - return queryResult - } - - Collection executeSubQueryInternal(criteria, criteriaList) { - SimpleMapResultList resultList = new SimpleMapResultList(this) - for (Query.Criterion criterion in criteriaList) { - if (criterion instanceof Query.Junction) { - resultList.results << executeSubQueryInternal(criterion, criterion.criteria) - } - else { - PersistentProperty property = getValidProperty(criterion) - - if ((property instanceof Custom) && (criterion instanceof Query.PropertyCriterion)) { - CustomTypeMarshaller customTypeMarshaller = ((Custom) property).getCustomTypeMarshaller() - customTypeMarshaller.query(property, criterion, resultList) - continue - } - else { - def handler = handlers[criterion.getClass()] - - def results = handler?.call(criterion, property) ?: [] - resultList.results << results - } - } - } - return applyJunctionToResults(criteria,resultList.results) - } - - private List applyJunctionToResults(Query.Junction criteria, List resultList) { - def finalIdentifiers = [] - if (!resultList.isEmpty()) { - if (resultList.size() > 1) { - if (criteria instanceof Query.Conjunction) { - def total = resultList.size() - finalIdentifiers = resultList[0] - for (num in 1.. cacheAdapterRepository) { - super(datastore, mappingContext, publisher, cacheAdapterRepository); - this.delayMillis = delayMillis; - } - - @Override - protected void postFlush(boolean hasUpdates) { - if (hasUpdates) { - pause(); - } - } - - private void pause() { - try { Thread.sleep(delayMillis); } catch (InterruptedException e) { /* ignored */ } - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/SimpleDBDatastore.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/SimpleDBDatastore.java deleted file mode 100644 index 7b6c03674..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/SimpleDBDatastore.java +++ /dev/null @@ -1,226 +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.mapping.simpledb; - -import static org.grails.datastore.mapping.config.utils.ConfigUtils.read; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; -import org.grails.datastore.mapping.core.AbstractDatastore; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.model.types.OneToMany; -import org.grails.datastore.mapping.simpledb.config.SimpleDBMappingContext; -import org.grails.datastore.mapping.simpledb.engine.AssociationKey; -import org.grails.datastore.mapping.simpledb.engine.SimpleDBAssociationInfo; -import org.grails.datastore.mapping.simpledb.engine.SimpleDBDomainResolver; -import org.grails.datastore.mapping.simpledb.engine.SimpleDBDomainResolverFactory; -import org.grails.datastore.mapping.simpledb.engine.SimpleDBIdGenerator; -import org.grails.datastore.mapping.simpledb.engine.SimpleDBIdGeneratorFactory; -import org.grails.datastore.mapping.simpledb.engine.SimpleDBNativeItem; -import org.grails.datastore.mapping.simpledb.model.types.SimpleDBTypeConverterRegistrar; -import org.grails.datastore.mapping.simpledb.util.DelayAfterWriteSimpleDBTemplateDecorator; -import org.grails.datastore.mapping.simpledb.util.SimpleDBTemplate; -import org.grails.datastore.mapping.simpledb.util.SimpleDBTemplateImpl; -import org.grails.datastore.mapping.simpledb.util.SimpleDBUtil; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.convert.converter.ConverterRegistry; - -/** - * A Datastore implementation for the AWS SimpleDB document store. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -public class SimpleDBDatastore extends AbstractDatastore implements InitializingBean, MappingContext.Listener { - - public static final String SECRET_KEY = "secretKey"; - public static final String ACCESS_KEY = "accessKey"; - public static final String ENDPOINT = "endpoint"; //optional, if specified will be used to explicitly set AWS endpoint. See http://docs.aws.amazon.com/general/latest/gr/rande.html#sdb_region - public static final String DOMAIN_PREFIX_KEY = "domainNamePrefix"; - public static final String DELAY_AFTER_WRITES_MS = "delayAfterWritesMS"; //used for testing - to fight eventual consistency if this flag value is 'true' it will add specified pause after writes - -// private Map simpleDBTemplates = new ConcurrentHashMap(); - private SimpleDBTemplate simpleDBTemplate; //currently there is no need to create template per entity, we can share same instance - protected Map associationInfoMap = new HashMap(); //contains entries only for those associations that need a dedicated domain - protected Map entityDomainResolverMap = new HashMap(); - protected Map entityIdGeneratorMap = new HashMap(); - - private String domainNamePrefix; - - public SimpleDBDatastore() { - this(new SimpleDBMappingContext(), Collections.emptyMap(), null, null); - } - - /** - * Constructs a SimpleDBDatastore using the given MappingContext and connection details map. - * - * @param mappingContext The SimpleDBMappingContext - * @param connectionDetails The connection details containing the {@link #ACCESS_KEY} and {@link #SECRET_KEY} settings - */ - public SimpleDBDatastore(MappingContext mappingContext, - Map connectionDetails, ConfigurableApplicationContext ctx, TPCacheAdapterRepository adapterRepository) { - super(mappingContext, connectionDetails, ctx, adapterRepository); - - if (mappingContext != null) { - mappingContext.addMappingContextListener(this); - } - - initializeConverters(mappingContext); - - domainNamePrefix = read(String.class, DOMAIN_PREFIX_KEY, connectionDetails, null); - } - - public SimpleDBDatastore(MappingContext mappingContext, Map connectionDetails) { - this(mappingContext, connectionDetails, null, null); - } - - public SimpleDBDatastore(MappingContext mappingContext) { - this(mappingContext, Collections.emptyMap(), null, null); - } - - public SimpleDBTemplate getSimpleDBTemplate(PersistentEntity entity) { -// return simpleDBTemplates.get(entity); - return simpleDBTemplate; - } - - public SimpleDBTemplate getSimpleDBTemplate() { - return simpleDBTemplate; - } - - @Override - protected Session createSession(Map connDetails) { - String delayAfterWrite = read(String.class, DELAY_AFTER_WRITES_MS, connectionDetails, null); - - if (delayAfterWrite != null && !"".equals(delayAfterWrite)) { - return new DelayAfterWriteSimpleDBSession(this, getMappingContext(), getApplicationEventPublisher(), Integer.parseInt(delayAfterWrite), cacheAdapterRepository); - } - return new SimpleDBSession(this, getMappingContext(), getApplicationEventPublisher(), cacheAdapterRepository); - } - - public void afterPropertiesSet() throws Exception { - for (PersistentEntity entity : mappingContext.getPersistentEntities()) { - // Only create SimpleDB templates for entities that are mapped with SimpleDB - if (!entity.isExternal()) { - createSimpleDBTemplate(entity); - } - } - } - - protected void createSimpleDBTemplate(PersistentEntity entity) { - if (simpleDBTemplate != null) { - return; - } - - String accessKey = read(String.class, ACCESS_KEY, connectionDetails, null); - String secretKey = read(String.class, SECRET_KEY, connectionDetails, null); - String delayAfterWrite = read(String.class, DELAY_AFTER_WRITES_MS, connectionDetails, null); - String endpoint = read(String.class, ENDPOINT, connectionDetails, null); - - simpleDBTemplate = new SimpleDBTemplateImpl(accessKey, secretKey, endpoint); - if (delayAfterWrite != null && !"".equals(delayAfterWrite)) { - simpleDBTemplate = new DelayAfterWriteSimpleDBTemplateDecorator(simpleDBTemplate, Integer.parseInt(delayAfterWrite)); - } - } - - /** - * If specified, returns domain name prefix so that same AWS account can be used for more than one environment (DEV/TEST/PROD etc). - * @return null if name was not specified in the configuration - */ - public String getDomainNamePrefix() { - return domainNamePrefix; - } - - public void persistentEntityAdded(PersistentEntity entity) { - createSimpleDBTemplate(entity); - analyzeAssociations(entity); - createEntityDomainResolver(entity); - createEntityIdGenerator(entity); - } - - /** - * If the specified association has a dedicated AWS domains, returns info for that association, - * otherwise returns null. - */ - public SimpleDBAssociationInfo getAssociationInfo(Association association) { - return associationInfoMap.get(generateAssociationKey(association)); - } - - /** - * Returns domain resolver for the specified entity. - * @param entity - * @return - */ - public SimpleDBDomainResolver getEntityDomainResolver(PersistentEntity entity) { - return entityDomainResolverMap.get(entity); - } - - /** - * Returns id generator for the specified entity. - * @param entity - * @return - */ - public SimpleDBIdGenerator getEntityIdGenerator(PersistentEntity entity) { - return entityIdGeneratorMap.get(entity); - } - - protected void createEntityDomainResolver(PersistentEntity entity) { - SimpleDBDomainResolverFactory resolverFactory = new SimpleDBDomainResolverFactory(); - SimpleDBDomainResolver domainResolver = resolverFactory.buildResolver(entity, this); - - entityDomainResolverMap.put(entity, domainResolver); - } - - protected void createEntityIdGenerator(PersistentEntity entity) { - SimpleDBIdGeneratorFactory factory = new SimpleDBIdGeneratorFactory(); - SimpleDBIdGenerator generator = factory.buildIdGenerator(entity, this); - - entityIdGeneratorMap.put(entity, generator); - } - - @Override - protected void initializeConverters(MappingContext mappingContext) { - final ConverterRegistry conversionService = mappingContext.getConverterRegistry(); - new SimpleDBTypeConverterRegistrar().register(conversionService); - } - - /** - * Analyzes associations and for those associations that need to be stored - * in a dedicated AWS domain, creates info object with details for that association. - */ - protected void analyzeAssociations(PersistentEntity entity) { - for (Association association : entity.getAssociations()) { - if (association instanceof OneToMany && !association.isBidirectional()) { - String associationDomainName = generateAssociationDomainName(association); - associationInfoMap.put(generateAssociationKey(association), new SimpleDBAssociationInfo(associationDomainName)); - } - } - } - - protected AssociationKey generateAssociationKey(Association association) { - return new AssociationKey(association.getOwner(), association.getName()); - } - - protected String generateAssociationDomainName(Association association) { - String ownerDomainName = SimpleDBUtil.getMappedDomainName(association.getOwner()); - return SimpleDBUtil.getPrefixedDomainName(domainNamePrefix, ownerDomainName.toUpperCase()+"_"+association.getName().toUpperCase()); - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/SimpleDBSession.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/SimpleDBSession.java deleted file mode 100644 index caac92701..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/SimpleDBSession.java +++ /dev/null @@ -1,82 +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.mapping.simpledb; - -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; -import org.springframework.context.ApplicationEventPublisher; -import org.grails.datastore.mapping.core.AbstractSession; -import org.grails.datastore.mapping.engine.Persister; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.simpledb.engine.SimpleDBEntityPersister; -import org.grails.datastore.mapping.simpledb.query.SimpleDBQuery; -import org.grails.datastore.mapping.simpledb.util.SimpleDBTemplate; -import org.grails.datastore.mapping.transactions.SessionOnlyTransaction; -import org.grails.datastore.mapping.transactions.Transaction; - -/** - * A {@link org.grails.datastore.mapping.core.Session} implementation - * for the AWS SimpleDB store. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class SimpleDBSession extends AbstractSession { - - SimpleDBDatastore simpleDBDatastore; - - public SimpleDBSession(SimpleDBDatastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher, TPCacheAdapterRepository cacheAdapterRepository) { - super(datastore, mappingContext, publisher, cacheAdapterRepository); - this.simpleDBDatastore = datastore; - } - - @Override - public SimpleDBQuery createQuery(Class type) { - return (SimpleDBQuery) super.createQuery(type); - } - -/* @Override - @SuppressWarnings({"rawtypes", "unchecked"}) - protected void flushPendingInserts(Map> inserts) { - //todo - optimize multiple inserts using batch put (make the number of threshold objects configurable) - for (final PersistentEntity entity : inserts.keySet()) { - final SimpleDBTemplate template = getSimpleDBTemplate(entity.isRoot() ? entity : entity.getRootEntity()); - - throw new RuntimeException("not implemented yet"); -// template.persist(null); //todo - :) - } - } - */ - - public Object getNativeInterface() { - return null; //todo - } - - @Override - protected Persister createPersister(Class cls, MappingContext mappingContext) { - final PersistentEntity entity = mappingContext.getPersistentEntity(cls.getName()); - return entity == null ? null : new SimpleDBEntityPersister(mappingContext, entity, this, publisher, cacheAdapterRepository); - } - - @Override - protected Transaction beginTransactionInternal() { - return new SessionOnlyTransaction(null, this); - } - - public SimpleDBTemplate getSimpleDBTemplate() { - return simpleDBDatastore.getSimpleDBTemplate(); - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/config/GormSimpleDBMappingFactory.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/config/GormSimpleDBMappingFactory.java deleted file mode 100644 index a37c4216d..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/config/GormSimpleDBMappingFactory.java +++ /dev/null @@ -1,59 +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.mapping.simpledb.config; - -import groovy.lang.Closure; - -import org.grails.datastore.mapping.config.groovy.MappingConfigurationBuilder; -import org.grails.datastore.mapping.keyvalue.mapping.config.Family; -import org.grails.datastore.mapping.keyvalue.mapping.config.GormKeyValueMappingFactory; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; - -/** - * MappingFactory for SimpleDB. - * - * @author Roman Stepanenko - * @since 0.l - */ -@SuppressWarnings({ "unchecked", "rawtypes" }) -public class GormSimpleDBMappingFactory extends GormKeyValueMappingFactory { - - public GormSimpleDBMappingFactory() { - super(null); - } - - @Override - public Family createMappedForm(PersistentEntity entity) { - ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass()); - - Closure value = cpf.getStaticPropertyValue(GormProperties.MAPPING, Closure.class); - if (value == null) { - return new SimpleDBDomainClassMappedForm(entity.getName()); - } - - Family family = new SimpleDBDomainClassMappedForm(); - MappingConfigurationBuilder builder = new MappingConfigurationBuilder(family, getPropertyMappedFormType()); - - builder.evaluate(value); - value = cpf.getStaticPropertyValue(GormProperties.CONSTRAINTS, Closure.class); - if (value != null) { - builder.evaluate(value); - } - entityToPropertyMap.put(entity, builder.getProperties()); - return family; - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/config/SimpleDBDomainClassMappedForm.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/config/SimpleDBDomainClassMappedForm.java deleted file mode 100644 index d19818d86..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/config/SimpleDBDomainClassMappedForm.java +++ /dev/null @@ -1,110 +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.mapping.simpledb.config; - -import java.util.Map; - -import org.grails.datastore.mapping.keyvalue.mapping.config.Family; -import org.grails.datastore.mapping.simpledb.util.SimpleDBConst; - -/** - * Mapping for - * {@link org.grails.datastore.mapping.simpledb.config.SimpleDBPersistentEntity} - * with the SimpleDB specific properties so that the following can be used in - * the mapping: - * - *
    - *      static mapping = {
    - *          domain 'Person'
    - *          sharding enabled:false, shards:3 //optional, needed only if sharding is used for this domain class
    - *          id_generator type:'hilo', maxLo:100  //optional, if not specified UUID is used
    - *      }
    - * 
    - * @author Roman Stepanenko - * @since 0.1 - */ -public class SimpleDBDomainClassMappedForm extends Family { - - protected String domain; - protected Map sharding; //sharding configuration - protected Map id_generator; //id generation configuration - protected boolean shardingEnabled; - - public SimpleDBDomainClassMappedForm() { - determineShardingConfiguration(); - } - - public SimpleDBDomainClassMappedForm(String domain) { - this.domain = domain; - determineShardingConfiguration(); - } - - public SimpleDBDomainClassMappedForm(String keyspace, String domain) { - super(keyspace, domain); - this.domain = domain; - determineShardingConfiguration(); - } - - public String getDomain() { - return domain; - } - - public void setDomain(String domain) { - this.domain = domain; - super.setFamily(domain); - } - - public boolean isShardingEnabled() { - return shardingEnabled; - } - - @Override - public void setFamily(String family) { - super.setFamily(family); - domain = family; - } - - public Map getId_generator() { - return id_generator; - } - - public void setId_generator(Map id_generator) { - this.id_generator = id_generator; - } - - public Map getSharding() { - return sharding; - } - - public void setSharding(Map sharding) { - this.sharding = sharding; - determineShardingConfiguration(); - } - - protected void determineShardingConfiguration() { - if (sharding != null) { - shardingEnabled = Boolean.TRUE.equals(sharding.get(SimpleDBConst.PROP_SHARDING_ENABLED)); - } - } - - @Override - public String toString() { - return "SimpleDBDomainClassMappedForm{" + - "domain='" + domain + '\'' + - ", shardingEnabled=" + shardingEnabled + - ", sharding=" + sharding + - '}'; - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/config/SimpleDBMappingContext.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/config/SimpleDBMappingContext.java deleted file mode 100644 index dcc53c1d7..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/config/SimpleDBMappingContext.java +++ /dev/null @@ -1,65 +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.mapping.simpledb.config; - -import org.grails.datastore.mapping.document.config.Attribute; -import org.grails.datastore.mapping.document.config.Collection; -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; - -/** - * Models a {@link org.grails.datastore.mapping.model.MappingContext} for SimpleDB. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class SimpleDBMappingContext extends AbstractMappingContext { - - protected MappingConfigurationStrategy syntaxStrategy; - MappingFactory mappingFactory; - - public SimpleDBMappingContext() { - mappingFactory = createMappingFactory(); - syntaxStrategy = new GormMappingConfigurationStrategy(mappingFactory); - } - - protected MappingFactory createMappingFactory() { - return new GormSimpleDBMappingFactory(); - } - - @Override - protected PersistentEntity createPersistentEntity(Class javaClass) { - SimpleDBPersistentEntity simpleDBPersistentEntity = new SimpleDBPersistentEntity(javaClass, this); - - //initialize mapping form for SimpleDBPersistentEntity here - otherwise there are some - //problems with the initialization sequence when some properties have OneToOne - //(FindOrCreateWhereSpec, FindOrSaveWhereSpec, FindOrSaveWhereSpec was failing) - mappingFactory.createMappedForm(simpleDBPersistentEntity); - - return simpleDBPersistentEntity; - } - - public MappingConfigurationStrategy getMappingSyntaxStrategy() { - return syntaxStrategy; - } - - public MappingFactory getMappingFactory() { - return mappingFactory; - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/config/SimpleDBPersistentEntity.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/config/SimpleDBPersistentEntity.java deleted file mode 100644 index 97f5de6ba..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/config/SimpleDBPersistentEntity.java +++ /dev/null @@ -1,52 +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.mapping.simpledb.config; - -import org.grails.datastore.mapping.model.AbstractClassMapping; -import org.grails.datastore.mapping.model.AbstractPersistentEntity; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Models a SimpleDB-mapped entity. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class SimpleDBPersistentEntity extends AbstractPersistentEntity { - - public SimpleDBPersistentEntity(Class javaClass, MappingContext context) { - super(javaClass, context); - } - - @SuppressWarnings("unchecked") - @Override - public ClassMapping getMapping() { - return new SimpleDBClassMapping(this, context); - } - - public class SimpleDBClassMapping extends AbstractClassMapping { - - public SimpleDBClassMapping(PersistentEntity entity, MappingContext context) { - super(entity, context); - } - - @Override - public SimpleDBDomainClassMappedForm getMappedForm() { - return (SimpleDBDomainClassMappedForm) context.getMappingFactory().createMappedForm(SimpleDBPersistentEntity.this); - } - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/AbstractSimpleDBDomainResolver.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/AbstractSimpleDBDomainResolver.java deleted file mode 100644 index bed3ee22f..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/AbstractSimpleDBDomainResolver.java +++ /dev/null @@ -1,39 +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.mapping.simpledb.engine; - -import org.grails.datastore.mapping.simpledb.util.SimpleDBUtil; - -/** - * @author Roman Stepanenko - */ -public abstract class AbstractSimpleDBDomainResolver implements SimpleDBDomainResolver { - - protected String entityFamily; - protected String domainNamePrefix; - - public AbstractSimpleDBDomainResolver(String entityFamily, String domainNamePrefix) { - this.domainNamePrefix = domainNamePrefix; - this.entityFamily = SimpleDBUtil.getPrefixedDomainName(domainNamePrefix, entityFamily); - } - - /** - * Helper getter for subclasses. - * @return entityFamily - */ - protected String getEntityFamily() { - return entityFamily; - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/AssociationKey.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/AssociationKey.java deleted file mode 100644 index 85042c027..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/AssociationKey.java +++ /dev/null @@ -1,62 +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.mapping.simpledb.engine; - -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Simple key object for looking up Associations from a map. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class AssociationKey { - - private PersistentEntity owner; - private String name; - - public AssociationKey(PersistentEntity owner, String name) { - this.owner = owner; - this.name = name; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - AssociationKey that = (AssociationKey) o; - - if (name != null ? !name.equals(that.name) : that.name != null) { - return false; - } - if (owner != null ? !owner.equals(that.owner) : that.owner != null) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result = owner != null ? owner.hashCode() : 0; - result = 31 * result + (name != null ? name.hashCode() : 0); - return result; - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/ConstSimpleDBDomainResolver.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/ConstSimpleDBDomainResolver.java deleted file mode 100644 index e58bdc89e..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/ConstSimpleDBDomainResolver.java +++ /dev/null @@ -1,42 +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.mapping.simpledb.engine; - -import java.util.LinkedList; -import java.util.List; - -/** - * An implementation of the domain resolver which assumes there is no sharding - - * i.e. always the same domain name for all the primary keys (for the same type - * of {@link org.grails.datastore.mapping.model.PersistentEntity} - */ -public class ConstSimpleDBDomainResolver extends AbstractSimpleDBDomainResolver { - - private List domains; - - public ConstSimpleDBDomainResolver(String entityFamily, String domainNamePrefix) { - super(entityFamily, domainNamePrefix); //parent contains the logic for figuring out the final entityFamily - domains = new LinkedList(); - domains.add(getEntityFamily()); // without sharding there is just one domain - } - - public String resolveDomain(String id) { - return entityFamily; // without sharding it is always the same one per PersistentEntity - } - - public List getAllDomainsForEntity() { - return domains; - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBAssociationIndexer.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBAssociationIndexer.java deleted file mode 100644 index a3d6232ea..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBAssociationIndexer.java +++ /dev/null @@ -1,115 +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.mapping.simpledb.engine; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.simpledb.SimpleDBDatastore; -import org.grails.datastore.mapping.simpledb.SimpleDBSession; -import org.grails.datastore.mapping.simpledb.util.SimpleDBUtil; - -import com.amazonaws.services.simpledb.model.Item; -import com.amazonaws.services.simpledb.model.ReplaceableAttribute; - -/** - * An {@link org.grails.datastore.mapping.engine.AssociationIndexer} implementation for the SimpleDB store. - * - * @author Roman Stepanenko - * @since 0.1 - */ -@SuppressWarnings("rawtypes") -public class SimpleDBAssociationIndexer implements AssociationIndexer { - public static final String FOREIGN_KEY_ATTRIBUTE_NAME = "FK"; - - private Association association; - private SimpleDBSession session; - - public SimpleDBAssociationIndexer(SimpleDBNativeItem nativeEntry, Association association, SimpleDBSession session) { - this.association = association; - this.session = session; - } - - public PersistentEntity getIndexedEntity() { - return association.getAssociatedEntity(); - } - - public void preIndex(Object primaryKey, List foreignKeys) { - // handled by index below. - } - - public void index(Object primaryKey, List foreignKeys) { -// System.out.println("INDEX: index for id: "+primaryKey+", keys: "+foreignKeys+". entry: "+nativeEntry+", association: "+association); - if (association.isBidirectional()) { //we use additional table only for unidirectional - return; - } - - SimpleDBAssociationInfo associationInfo = getDatastore().getAssociationInfo(association); - //current implementation can not handle more than 255 ids because we store them in a multi-value attribute - //and key this collection by the primary key of the entity - List attributes = new LinkedList(); - for (Object foreignKey : foreignKeys) { - attributes.add(new ReplaceableAttribute(FOREIGN_KEY_ATTRIBUTE_NAME, foreignKey.toString(), Boolean.TRUE)); - } - session.getSimpleDBTemplate().putAttributes(associationInfo.getDomainName(), primaryKey.toString(), attributes); - } - - public List query(Object primaryKey) { -// System.out.println("INDEX: query for id: "+primaryKey+". entry: "+nativeEntry+", association: "+association); - if (!association.isBidirectional()) { //we use additional table only for unidirectional - SimpleDBAssociationInfo associationInfo = getDatastore().getAssociationInfo(association); - String query = "SELECT * FROM "+ SimpleDBUtil.quoteName(associationInfo.getDomainName())+" WHERE itemName() = " + SimpleDBUtil.quoteValue(primaryKey.toString())+" LIMIT 2500"; - List items = session.getSimpleDBTemplate().query(query, Integer.MAX_VALUE); - if (items.isEmpty()) { - return Collections.EMPTY_LIST; - } else if (items.size() > 1) { - throw new IllegalArgumentException("current implementation stores all foreign keys in a single item, if more than one item is returned it is a data corruption"); - } else { - return SimpleDBUtil.collectAttributeValues(items.get(0), FOREIGN_KEY_ATTRIBUTE_NAME); - } - } - - //for bidirectional onToMany association the use the other entity to refer to this guy's PK via FK - SimpleDBDomainResolver domainResolver = getDatastore().getEntityDomainResolver(association.getAssociatedEntity()); - - //todo - implement for sharding (must look in all shards) - String query = "SELECT itemName() FROM "+ SimpleDBUtil.quoteName(domainResolver.getAllDomainsForEntity().get(0)) + - " WHERE " + SimpleDBUtil.quoteName(association.getInverseSide().getName()) + - " = " + SimpleDBUtil.quoteValue(primaryKey.toString()) + " LIMIT 2500"; - - List items = session.getSimpleDBTemplate().query(query, Integer.MAX_VALUE); - if (items.isEmpty()) { - return Collections.EMPTY_LIST; - } - return SimpleDBUtil.collectItemNames(items); - } - - private SimpleDBDatastore getDatastore() { - return ((SimpleDBDatastore) session.getDatastore()); - } - - public void index(Object primaryKey, Object foreignKey) { -// System.out.println("INDEX: index for id: "+primaryKey+", KEY: "+foreignKey+". entry: "+nativeEntry+", association: "+association); - if (association.isBidirectional()) { //we use additional table only for unidirectional - return; - } - - throw new RuntimeException("not implemented: index(Object primaryKey, Object foreignKey)"); - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBAssociationInfo.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBAssociationInfo.java deleted file mode 100644 index e3047a44d..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBAssociationInfo.java +++ /dev/null @@ -1,39 +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.mapping.simpledb.engine; - -/** - * For associations that are stored in dedicated domains (unidirectional onToMany), contains - * domain name for each association. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class SimpleDBAssociationInfo { - - private String domainName; - - public SimpleDBAssociationInfo(String domainName) { - this.domainName = domainName; - } - - public String getDomainName() { - return domainName; - } - - public void setDomainName(String domainName) { - this.domainName = domainName; - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBDomainResolver.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBDomainResolver.java deleted file mode 100644 index 37b694f8d..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBDomainResolver.java +++ /dev/null @@ -1,46 +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.mapping.simpledb.engine; - -import java.util.List; - -/** - * Encapsulates logic of determining SimpleDB domain name based specific a - * primary key, assuming that this instance of the resolver is used only for one - * {@link org.grails.datastore.mapping.model.PersistentEntity}, which - * was provided during construction time of this instance. This class is used to - * enable sharding and to provide various sharding hashing function algorithms. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public interface SimpleDBDomainResolver { - - /** - * Returns domain name for the specified primary key value. - * - * @param id - * @return - */ - String resolveDomain(String id); - - /** - * Returns all domain names for this type of entity. Without sharding this - * list contains always one element. - * - * @return - */ - List getAllDomainsForEntity(); -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBDomainResolverFactory.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBDomainResolverFactory.java deleted file mode 100644 index c6bf7e030..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBDomainResolverFactory.java +++ /dev/null @@ -1,45 +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.mapping.simpledb.engine; - -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.simpledb.SimpleDBDatastore; -import org.grails.datastore.mapping.simpledb.config.SimpleDBDomainClassMappedForm; -import org.grails.datastore.mapping.simpledb.util.SimpleDBUtil; - -/** - * Encapsulates logic of building appropriately configured SimpleDBDomainResolver instance. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class SimpleDBDomainResolverFactory { - - public SimpleDBDomainResolver buildResolver(PersistentEntity entity, SimpleDBDatastore simpleDBDatastore) { - String entityFamily = SimpleDBUtil.getMappedDomainName(entity); - - @SuppressWarnings("unchecked") - ClassMapping classMapping = entity.getMapping(); - SimpleDBDomainClassMappedForm mappedForm = classMapping.getMappedForm(); - - if (mappedForm.isShardingEnabled()) { - throw new RuntimeException("sharding is not implemented yet"); - } - - return new ConstSimpleDBDomainResolver(entityFamily, simpleDBDatastore.getDomainNamePrefix()); - } - -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBEntityPersister.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBEntityPersister.java deleted file mode 100644 index 70b41c43f..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBEntityPersister.java +++ /dev/null @@ -1,315 +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.mapping.simpledb.engine; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; -import org.grails.datastore.mapping.engine.AssociationIndexer; -import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.NativeEntryEntityPersister; -import org.grails.datastore.mapping.engine.PropertyValueIndexer; -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.Association; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.simpledb.SimpleDBDatastore; -import org.grails.datastore.mapping.simpledb.SimpleDBSession; -import org.grails.datastore.mapping.simpledb.model.types.SimpleDBTypeConverterRegistrar; -import org.grails.datastore.mapping.simpledb.query.SimpleDBQuery; -import org.grails.datastore.mapping.simpledb.util.SimpleDBConverterUtil; -import org.grails.datastore.mapping.simpledb.util.SimpleDBTemplate; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.dao.DataAccessException; - -import com.amazonaws.services.simpledb.model.Attribute; -import com.amazonaws.services.simpledb.model.Item; -import com.amazonaws.services.simpledb.model.ReplaceableAttribute; - -/** - * A {@link org.grails.datastore.mapping.engine.EntityPersister} implementation for the SimpleDB store. - * - * @author Roman Stepanenko based on Graeme Rocher code for MongoDb and Redis - * @since 0.1 - */ -public class SimpleDBEntityPersister extends NativeEntryEntityPersister { - - protected SimpleDBTemplate simpleDBTemplate; - protected String entityFamily; - protected SimpleDBDomainResolver domainResolver; - protected SimpleDBIdGenerator idGenerator; - protected boolean hasNumericalIdentifier = false; - protected boolean hasStringIdentifier = false; - - public SimpleDBEntityPersister(MappingContext mappingContext, PersistentEntity entity, - SimpleDBSession simpleDBSession, ApplicationEventPublisher publisher, TPCacheAdapterRepository cacheAdapterRepository) { - super(mappingContext, entity, simpleDBSession, publisher, cacheAdapterRepository); - SimpleDBDatastore datastore = (SimpleDBDatastore) simpleDBSession.getDatastore(); - simpleDBTemplate = datastore.getSimpleDBTemplate(entity); - - hasNumericalIdentifier = Long.class.isAssignableFrom(entity.getIdentity().getType()); - hasStringIdentifier = String.class.isAssignableFrom(entity.getIdentity().getType()); - domainResolver = datastore.getEntityDomainResolver(entity); - idGenerator = datastore.getEntityIdGenerator(entity); - } - - public Query createQuery() { - return new SimpleDBQuery(getSession(), getPersistentEntity(), domainResolver, this, simpleDBTemplate); - } - - public SimpleDBDomainResolver getDomainResolver() { - return domainResolver; - } - - @Override - protected boolean doesRequirePropertyIndexing() { - return false; - } - - @Override - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected List retrieveAllEntities(PersistentEntity persistentEntity, - Iterable keys) { - - Query query = session.createQuery(persistentEntity.getJavaClass()); - - if (keys instanceof List) { - if (((List)keys).isEmpty()) { - return Collections.EMPTY_LIST; - } - query.in(persistentEntity.getIdentity().getName(), (List)keys); - } - else { - List keyList = new ArrayList(); - for (Serializable key : keys) { - keyList.add(key); - } - if (keyList.isEmpty()) { - return Collections.EMPTY_LIST; - } - query.in(persistentEntity.getIdentity().getName(), keyList); - } - - List entityResults = new ArrayList(); - Iterator keyIterator = keys.iterator(); - Iterator listIterator = query.list().iterator(); - while (keyIterator.hasNext() && listIterator.hasNext()) { - Serializable key = keyIterator.next(); - Object next = listIterator.next(); - if (next instanceof SimpleDBNativeItem) { - entityResults.add(createObjectFromNativeEntry(getPersistentEntity(), key, (SimpleDBNativeItem)next)); - } - else { - entityResults.add(next); - } - } - - return entityResults; - } - - @Override - protected List retrieveAllEntities(PersistentEntity persistentEntity, Serializable[] keys) { - return retrieveAllEntities(persistentEntity, Arrays.asList(keys)); - } - - @Override - public String getEntityFamily() { - return entityFamily; - } - - @Override - protected void deleteEntry(String family, Object key, Object entry) { - String domain = domainResolver.resolveDomain((String)key); - simpleDBTemplate.deleteItem(domain, (String) key); - } - - @Override - protected Object generateIdentifier(final PersistentEntity persistentEntity, - final SimpleDBNativeItem nativeEntry) { - return idGenerator.generateIdentifier(persistentEntity, nativeEntry); - } - - @SuppressWarnings("rawtypes") - @Override - public PropertyValueIndexer getPropertyIndexer(PersistentProperty property) { - // We don't need to implement this for SimpleDB since SimpleDB automatically creates indexes for us - return null; - } - - @Override - @SuppressWarnings("rawtypes") - public AssociationIndexer getAssociationIndexer(SimpleDBNativeItem nativeEntry, Association association) { - return new SimpleDBAssociationIndexer(nativeEntry, association, (SimpleDBSession) session); - } - - @Override - protected SimpleDBNativeItem createNewEntry(String family) { - return new SimpleDBNativeItem(); - } - - @Override - protected Object getEntryValue(SimpleDBNativeItem nativeEntry, String property) { - return nativeEntry.get(property); - } - - @Override - protected void setEntryValue(SimpleDBNativeItem nativeEntry, String key, Object value) { - if (!getMappingContext().isPersistentEntity(value)) { - String stringValue = SimpleDBConverterUtil.convertToString(value, getMappingContext()); - - nativeEntry.put(key, stringValue); - } - } - - @Override - protected EntityAccess createEntityAccess(PersistentEntity persistentEntity, Object obj, SimpleDBNativeItem nativeEntry) { - final NativeEntryModifyingEntityAccess ea = new SimpleDBNativeEntryModifyingEntityAccess(persistentEntity, obj); - ea.setNativeEntry(nativeEntry); - return ea; - } - - @Override - protected SimpleDBNativeItem retrieveEntry(final PersistentEntity persistentEntity, - String family, final Serializable key) { - String domain = domainResolver.resolveDomain((String)key); - Item item = simpleDBTemplate.get(domain, (String) key); - return item == null ? null : new SimpleDBNativeItem(item); - } - - @Override - protected Object storeEntry(final PersistentEntity persistentEntity, final EntityAccess entityAccess, - final Object storeId, final SimpleDBNativeItem entry) { - String id = storeId.toString(); - String domain = domainResolver.resolveDomain(id); - - //for non-null values we should call putAttributes, for nulls we should just do nothing during creation - List allAttributes = entry.createReplaceableItem().getAttributes(); - - List puts = new LinkedList(); - for (ReplaceableAttribute attribute : allAttributes) { - if (attribute.getValue() != null) { - puts.add(attribute); - } - } - - simpleDBTemplate.putAttributes(domain, id, puts); - return storeId; //todo should we return string id here? - } - - @Override - public void updateEntry(final PersistentEntity persistentEntity, final EntityAccess ea, - final Object key, final SimpleDBNativeItem entry) { - - String id = key.toString(); - String domain = domainResolver.resolveDomain(id); - - //for non-null values we should call putAttributes, for nulls we should call delete attributes - List allAttributes = entry.createReplaceableItem().getAttributes(); - - List puts = new LinkedList(); - List deletes = new LinkedList(); - - //we have to put *new* (incremented) version as part of the 'version' value and use the old version value in the conditional update. - //if the update fails we have to restore the version to the old value - Object currentVersion = null; - String stringCurrentVersion = null; - if (isVersioned(ea)) { - currentVersion = ea.getProperty("version"); - stringCurrentVersion = convertVersionToString(currentVersion); - incrementVersion(ea); //increment version now before we save it - } - - for (ReplaceableAttribute attribute : allAttributes) { - if ("version".equals(attribute.getName())) { - //ignore it, it will be explicitly added later right before the insert by taking incrementing and taking new one - } else { - if (attribute.getValue() != null) { - puts.add(attribute); - } else { - deletes.add(new Attribute(attribute.getName(), null)); - } - } - } - - if (isVersioned(ea)) { - puts.add(createAttributeForVersion(ea)); //update the version - try { - simpleDBTemplate.deleteAttributesVersioned(domain, id, deletes, stringCurrentVersion, persistentEntity); - simpleDBTemplate.putAttributesVersioned(domain, id, puts, stringCurrentVersion, persistentEntity); - } catch (DataAccessException e) { - //we need to restore version to what it was before the attempt to update - ea.setProperty("version", currentVersion); - throw e; - } - } else { - simpleDBTemplate.deleteAttributes(domain, id, deletes); - simpleDBTemplate.putAttributes(domain, id, puts); - } - } - - protected ReplaceableAttribute createAttributeForVersion(EntityAccess ea) { - ReplaceableAttribute attrToPut; - Object updatedVersion = ea.getProperty("version"); - String stringUpdatedVersion = convertVersionToString(updatedVersion); - attrToPut = new ReplaceableAttribute("version", stringUpdatedVersion, - Boolean.TRUE); - return attrToPut; - } - - protected String convertVersionToString(Object currentVersion) { - if (currentVersion == null) { - return null; - } - - if (currentVersion instanceof Long) { - return SimpleDBTypeConverterRegistrar.LONG_TO_STRING_CONVERTER.convert((Long) currentVersion); - } - - return currentVersion.toString(); - } - - @Override - protected void deleteEntries(String family, final List keys) { - for (Object key : keys) { - deleteEntry(family, key, null); //todo - optimize for bulk removal - } - } - - /** - * Provides proper conversion of 'version' field from Integer to Long - since we use numeric padding in SimpleDB - * there are different amounts of zeros for Long and Integer - and it matters for optimistic locking assertions - * on SimpleDB level. - */ - protected class SimpleDBNativeEntryModifyingEntityAccess extends NativeEntryModifyingEntityAccess { - public SimpleDBNativeEntryModifyingEntityAccess(PersistentEntity persistentEntity, Object entity) { - super(persistentEntity, entity); - } - - @Override - public void setProperty(String name, Object value) { - if ("version".equals(name) && value instanceof Integer) { - value = ((Integer)value).longValue(); - } - super.setProperty(name, value); - } - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBHiLoIdGenerator.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBHiLoIdGenerator.java deleted file mode 100644 index 9e053e2d6..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBHiLoIdGenerator.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.grails.datastore.mapping.simpledb.engine; - -import java.util.LinkedList; -import java.util.List; - -import org.grails.datastore.mapping.core.OptimisticLockingException; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.simpledb.util.SimpleDBConst; -import org.grails.datastore.mapping.simpledb.util.SimpleDBTemplate; -import org.grails.datastore.mapping.simpledb.util.SimpleDBUtil; -import org.springframework.dao.DataAccessException; - -import com.amazonaws.AmazonServiceException; -import com.amazonaws.services.simpledb.model.Item; -import com.amazonaws.services.simpledb.model.ReplaceableAttribute; - -/** - * Implementation of HiLo generator for SimpleDB. - * All HiLows are stored in a single dedicated AWS domain. Id of each record is the corresponding domain name of the - * {@link PersistentEntity}. The only attributes are the nextHi long attribute and the version. - * - * @author Roman Stepanenko - */ -public class SimpleDBHiLoIdGenerator implements SimpleDBIdGenerator { - /** - * @param domain domain where the all the counters are stored - * @param id name of the domain for some {@link PersistentEntity} for which this instance will be keeping the counter - * @param template - */ - public SimpleDBHiLoIdGenerator(String domain, String id, int lowSize, SimpleDBTemplate template) { - this.domain = domain; - this.id = id; - this.lowSize = lowSize; - this.template = template; - } - - public synchronized Object generateIdentifier(PersistentEntity persistentEntity, SimpleDBNativeItem nativeEntry) { - if (!initialized) { - initialize(persistentEntity); - } - if (current == max) { - incrementDBAndRefresh(persistentEntity); - reset(); - } - - long result = current; - current = current + 1; - return result; - } - - private void reset() { - current = currentHi * lowSize; - max = current + lowSize; - } - - private void incrementDBAndRefresh(PersistentEntity persistentEntity) { - boolean done = false; - int attempt = 0; - while (!done) { - attempt++; - if (attempt > 10000) {//todo - make configurable at some point - throw new IllegalArgumentException("exceeded number of attempts to load new Hi value value from db"); - } - try { - Item item = template.getConsistent(domain, id); - - if (item == null) {//no record exist yet - currentHi = 1; - currentVersion = null; - } else { - List hiAttributes = SimpleDBUtil.collectAttributeValues(item, SimpleDBConst.ID_GENERATOR_HI_LO_ATTRIBUTE_NAME); - currentHi = Long.parseLong(hiAttributes.get(0)); - currentVersion = Long.parseLong(SimpleDBUtil.collectAttributeValues(item, "version").get(0)); - } - - long nextHi = currentHi + 1; - long nextVersion = currentVersion == null ? (long)1: currentVersion+1; - - createOrUpdate(nextHi, nextVersion, currentVersion, persistentEntity); - currentVersion = nextVersion; - - done = true; - } catch (OptimisticLockingException e) { - //collition, it is expected to happen, we will try again - } - } - } - - /** - * Create domain if needed. - */ - private void initialize(PersistentEntity persistentEntity) { - try { - /*Item item =*/ template.getConsistent(domain, id); - } catch (DataAccessException e) { - throw new RuntimeException(e); - } catch (Exception e) { - //check if domain does not exist at all - AmazonServiceException awsE = null; - if (e instanceof AmazonServiceException) { - awsE = (AmazonServiceException) e; - } else if (e.getCause() instanceof AmazonServiceException) { - awsE = (AmazonServiceException) e.getCause(); - } - if (awsE != null && SimpleDBUtil.AWS_ERR_CODE_NO_SUCH_DOMAIN.equals(awsE.getErrorCode())) { - //domain does not exist, must create it - template.createDomain(domain); - } else { - throw new RuntimeException(e); - } - } - - current = 0; - max = 0; - - initialized = true; - } - - private void createOrUpdate(long nextHi, long newVersion, Long expectedVersion, PersistentEntity persistentEntity) { - List newValues = new LinkedList(); - newValues.add(new ReplaceableAttribute(SimpleDBConst.ID_GENERATOR_HI_LO_ATTRIBUTE_NAME, String.valueOf(nextHi), true)); - newValues.add(new ReplaceableAttribute("version", String.valueOf(newVersion), true)); - if (expectedVersion == null) { - //since there is no record yet we can't assert on version - template.putAttributes(domain, id, newValues); - } else { - template.putAttributesVersioned(domain, id, newValues, String.valueOf(expectedVersion), persistentEntity); - } - } - - private String id; - private long current; - private int lowSize; - private long max; - - private boolean initialized; - private long currentHi; - private Long currentVersion; - - private SimpleDBTemplate template; - private String domain; -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBIdGenerator.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBIdGenerator.java deleted file mode 100644 index ae7869c08..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBIdGenerator.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.grails.datastore.mapping.simpledb.engine; - -import org.grails.datastore.mapping.model.PersistentEntity; - -/** - * Encapsulates logic for generating id for a SimpleDB object. - * - * @author Roman Stepanenko - */ -public interface SimpleDBIdGenerator { - Object generateIdentifier(final PersistentEntity persistentEntity, final SimpleDBNativeItem nativeEntry); -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBIdGeneratorFactory.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBIdGeneratorFactory.java deleted file mode 100644 index bd8a67100..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBIdGeneratorFactory.java +++ /dev/null @@ -1,65 +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.mapping.simpledb.engine; - -import java.util.Map; - -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.simpledb.SimpleDBDatastore; -import org.grails.datastore.mapping.simpledb.config.SimpleDBDomainClassMappedForm; -import org.grails.datastore.mapping.simpledb.util.SimpleDBConst; -import org.grails.datastore.mapping.simpledb.util.SimpleDBUtil; - -/** - * Encapsulates logic of building appropriately configured SimpleDBIdGenerator instance. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class SimpleDBIdGeneratorFactory { - - public SimpleDBIdGenerator buildIdGenerator(PersistentEntity entity, SimpleDBDatastore simpleDBDatastore) { - String entityFamily = SimpleDBUtil.getMappedDomainName(entity); - - @SuppressWarnings("unchecked") - ClassMapping classMapping = entity.getMapping(); - SimpleDBDomainClassMappedForm mappedForm = classMapping.getMappedForm(); - - Map generatorInfo = mappedForm.getId_generator(); - - //by default use uuid generator - if (generatorInfo == null || generatorInfo.isEmpty()) { - return new SimpleDBUUIDIdGenerator(); - } - - String generatorType = (String) generatorInfo.get(SimpleDBConst.PROP_ID_GENERATOR_TYPE); - if (SimpleDBConst.PROP_ID_GENERATOR_TYPE_UUID.equals(generatorType)) { - return new SimpleDBUUIDIdGenerator(); - } - - if ((SimpleDBConst.PROP_ID_GENERATOR_TYPE_HILO.equals(generatorType))) { - Integer lowSize = (Integer) generatorInfo.get(SimpleDBConst.PROP_ID_GENERATOR_MAX_LO); - if (lowSize == null) { - lowSize = SimpleDBConst.PROP_ID_GENERATOR_MAX_LO_DEFAULT_VALUE; // default value - } - String hiloDomainName = SimpleDBUtil.getPrefixedDomainName(simpleDBDatastore.getDomainNamePrefix(), SimpleDBConst.ID_GENERATOR_HI_LO_DOMAIN_NAME); - return new SimpleDBHiLoIdGenerator(hiloDomainName, entityFamily, lowSize, simpleDBDatastore.getSimpleDBTemplate()); - } - - throw new IllegalArgumentException("unknown id generator type for simpledb: " + generatorType + ". Current implementation supports only " + - SimpleDBConst.PROP_ID_GENERATOR_TYPE_UUID + " and " + SimpleDBConst.PROP_ID_GENERATOR_TYPE_HILO); - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBNativeItem.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBNativeItem.java deleted file mode 100644 index e204452b1..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBNativeItem.java +++ /dev/null @@ -1,74 +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.mapping.simpledb.engine; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.amazonaws.services.simpledb.model.Attribute; -import com.amazonaws.services.simpledb.model.Item; -import com.amazonaws.services.simpledb.model.ReplaceableAttribute; -import com.amazonaws.services.simpledb.model.ReplaceableItem; - -/** - * Logical representation of how information is loaded from and sent to AWS. - *

    - * It stores all data in an internal Map and then creates appropriate AWS objects (@link com.amazonaws.services.simpledb.model.ReplaceableAttribute). - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class SimpleDBNativeItem { - - private Map data = Collections.synchronizedMap(new HashMap()); - - public SimpleDBNativeItem() {} - - public SimpleDBNativeItem(Item item) { - //populate map with the item attributes. //todo - handle multi-value attributes/long string etc - List attributes = item.getAttributes(); - for (Attribute attribute : attributes) { - put(attribute.getName(), attribute.getValue()); - } - } - - public void put(String key, String value) { - data.put(key, value); - } - - public String get(String key) { - return data.get(key); - } - - public ReplaceableItem createReplaceableItem() { - ReplaceableItem replaceableItem = new ReplaceableItem(); - for (Map.Entry entry : data.entrySet()) { - //exclude id property because that will be specified as the item name - String key = entry.getKey(); - if (!"id".equals(key)) { - String value = entry.getValue(); - replaceableItem.withAttributes(new ReplaceableAttribute(key, value, true)); - } - } - return replaceableItem; - } - - @Override - public String toString() { - return "SimpleDBNativeItem{data=" + data + '}'; - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBUUIDIdGenerator.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBUUIDIdGenerator.java deleted file mode 100644 index 585adacf4..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/engine/SimpleDBUUIDIdGenerator.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.grails.datastore.mapping.simpledb.engine; - -import org.grails.datastore.mapping.model.PersistentEntity; - -import java.util.UUID; - -/** - * Uses java UUID to generate a unique id. - * @author Roman Stepanenko - */ -public class SimpleDBUUIDIdGenerator implements SimpleDBIdGenerator { - public Object generateIdentifier(PersistentEntity persistentEntity, SimpleDBNativeItem nativeEntry) { - return UUID.randomUUID().toString(); - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/model/types/SimpleDBTypeConverterRegistrar.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/model/types/SimpleDBTypeConverterRegistrar.java deleted file mode 100644 index 819cc0fd5..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/model/types/SimpleDBTypeConverterRegistrar.java +++ /dev/null @@ -1,262 +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.mapping.simpledb.model.types; - -import org.springframework.core.GenericTypeResolver; -import org.springframework.core.convert.converter.Converter; -import org.springframework.core.convert.converter.ConverterRegistry; -import org.springframework.core.convert.converter.GenericConverter; -import org.grails.datastore.mapping.model.types.BasicTypeConverterRegistrar; - -import com.amazonaws.services.simpledb.util.SimpleDBUtils; - -import java.math.BigDecimal; -import java.text.ParseException; -import java.util.Date; - -/** - * A registrar that registers type converters used for SimpleDB. For example, - * numeric types are padded with zeros because AWS SimpleDB stores everything as - * a string and without padding ordering of numerics would not work. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class SimpleDBTypeConverterRegistrar extends BasicTypeConverterRegistrar { - public static final byte CONVERTER_NEGATIVE_BYTE_OFFSET = (byte)128; //abs value of Byte.MIN_VALUE - public static final int PADDING_BYTE = 4; //how many digits there will be for byte string representation see the offset length +1 - - public static final short CONVERTER_NEGATIVE_SHORT_OFFSET = (short)32768; //abs value of Short.MIN_VALUE - public static final int PADDING_SHORT = 6; //how many digits there will be for byte string representation - see the offset length +1 - - public static final int CONVERTER_NEGATIVE_INTEGER_OFFSET = new BigDecimal("2147483648").intValue(); //abs value of Integer.MIN_VALUE - public static final int PADDING_INTEGER = 11; //how many digits there will be for byte string representation - see the offset length +1 - - public static final long CONVERTER_NEGATIVE_LONG_OFFSET = new BigDecimal("9223372036854775808").longValue(); //abs value of Long.MIN_VALUE - public static final int PADDING_LONG = 20; //how many digits there will be for byte string representation - see the offset length +1 - - public static final Converter DATE_TO_STRING_CONVERTER = new Converter() { - public String convert(Date source) { - return SimpleDBUtils.encodeDate(source); - } - }; - - public static final Converter STRING_TO_DATE_CONVERTER = new Converter() { - public Date convert(String source) { - try { - return SimpleDBUtils.decodeDate(source); - } catch (ParseException e) { - throw new RuntimeException(e); - } - } - }; - - public static final Converter BYTE_TO_STRING_CONVERTER = new Converter() { - public String convert(Byte source) { - // the goal is to move all negatives into the positives realms so that we can - // compare strings lexicographically and it will be accurate for mix of positives and negatives - // Byte is -128..127 - // Let's say we shift by adding 128 and pad with zeros into 4 digits. - // This way we can cover all negatives and turn them into positives. - // -128 --> 0000 - // -127 --> 0001 - // ... - // -1 --> 0127 (this is the maximum a Byte can hold) - // - // so now we need to take care of how to convert remaining range of 0..127 values. - // lets say that for those values which are initially positive we just do toString and prepend them with '1' - // 0 --> 1000 - // 1 --> 1001 - // 126 --> 1126 - // 127 --> 1127 - // - // with this logic initially positive values will be 'greater' than converted negatives and yet conversion back/forth is faster than dealing with BigDecimals - // another benefit is that for 'initially' positive values would look pretty much the same in the converted format, which is handy when looking at raw DB values - - //decoding is simple - we look at first char to decide how to proceed because we know exactly how we got it - if (source < 0) { - byte shiftedValue = (byte)(source + CONVERTER_NEGATIVE_BYTE_OFFSET); - return SimpleDBUtils.encodeZeroPadding(shiftedValue, PADDING_BYTE); - } - return "1" + SimpleDBUtils.encodeZeroPadding(source, PADDING_BYTE-1); //-1 because we explicitly put 1 in front - } - }; - - public static final Converter STRING_TO_BYTE_CONVERTER = new Converter() { - public Byte convert(String source) { - //see conversion logic fully described in the BYTE_TO_STRING_CONVERTER - if (source.length() < PADDING_BYTE) { - //it might be just a short string like '10' - in this case just parse value - return Byte.parseByte(source); - } - if (source.charAt(0) == '0') { - //initial value was negative - return (byte)(Byte.parseByte(source) - CONVERTER_NEGATIVE_BYTE_OFFSET); - } - if (source.charAt(0) == '1') { - //initial value was positive, just ignore '1' in the front - Integer intResult = SimpleDBUtils.decodeZeroPaddingInt(source.substring(1)); - return intResult == null ? null : intResult.byteValue(); - } - if (source.charAt(0) == '-') { - return Byte.parseByte(source); - } - throw new IllegalArgumentException("should not happen: "+source); - } - }; - - public static final Converter SHORT_TO_STRING_CONVERTER = new Converter() { - public String convert(Short source) { - //see conversion logic fully described in the BYTE_TO_STRING_CONVERTER - if (source < 0) { - short shiftedValue = (short)(source + CONVERTER_NEGATIVE_SHORT_OFFSET); - return SimpleDBUtils.encodeZeroPadding(shiftedValue, PADDING_SHORT); - } - return "1" + SimpleDBUtils.encodeZeroPadding(source, PADDING_SHORT-1); //-1 because we explicitly put 1 in front - } - }; - - public static final Converter STRING_TO_SHORT_CONVERTER = new Converter() { - public Short convert(String source) { - //see conversion logic fully described in the BYTE_TO_STRING_CONVERTER - if (source.length() < PADDING_SHORT) { - //it might be just a short string like '10' - in this case just parse value - return Short.parseShort(source); - } - if (source.charAt(0) == '0') { - //initial value was negative - return (short)(Short.parseShort(source) - CONVERTER_NEGATIVE_SHORT_OFFSET); - } - if (source.charAt(0) == '1') { - //initial value was positive, just ignore '1' in the front - Integer intResult = SimpleDBUtils.decodeZeroPaddingInt(source.substring(1)); - return intResult == null ? null : intResult.shortValue(); - } - if (source.charAt(0) == '-') { - return Short.parseShort(source); - } - throw new IllegalArgumentException("should not happen: "+source); - } - }; - - public static final Converter INTEGER_TO_STRING_CONVERTER = new Converter() { - public String convert(Integer source) { - //see conversion logic fully described in the BYTE_TO_STRING_CONVERTER - if (source < 0) { - int shiftedValue = source + CONVERTER_NEGATIVE_INTEGER_OFFSET; - return SimpleDBUtils.encodeZeroPadding(shiftedValue, PADDING_INTEGER); - } - return "1" + SimpleDBUtils.encodeZeroPadding(source, PADDING_INTEGER-1); //-1 because we explicitly put 1 in front - } - }; - - public static final Converter STRING_TO_INTEGER_CONVERTER = new Converter() { - public Integer convert(String source) { - if (source.length() < PADDING_INTEGER) { - //it might be just a short string like '10' - in this case just parse value - return Integer.parseInt(source); - } - //see conversion logic fully described in the BYTE_TO_STRING_CONVERTER - if (source.charAt(0) == '0') { - //initial value was negative - return Integer.parseInt(source) - CONVERTER_NEGATIVE_INTEGER_OFFSET; - } - if (source.charAt(0) == '1') { - //initial value was positive, just ignore '1' in the front - return SimpleDBUtils.decodeZeroPaddingInt(source.substring(1)); - } - if (source.charAt(0) == '-') { - return Integer.parseInt(source); - } - throw new IllegalArgumentException("should not happen: "+source); - } - }; - - public static final Converter LONG_TO_STRING_CONVERTER = new Converter() { - public String convert(Long source) { - //see conversion logic fully described in the BYTE_TO_STRING_CONVERTER - if (source < 0) { - long shiftedValue = source + CONVERTER_NEGATIVE_LONG_OFFSET; - return SimpleDBUtils.encodeZeroPadding(shiftedValue, PADDING_LONG); - } - return "1" + SimpleDBUtils.encodeZeroPadding(source, PADDING_LONG-1); //-1 because we explicitly put 1 in front - } - }; - - public static final Converter STRING_TO_LONG_CONVERTER = new Converter() { - public Long convert(String source) { - //see conversion logic fully described in the BYTE_TO_STRING_CONVERTER - if (source.length() < PADDING_LONG) { - //it might be just a short string like '10' - in this case just parse value - return Long.parseLong(source); - } - if (source.charAt(0) == '0') { - //initial value was negative - return Long.parseLong(source) - CONVERTER_NEGATIVE_LONG_OFFSET; - } - if (source.charAt(0) == '1') { - //initial value was positive, just ignore '1' in the front - return SimpleDBUtils.decodeZeroPaddingLong(source.substring(1)); - } - if (source.charAt(0) == '-') { - return Long.parseLong(source); - } - throw new IllegalArgumentException("should not happen: "+source); - } - }; - - @Override - public void register(ConverterRegistry registry) { - //we use most of the standard's converters - super.register(registry); - - overwrite(registry, BYTE_TO_STRING_CONVERTER); - overwrite(registry, STRING_TO_BYTE_CONVERTER); - - overwrite(registry, SHORT_TO_STRING_CONVERTER); - overwrite(registry, STRING_TO_SHORT_CONVERTER); - - overwrite(registry, INTEGER_TO_STRING_CONVERTER); - overwrite(registry, STRING_TO_INTEGER_CONVERTER); - - overwrite(registry, LONG_TO_STRING_CONVERTER); - overwrite(registry, STRING_TO_LONG_CONVERTER); - - overwrite(registry, DATE_TO_STRING_CONVERTER); - overwrite(registry, STRING_TO_DATE_CONVERTER); - } - - protected void overwrite(ConverterRegistry registry, @SuppressWarnings("rawtypes") Converter converter) { - //get type info for the specified converter - GenericConverter.ConvertiblePair typeInfo = getRequiredTypeInfo(converter, Converter.class); - if (typeInfo == null) { - throw new IllegalArgumentException( - "Unable to the determine sourceType and targetType which " + - "your Converter converts between; declare these generic types. Converter class: " + - converter.getClass().getName()); - } - - //now remove converters that we will overwrite for SimpleDB - registry.removeConvertible(typeInfo.getSourceType(), typeInfo.getTargetType()); - - //now add - registry.addConverter(converter); - } - - private GenericConverter.ConvertiblePair getRequiredTypeInfo(Object converter, Class genericIfc) { - Class[] args = GenericTypeResolver.resolveTypeArguments(converter.getClass(), genericIfc); - return (args != null ? new GenericConverter.ConvertiblePair(args[0], args[1]) : null); - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/query/SimpleDBQuery.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/query/SimpleDBQuery.java deleted file mode 100644 index d1be1b636..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/query/SimpleDBQuery.java +++ /dev/null @@ -1,402 +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.mapping.simpledb.query; - -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValue; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.simpledb.engine.SimpleDBDomainResolver; -import org.grails.datastore.mapping.simpledb.engine.SimpleDBEntityPersister; -import org.grails.datastore.mapping.simpledb.engine.SimpleDBNativeItem; -import org.grails.datastore.mapping.simpledb.util.SimpleDBConverterUtil; -import org.grails.datastore.mapping.simpledb.util.SimpleDBTemplate; -import org.grails.datastore.mapping.simpledb.util.SimpleDBUtil; - -import com.amazonaws.services.simpledb.model.Item; - -/** - * A {@link org.grails.datastore.mapping.query.Query} implementation for the SimpleDB store - * - * @author Roman Stepanenko - * @since 0.1 - */ -@SuppressWarnings("rawtypes") -public class SimpleDBQuery extends Query { - - protected SimpleDBDomainResolver domainResolver; - protected SimpleDBTemplate simpleDBTemplate; - protected SimpleDBEntityPersister simpleDBEntityPersister; - - protected static Map queryHandlers = new HashMap(); - protected static final String ITEM_NAME = "itemName()"; - - static{ - queryHandlers.put(Equals.class, new QueryHandler() { - public void handle(PersistentEntity entity, Equals criterion, StringBuilder clause) { - String propertyName = criterion.getProperty(); - String key = getSmartQuotedKey(entity, propertyName); - String stringValue = SimpleDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - - addSimpleComparison(clause, key, "=", stringValue); - } - }); - queryHandlers.put(NotEquals.class, new QueryHandler() { - public void handle(PersistentEntity entity, NotEquals criterion, StringBuilder clause) { - String propertyName = criterion.getProperty(); - String key = getSmartQuotedKey(entity, propertyName); - String stringValue = SimpleDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - - addSimpleComparison(clause, key, "!=", stringValue); - } - }); - queryHandlers.put(IsNull.class, new QueryHandler() { - public void handle(PersistentEntity entity, IsNull criterion, StringBuilder clause) { - String propertyName = criterion.getProperty(); - String key = getSmartQuotedKey(entity, propertyName); - - clause.append(key).append(" ").append("IS NULL").append(" "); - } - }); - queryHandlers.put(IdEquals.class, new QueryHandler() { - public void handle(PersistentEntity entity, IdEquals criterion, StringBuilder clause) { - String stringValue = SimpleDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - - addSimpleComparison(clause, ITEM_NAME, "=", stringValue); - } - }); - queryHandlers.put(Like.class, new QueryHandler() { - public void handle(PersistentEntity entity, Like criterion, StringBuilder clause) { - String propertyName = criterion.getProperty(); - String key = getSmartQuotedKey(entity, propertyName); - String stringValue = SimpleDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - - addSimpleComparison(clause, key, "LIKE", stringValue); - } - }); - queryHandlers.put(In.class, new QueryHandler() { - public void handle(PersistentEntity entity, In criterion, StringBuilder clause) { - String propertyName = criterion.getProperty(); - String key = getSmartQuotedKey(entity, propertyName); - - Collection stringValues = SimpleDBConverterUtil.convertToStrings(criterion.getValues(), entity.getMappingContext()); - clause.append(key).append(" IN ("); - clause.append(SimpleDBUtil.quoteValues(stringValues)).append(")"); - } - }); - queryHandlers.put(Between.class, new QueryHandler() { - public void handle(PersistentEntity entity, Between criterion, StringBuilder clause) { - String propertyName = criterion.getProperty(); - String key = getSmartQuotedKey(entity, propertyName); - String fromStringValue = SimpleDBConverterUtil.convertToString(criterion.getFrom(), entity.getMappingContext()); - String toStringValue = SimpleDBConverterUtil.convertToString(criterion.getTo(), entity.getMappingContext()); - - clause.append(key).append(" >= ").append(SimpleDBUtil.quoteValue(fromStringValue)).append(" AND "); - clause.append(key).append(" <= ").append(SimpleDBUtil.quoteValue(toStringValue)); - } - }); - queryHandlers.put(GreaterThan.class, new QueryHandler() { - public void handle(PersistentEntity entity, GreaterThan criterion, StringBuilder clause) { - String propertyName = criterion.getProperty(); - String key = getSmartQuotedKey(entity, propertyName); - String stringValue = SimpleDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - - addSimpleComparison(clause, key, ">", stringValue); - } - }); - queryHandlers.put(GreaterThanEquals.class, new QueryHandler() { - public void handle(PersistentEntity entity, GreaterThanEquals criterion, StringBuilder clause) { - String propertyName = criterion.getProperty(); - String key = getSmartQuotedKey(entity, propertyName); - String stringValue = SimpleDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - - addSimpleComparison(clause, key, ">=", stringValue); - } - }); - queryHandlers.put(LessThan.class, new QueryHandler() { - public void handle(PersistentEntity entity, LessThan criterion, StringBuilder clause) { - String propertyName = criterion.getProperty(); - String key = getSmartQuotedKey(entity, propertyName); - String stringValue = SimpleDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - - addSimpleComparison(clause, key, "<", stringValue); - } - }); - queryHandlers.put(LessThanEquals.class, new QueryHandler() { - public void handle(PersistentEntity entity, LessThanEquals criterion, StringBuilder clause) { - String propertyName = criterion.getProperty(); - String key = getSmartQuotedKey(entity, propertyName); - String stringValue = SimpleDBConverterUtil.convertToString(criterion.getValue(), entity.getMappingContext()); - - addSimpleComparison(clause, key, "<=", stringValue); - } - }); - } - - public SimpleDBQuery(Session session, PersistentEntity entity, SimpleDBDomainResolver domainResolver, - SimpleDBEntityPersister simpleDBEntityPersister, SimpleDBTemplate simpleDBTemplate) { - super(session, entity); - this.domainResolver = domainResolver; - this.simpleDBEntityPersister = simpleDBEntityPersister; - this.simpleDBTemplate = simpleDBTemplate; - } - - @Override - protected List executeQuery(PersistentEntity entity, Junction criteria) { - // TODO - in case of sharding we should iterate over all domains for this PersistentEntity (ideally in parallel) - String domain = domainResolver.getAllDomainsForEntity().get(0); - - final List projectionList = projections().getProjectionList(); - boolean hasCountProjection = false; - - StringBuilder query; - if (projectionList.isEmpty()) { - query = new StringBuilder("select * from `").append(domain).append("`"); - } else { - hasCountProjection = validateProjectionsAndCheckIfCountIsPresent(projectionList); - query = buildQueryForProjections(entity, domain, projectionList); - } - - if (!criteria.getCriteria().isEmpty()) { - query.append(" where "); //things like TestEntity.list() result in empty criteria collection, so we should not have a 'where' clause at all - } - - String clause = ""; - Set usedPropertyNames = new HashSet(); - if (criteria instanceof Conjunction) { - clause = buildCompositeClause(criteria, "AND", usedPropertyNames); - } else if (criteria instanceof Disjunction) { - clause = buildCompositeClause(criteria, "OR", usedPropertyNames); - } else { - throw new RuntimeException("not implemented: " + criteria.getClass().getName()); - } - - query.append(clause); - - List orderBys = getOrderBy(); - if (!orderBys.isEmpty()) { - if (orderBys.size() > 1) { - throw new UnsupportedOperationException("Only single 'order by' clause is supported. You have: " + orderBys.size()); - } - Order orderBy = orderBys.get(0); - String orderByPropertyName = orderBy.getProperty(); - String key = extractPropertyKey(orderByPropertyName, entity); - //AWS SimpleDB rule: if you use ORDER BY then you have to have a condition on that attribute in the where clause, otherwise it will throw an error - //so we check if that property was used in the clause and if not we add 'is not null' condition - if (!usedPropertyNames.contains(orderByPropertyName)) { - if (criteria.getCriteria().isEmpty()) { //we might have a case 'select * from X order by ABC' which must be fixed into 'select * from X where ABC IS NOT NULL order by ABC' - query.append(" where "); - } else { - query.append(" AND "); - } - - query.append(SimpleDBUtil.quoteName(key)).append(" IS NOT NULL"); - } - - query.append(" ORDER BY ").append(SimpleDBUtil.quoteName(key)).append(" ").append(orderBy.getDirection()); - } - - //specify the limit on the returned results - int limit = max < 0 ? 2500 : max; //if user did not explicitly limit maxResults, use the maximum limit allowed dy AWS (if not specified explicitly it will use 100 limit) - query.append(" LIMIT ").append(limit); - - List items = simpleDBTemplate.query(query.toString(), max < 0 ? Integer.MAX_VALUE : max); - List results = new LinkedList(); - if (projectionList.isEmpty()) { - for (Item item : items) { - results.add(createObjectFromItem(item)); - } - } else { - if (hasCountProjection) { //count (*) is returned by AWS in a special way... - int count = Integer.parseInt(items.get(0).getAttributes().get(0).getValue()); - results.add(count); - } else { - for (Projection projection : projectionList) { - if (IdProjection.class.equals(projection.getClass())) { - for (Item item : items) { - results.add(item.getName()); - } - } else if (PropertyProjection.class.equals(projection.getClass())) { - for (Item item : items) { - String key = extractPropertyKey(((PropertyProjection) projection).getPropertyName(), entity); - results.addAll(SimpleDBUtil.collectAttributeValues(item, key)); - } - } - } - } - } - - return results; - } - - private StringBuilder buildQueryForProjections(PersistentEntity entity, String domain, List projectionList) { - StringBuilder query = new StringBuilder("select "); - boolean isFirst = true; - for (Projection projection : projectionList) { - if (projectionList.size() > 1 && !isFirst) { - query.append(", "); - } - if (isFirst) { - isFirst = false; - } - if (CountProjection.class.equals(projection.getClass())) { - query.append("count(*)"); - } else if (IdProjection.class.equals(projection.getClass())) { - query.append("itemName()"); - } else if (PropertyProjection.class.equals(projection.getClass())) { - String key = getSmartQuotedKey(entity, ((PropertyProjection)projection).getPropertyName()); - query.append(key); - } - } - query.append(" from `").append(domain).append("`"); - return query; - } - - /** - * make sure that only property, id, or count projections are provided, and that the combination of them is meaningful. - * Throws exception if something is invalid. - * @param projections - * @returns true if count projection is present, false otherwise. - */ - private boolean validateProjectionsAndCheckIfCountIsPresent(List projections) { - //of the grouping projects AWS SimpleDB only supports count(*) projection, nothing else. Other kinds will have - //to be explicitly coded later... - boolean hasCountProjection = false; - for (Projection projection : projections) { - if (!(PropertyProjection.class.equals(projection.getClass()) || - IdProjection.class.equals(projection.getClass()) || - CountProjection.class.equals(projection.getClass()))) { - throw new UnsupportedOperationException("Currently projections of type " + - projection.getClass().getSimpleName() + " are not supported by this implementation"); - } - - if (CountProjection.class.equals(projection.getClass())) { - hasCountProjection = true; - } - } - if ( projections.size() > 1 && hasCountProjection ) { - throw new IllegalArgumentException("Can not mix count projection and other types of projections. You requested: "+projections); - } - return hasCountProjection; - } - - @SuppressWarnings("unchecked") - private String buildCompositeClause(Junction criteria, String booleanOperator, Set usedPropertyNames) { - StringBuilder clause = new StringBuilder(); - boolean first = true; - for (Criterion criterion : criteria.getCriteria()) { - if (first) { - //do nothing first time - first = false; - } else { - clause.append(" ").append(booleanOperator).append(" "); //prepend with operator - } - - if (criterion instanceof PropertyNameCriterion) { - PropertyNameCriterion propertyCriterion = (PropertyNameCriterion) criterion; - String propertyName = propertyCriterion.getProperty(); - - usedPropertyNames.add(propertyName); //register the fact that the property did have some condition - it is needed if we use order by clause - - QueryHandler queryHandler = queryHandlers.get(criterion.getClass()); - if (queryHandler != null) { - queryHandler.handle(entity, criterion, clause); - } else { - throw new UnsupportedOperationException("Queries of type " + - criterion.getClass().getSimpleName() + " are not supported by this implementation"); - } - } else if (criterion instanceof Conjunction) { - String innerClause = buildCompositeClause((Conjunction) criterion, "AND", usedPropertyNames); - addToMainClause(criteria, clause, innerClause); - } else if (criterion instanceof Disjunction) { - String innerClause = buildCompositeClause((Disjunction) criterion, "OR", usedPropertyNames); - addToMainClause(criteria, clause, innerClause); - } else if (criterion instanceof Negation) { - String innerClause = buildCompositeClause((Negation) criterion, "OR", usedPropertyNames); //when we negate we use OR by default - clause.append("NOT (").append(innerClause).append(")"); - } else { - throw new UnsupportedOperationException("Queries of type " + - criterion.getClass().getSimpleName() + " are not supported by this implementation"); - } - } - return clause.toString(); - } - - private void addToMainClause(Junction criteria, StringBuilder clause, String innerClause) { - boolean useParenthesis = criteria.getCriteria().size() > 1; //use parenthesis only when needed - if (useParenthesis) { - clause.append("("); - } - clause.append(innerClause); - if (useParenthesis) { - clause.append(")"); - } - } - - protected Object createObjectFromItem(Item item) { - final String id = item.getName(); - return simpleDBEntityPersister.createObjectFromNativeEntry(getEntity(), id, - new SimpleDBNativeItem(item)); - } - - protected static interface QueryHandler { - public void handle(PersistentEntity entity, T criterion, StringBuilder clause); - } - - protected static String extractPropertyKey(String propertyName, PersistentEntity entity) { - PersistentProperty prop = entity.getPropertyByName(propertyName); - if (prop == null) { - throw new IllegalArgumentException( - "Could not find property '" + propertyName + "' in entity '" + entity.getName() + "'"); - } - - KeyValue kv = (KeyValue) prop.getMapping().getMappedForm(); - String key = kv.getKey(); - return key; - } - - /** - * Assumes that the key is already quoted or is itemName() - * @param clause - * @param key - * @param comparison - * @param stringValue - */ - protected static void addSimpleComparison(StringBuilder clause, String key, String comparison, String stringValue) { - clause.append(key).append(" ").append(comparison).append(" ").append(SimpleDBUtil.quoteValue(stringValue)); - } - - /** - * Returns quoted mapped key OR if the property is an identity returns 'itemName()' - this is how AWS SimpleDB refers to primary key field. - * @param entity - * @param propertyName - * @return - */ - protected static String getSmartQuotedKey(PersistentEntity entity, String propertyName) { - if (entity.isIdentityName(propertyName)) { - return ITEM_NAME; - } - return SimpleDBUtil.quoteName(extractPropertyKey(propertyName, entity)); - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/DelayAfterWriteSimpleDBTemplateDecorator.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/DelayAfterWriteSimpleDBTemplateDecorator.java deleted file mode 100644 index 6f6b2cfa3..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/DelayAfterWriteSimpleDBTemplateDecorator.java +++ /dev/null @@ -1,101 +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.mapping.simpledb.util; - -import java.util.List; - -import org.grails.datastore.mapping.model.PersistentEntity; -import org.springframework.dao.DataAccessException; - -import com.amazonaws.services.simpledb.model.Attribute; -import com.amazonaws.services.simpledb.model.Item; -import com.amazonaws.services.simpledb.model.ReplaceableAttribute; - -/** - * Simple decorator used in testing to fight eventual consistency of SimpleDB. - */ -public class DelayAfterWriteSimpleDBTemplateDecorator implements SimpleDBTemplate { - - private SimpleDBTemplate template; - private long delayMillis; - - public DelayAfterWriteSimpleDBTemplateDecorator(SimpleDBTemplate template, long delayMillis) { - this.template = template; - this.delayMillis = delayMillis; - } - - public void createDomain(String domainName) throws DataAccessException { - template.createDomain(domainName); - pause(); - } - - public boolean deleteAllItems(String domainName) throws DataAccessException { - boolean result = template.deleteAllItems(domainName); - if (result) { - pause(); //pause only if there were items to delete - } - return result; - } - - public void deleteAttributes(String domainName, String id, List attributes) throws DataAccessException { - template.deleteAttributes(domainName, id, attributes); - pause(); - } - - public void deleteAttributesVersioned(String domainName, String id, List attributes, String expectedVersion, PersistentEntity persistentEntity) throws DataAccessException { - template.deleteAttributesVersioned(domainName, id, attributes, expectedVersion, persistentEntity); - pause(); - } - - public void deleteDomain(String domainName) throws DataAccessException { - template.deleteDomain(domainName); - pause(); - } - - public void deleteItem(String domainName, String id) throws DataAccessException { - template.deleteItem(domainName, id); - pause(); - } - - public Item get(String domainName, String id) throws DataAccessException { - return template.get(domainName, id); - } - - public Item getConsistent(String domainName, String id) throws DataAccessException { - return template.getConsistent(domainName, id); - } - - public List listDomains() throws DataAccessException { - return template.listDomains(); - } - - public void putAttributes(String domainName, String id, List attributes) throws DataAccessException { - template.putAttributes(domainName, id, attributes); -// pause(); //for tests we use DelayAfterWriteSimpleDBSession which pauses after flush - } - - public void putAttributesVersioned(String domainName, String id, List attributes, String expectedVersion, PersistentEntity persistentEntity) throws DataAccessException { - template.putAttributesVersioned(domainName, id, attributes, expectedVersion, persistentEntity); -// pause(); //for tests we use DelayAfterWriteSimpleDBSession which pauses after flush - } - - public List query(String query, int max) throws DataAccessException { - return template.query(query, max); - } - - private void pause() { - try { Thread.sleep(delayMillis); } catch (InterruptedException e) { /* ignored */ } - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBConst.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBConst.java deleted file mode 100644 index d360f2026..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBConst.java +++ /dev/null @@ -1,52 +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.mapping.simpledb.util; - -/** - * Various constants for SimpleDB support. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class SimpleDBConst { - - private SimpleDBConst() { - // don't instantiate - } - - public static final String PROP_ID_GENERATOR_TYPE = "type"; - public static final String PROP_ID_GENERATOR_TYPE_HILO = "hilo"; - public static final String PROP_ID_GENERATOR_TYPE_UUID = "uuid"; //used by default - public static final String PROP_ID_GENERATOR_MAX_LO = "maxLo"; - public static final int PROP_ID_GENERATOR_MAX_LO_DEFAULT_VALUE = 1000; - public static final String ID_GENERATOR_HI_LO_DOMAIN_NAME = "HiLo"; //in which domain will HiLo store the counters, this domain name might be prefixed, as for all other domains - public static final String ID_GENERATOR_HI_LO_ATTRIBUTE_NAME = "nextHi"; - - public static final String PROP_SHARDING_ENABLED = "enabled"; - - /** - * What must be specified in mapping as a value of 'mapWith' to map the - * domain class with SimpleDB gorm plugin: - *
    -     * class DomPerson {
    -     *      String id
    -     *      String firstName
    -     *      static mapWith = "simpledb"
    -     * }
    -     * 
    - */ - public static final String SIMPLE_DB_MAP_WITH_VALUE = "simpledb"; - -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBConverterUtil.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBConverterUtil.java deleted file mode 100644 index e0f0475a3..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBConverterUtil.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.grails.datastore.mapping.simpledb.util; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; - -import org.springframework.core.convert.ConversionService; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.proxy.EntityProxy; - -/** - * Simple conversion utility for SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class SimpleDBConverterUtil { - public static String convertToString(Object value, MappingContext mappingContext) { - if (value == null) { - return null; - } - String stringValue = null; - if (value instanceof String) { - stringValue = (String)value; - } else if (shouldConvert(value, mappingContext)) { - final ConversionService conversionService = mappingContext.getConversionService(); - stringValue = conversionService.convert(value, String.class); - } - return stringValue; - } - - public static Collection convertToStrings(Collection values, MappingContext mappingContext) { - List stringValues = new LinkedList(); - for (Object value : values) { - stringValues.add(convertToString(value, mappingContext)); - } - - return stringValues; - } - - private static boolean shouldConvert(Object value, MappingContext mappingContext) { - return !mappingContext.isPersistentEntity(value) && !(value instanceof EntityProxy); - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBTemplate.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBTemplate.java deleted file mode 100644 index 10622f423..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBTemplate.java +++ /dev/null @@ -1,125 +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.mapping.simpledb.util; - -import java.util.List; - -import org.grails.datastore.mapping.model.PersistentEntity; -import org.springframework.dao.DataAccessException; - -import com.amazonaws.services.simpledb.model.Attribute; -import com.amazonaws.services.simpledb.model.Item; -import com.amazonaws.services.simpledb.model.ReplaceableAttribute; - -/** - * AWS SimpleDB template. This is a low-level way of accessing SimpleDB, - * currently is uses AWS SDK API as the return and parameter types. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public interface SimpleDBTemplate { - - Item get(String domainName, String id) throws DataAccessException; - - /** - * Same as get but with consistent read flag. - * @param domainName - * @param id - * @return - * @throws DataAccessException - */ - Item getConsistent(String domainName, String id) throws DataAccessException; - - void putAttributes(String domainName, String id, List attributes) throws DataAccessException; - - /** - * Puts attributes conditioned on the specified version - used for optimistic - * locking. If the specified expectedVersion does not match what is in - * simpleDB, exception is thrown and no changes are made to the simpleDB - * - * @param domainName - * @param id - * @param attributes - * @param expectedVersion - * @param persistentEntity - * @throws DataAccessException - */ - void putAttributesVersioned(String domainName, String id, List attributes, - String expectedVersion, PersistentEntity persistentEntity) throws DataAccessException; - - /** - * If attributes is empty this method will do nothing - otherwise the whole - * item will be deleted. Use dedicated deleteItem method to delete item. - * - * @param domainName - * @param id - * @param attributes - * @throws DataAccessException - */ - void deleteAttributes(String domainName, String id, List attributes) throws DataAccessException; - - /** - * Deletes attributes conditioned on the specified version - used for - * optimistic locking. If the specified expectedVersion does not match what - * is in simpleDB, exception is thrown and no changes are made to the - * simpleDB. If attributes is empty this method will do nothing - otherwise - * the whole item will be deleted. Use dedicated deleteItem method to delete - * item. - * - * @param domainName - * @param id - * @param attributes - * @param expectedVersion - * @param persistentEntity - * @throws DataAccessException - */ - void deleteAttributesVersioned(String domainName, String id, List attributes, String expectedVersion, PersistentEntity persistentEntity) - throws DataAccessException; - - /** - * Deletes the specified item with all of its attributes. - * - * @param domainName - * @param id - */ - void deleteItem(String domainName, String id) throws DataAccessException; - - /** - * Returns true if any item was deleted, in other words if domain was empty it returns false. - * @param domainName - * @return - * @throws DataAccessException - */ - boolean deleteAllItems(String domainName) throws DataAccessException; - - /** - * - * @param query - * @param max maximum amount of items to return (inclusive). Note that - * this max parameter is very different from LIMIT parameter used in the - * actual query: LIMIT controls pretty much 'page size' while this parameter - * control total number of items returned. - * @return - * @throws DataAccessException - */ - List query(String query, int max) throws DataAccessException; - - void deleteDomain(String domainName) throws DataAccessException; - - void createDomain(String domainName) throws DataAccessException; - - List listDomains() throws DataAccessException; -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBTemplateImpl.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBTemplateImpl.java deleted file mode 100644 index d889a28af..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBTemplateImpl.java +++ /dev/null @@ -1,326 +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.mapping.simpledb.util; - -import java.util.LinkedList; -import java.util.List; - -import org.grails.datastore.mapping.core.OptimisticLockingException; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.springframework.dao.DataAccessException; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -import com.amazonaws.AmazonServiceException; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.services.simpledb.AmazonSimpleDB; -import com.amazonaws.services.simpledb.AmazonSimpleDBClient; -import com.amazonaws.services.simpledb.model.Attribute; -import com.amazonaws.services.simpledb.model.CreateDomainRequest; -import com.amazonaws.services.simpledb.model.DeleteAttributesRequest; -import com.amazonaws.services.simpledb.model.DeleteDomainRequest; -import com.amazonaws.services.simpledb.model.GetAttributesRequest; -import com.amazonaws.services.simpledb.model.Item; -import com.amazonaws.services.simpledb.model.ListDomainsRequest; -import com.amazonaws.services.simpledb.model.ListDomainsResult; -import com.amazonaws.services.simpledb.model.PutAttributesRequest; -import com.amazonaws.services.simpledb.model.ReplaceableAttribute; -import com.amazonaws.services.simpledb.model.SelectRequest; -import com.amazonaws.services.simpledb.model.SelectResult; -import com.amazonaws.services.simpledb.model.UpdateCondition; - -/** - * Implementation of SimpleDBTemplate using AWS Java SDK. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class SimpleDBTemplateImpl implements SimpleDBTemplate { - - private AmazonSimpleDB sdb; - - public SimpleDBTemplateImpl(AmazonSimpleDB sdb) { - this.sdb = sdb; - } - - /** - * Constructs instance with the specified credentials and region (via endpoint) - * @param accessKey - * @param secretKey - * @param endpoint if null will use AWS ASD default setting for your account. See http://docs.aws.amazon.com/general/latest/gr/rande.html#sdb_region - */ - public SimpleDBTemplateImpl(String accessKey, String secretKey, String endpoint) { - Assert.isTrue(StringUtils.hasLength(accessKey) && StringUtils.hasLength(secretKey), - "Please provide accessKey and secretKey"); - - sdb = new AmazonSimpleDBClient(new BasicAWSCredentials(accessKey, secretKey)); - - if (endpoint != null && !"".equals(endpoint)) { - sdb.setEndpoint(endpoint); - } - } - - public Item get(String domainName, String id) { - return getInternal(domainName, id, 1); - } - private Item getInternal(String domainName, String id, int attempt) { - GetAttributesRequest request = new GetAttributesRequest(domainName, id); - try { - List attributes = sdb.getAttributes(request).getAttributes(); - if (attributes.isEmpty()) { - return null; - } - - return new Item(id, attributes); - } catch (AmazonServiceException e) { - if (SimpleDBUtil.AWS_ERR_CODE_NO_SUCH_DOMAIN.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such domain: "+domainName, e); - } else if (SimpleDBUtil.AWS_ERR_CODE_SERVICE_UNAVAILABLE.equals(e.getErrorCode())) { - //retry after a small pause - SimpleDBUtil.sleepBeforeRetry(attempt); - attempt++; - return getInternal(domainName, id, attempt); - } else { - throw e; - } - } - } - - public Item getConsistent(String domainName, String id) { - return getConsistentInternal(domainName, id, 1); - } - private Item getConsistentInternal(String domainName, String id, int attempt) { -// String selectExpression = "select * from `" + domainName + "` where id = '"+id+"'"; //todo - - //todo - handle exceptions and retries - - GetAttributesRequest request = new GetAttributesRequest(domainName, id); - request.setConsistentRead(true); - try { - List attributes = sdb.getAttributes(request).getAttributes(); - if (attributes.isEmpty()) { - return null; - } - - return new Item(id, attributes); - } catch (AmazonServiceException e) { - if (SimpleDBUtil.AWS_ERR_CODE_NO_SUCH_DOMAIN.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such domain: "+domainName, e); - } else if (SimpleDBUtil.AWS_ERR_CODE_SERVICE_UNAVAILABLE.equals(e.getErrorCode())) { - //retry after a small pause - SimpleDBUtil.sleepBeforeRetry(attempt); - attempt++; - return getConsistentInternal(domainName, id, attempt); - } else { - throw e; - } - } - } - - public void putAttributes(String domainName, String id, List attributes) throws DataAccessException { - putAttributesInternal(domainName, id, attributes, 1); - } - private void putAttributesInternal(String domainName, String id, List attributes, int attempt) throws DataAccessException { - try { - PutAttributesRequest request = new PutAttributesRequest(domainName, id, attributes); - sdb.putAttributes(request); - } catch (AmazonServiceException e) { - if (SimpleDBUtil.AWS_ERR_CODE_NO_SUCH_DOMAIN.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such domain: "+domainName, e); - } else if (SimpleDBUtil.AWS_ERR_CODE_SERVICE_UNAVAILABLE.equals(e.getErrorCode())) { - //retry after a small pause - SimpleDBUtil.sleepBeforeRetry(attempt); - attempt++; - putAttributesInternal(domainName, id, attributes, attempt); - } else { - throw e; - } - } - } - - public void putAttributesVersioned(String domainName, String id, List attributes, String expectedVersion, PersistentEntity persistentEntity) throws DataAccessException { - putAttributesVersionedInternal(domainName, id, attributes, expectedVersion, persistentEntity, 1); - } - private void putAttributesVersionedInternal(String domainName, String id, List attributes, String expectedVersion, PersistentEntity persistentEntity, int attempt) throws DataAccessException { - PutAttributesRequest request = new PutAttributesRequest(domainName, id, attributes, - getOptimisticVersionCondition(expectedVersion)); - try { - sdb.putAttributes(request); - } catch (AmazonServiceException e) { - if (SimpleDBUtil.AWS_ERR_CODE_CONDITIONAL_CHECK_FAILED.equals(e.getErrorCode())) { - throw new OptimisticLockingException(persistentEntity, id); - } else if (SimpleDBUtil.AWS_ERR_CODE_NO_SUCH_DOMAIN.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such domain: " + domainName, e); - } else if (SimpleDBUtil.AWS_ERR_CODE_SERVICE_UNAVAILABLE.equals(e.getErrorCode())) { - //retry after a small pause - SimpleDBUtil.sleepBeforeRetry(attempt); - attempt++; - putAttributesVersionedInternal(domainName, id, attributes, expectedVersion, persistentEntity, attempt); - } else { - throw e; - } - } - } - - public void deleteAttributes(String domainName, String id, List attributes) throws DataAccessException { - deleteAttributesInternal(domainName, id, attributes, 1); - } - private void deleteAttributesInternal(String domainName, String id, List attributes, int attempt) throws DataAccessException { - if (!attributes.isEmpty()) { - DeleteAttributesRequest request = new DeleteAttributesRequest(domainName, id, attributes); - try { - sdb.deleteAttributes(request); - } catch (AmazonServiceException e) { - if (SimpleDBUtil.AWS_ERR_CODE_NO_SUCH_DOMAIN.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such domain: "+domainName, e); - } else if (SimpleDBUtil.AWS_ERR_CODE_SERVICE_UNAVAILABLE.equals(e.getErrorCode())) { - //retry after a small pause - SimpleDBUtil.sleepBeforeRetry(attempt); - attempt++; - deleteAttributesInternal(domainName, id, attributes, attempt); - } else { - throw e; - } - } - } - } - - public void deleteAttributesVersioned(String domainName, String id, List attributes, String expectedVersion, PersistentEntity persistentEntity) throws DataAccessException { - deleteAttributesVersionedInternal(domainName, id, attributes, expectedVersion, persistentEntity, 1); - } - private void deleteAttributesVersionedInternal(String domainName, String id, List attributes, String expectedVersion, PersistentEntity persistentEntity, int attempt) throws DataAccessException { - // If attribute list is empty AWS api will erase the whole item. - // Do not do that, otherwise all the callers will have to check for empty list before calling - if (!attributes.isEmpty()) { - DeleteAttributesRequest request = new DeleteAttributesRequest(domainName, id, attributes, getOptimisticVersionCondition(expectedVersion)); - try { - sdb.deleteAttributes(request); - } catch (AmazonServiceException e) { - if (SimpleDBUtil.AWS_ERR_CODE_CONDITIONAL_CHECK_FAILED.equals(e.getErrorCode())) { - throw new OptimisticLockingException(persistentEntity, id); - } else if (SimpleDBUtil.AWS_ERR_CODE_NO_SUCH_DOMAIN.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such domain: " + domainName, e); - } else if (SimpleDBUtil.AWS_ERR_CODE_SERVICE_UNAVAILABLE.equals(e.getErrorCode())) { - //retry after a small pause - SimpleDBUtil.sleepBeforeRetry(attempt); - attempt++; - deleteAttributesVersionedInternal(domainName, id, attributes, expectedVersion, persistentEntity, attempt); - } else { - throw e; - } - } - } - } - - public void deleteItem(String domainName, String id) { - deleteItemInternal(domainName, id, 1); - } - private void deleteItemInternal(String domainName, String id, int attempt) { - DeleteAttributesRequest request = new DeleteAttributesRequest(domainName, id); - try { - sdb.deleteAttributes(request); - } catch (AmazonServiceException e) { - if (SimpleDBUtil.AWS_ERR_CODE_NO_SUCH_DOMAIN.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such domain: " + domainName, e); - } else if (SimpleDBUtil.AWS_ERR_CODE_SERVICE_UNAVAILABLE.equals(e.getErrorCode())) { - //retry after a small pause - SimpleDBUtil.sleepBeforeRetry(attempt); - attempt++; - deleteItemInternal(domainName, id, attempt); - } else { - throw e; - } - } - } - - public boolean deleteAllItems(String domainName) throws DataAccessException { - //determine the count currently - if it is small delete items individually, otherwise just drop/create domain - SelectRequest countRequest = new SelectRequest("select count(*) from `"+domainName+"`"); - List items = sdb.select(countRequest).getItems(); - int count = Integer.parseInt(items.get(0).getAttributes().get(0).getValue()); - if (count >= 2500) { - deleteDomain(domainName); - createDomain(domainName); - } else { - SelectRequest selectRequest = new SelectRequest("select itemName() from `"+domainName+"` limit 2500"); - items = sdb.select(selectRequest).getItems(); - - for (Item item : items) { - deleteItem(domainName, item.getName()); - } - } - return count > 0; - } - - public List query(String query, int max) { - return queryInternal(query, max, 1); - } - private List queryInternal(String query, int max, int attempt) { - LinkedList items = new LinkedList(); - try { - SelectRequest selectRequest = new SelectRequest(query); - SelectResult result = sdb.select(selectRequest); - items.addAll(result.getItems()); - - String nextToken = null; - do { - nextToken = result.getNextToken(); - if (nextToken != null) { - selectRequest = new SelectRequest(query).withNextToken(nextToken); - result = sdb.select(selectRequest); - items.addAll(result.getItems()); - } - } while (nextToken != null && items.size() < max); - - //truncate if needed - while (items.size() > max) { - items.removeLast(); - } - - return items; - } catch (AmazonServiceException e) { - if (SimpleDBUtil.AWS_ERR_CODE_NO_SUCH_DOMAIN.equals(e.getErrorCode())) { - throw new IllegalArgumentException("no such domain: " + query, e); - } else if (SimpleDBUtil.AWS_ERR_CODE_SERVICE_UNAVAILABLE.equals(e.getErrorCode())) { - //retry after a small pause - SimpleDBUtil.sleepBeforeRetry(attempt); - attempt++; - return queryInternal(query, max, attempt); - } else { - throw e; - } - } - } - - public void createDomain(String domainName) throws DataAccessException { - CreateDomainRequest request = new CreateDomainRequest(domainName); - sdb.createDomain(request); - } - - public List listDomains() throws DataAccessException { - ListDomainsRequest request = new ListDomainsRequest(); - ListDomainsResult result = sdb.listDomains(request); - return result.getDomainNames(); - } - - public void deleteDomain(String domainName) throws DataAccessException { - DeleteDomainRequest request = new DeleteDomainRequest(domainName); - sdb.deleteDomain(request); - } - - protected UpdateCondition getOptimisticVersionCondition(String expectedVersion) { - return new UpdateCondition("version", expectedVersion,Boolean.TRUE); - } -} diff --git a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBUtil.java b/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBUtil.java deleted file mode 100644 index 36318306f..000000000 --- a/grails-datastore-simpledb/src/main/groovy/org/grails/datastore/mapping/simpledb/util/SimpleDBUtil.java +++ /dev/null @@ -1,146 +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.mapping.simpledb.util; - -import com.amazonaws.services.simpledb.model.Attribute; -import com.amazonaws.services.simpledb.model.Item; -import com.amazonaws.services.simpledb.util.SimpleDBUtils; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.simpledb.config.SimpleDBDomainClassMappedForm; - -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -/** - * Simple util class for SimpleDB. - * - * @author Roman Stepanenko - * @since 0.1 - */ -public class SimpleDBUtil { - public static final String AWS_ERR_CODE_CONDITIONAL_CHECK_FAILED = "ConditionalCheckFailed"; - public static final String AWS_ERR_CODE_NO_SUCH_DOMAIN = "NoSuchDomain"; - public static final String AWS_ERR_CODE_SERVICE_UNAVAILABLE = "ServiceUnavailable"; - - /** - * Quotes and escapes an attribute name or domain name by wrapping it with backticks and escaping any backticks inside the name. - * @param name - * @return - */ - public static String quoteName(String name) { - return SimpleDBUtils.quoteName(name); - } - - /** - * Quotes and escapes an attribute value by wrapping it with single quotes and escaping any single quotes inside the value. - * @param value - * @return - */ - public static String quoteValue(String value) { - return SimpleDBUtils.quoteValue(value); - } - - /** - * Quotes and escapes a list of values so that they can be used in a SimpleDB query. - * @param values - * @return - */ - public static String quoteValues(Collection values) { - return SimpleDBUtils.quoteValues(values); - } - - /** - * If domainNamePrefix is not null returns prefexed domain name. - * @param domainName - * @param domainNamePrefix - * @return - */ - public static String getPrefixedDomainName(String domainNamePrefix, String domainName) { - if (domainNamePrefix != null) { - return domainNamePrefix + domainName; - } - return domainName; - } - - /** - * Returns mapped domain name (*unprefixed*) for the specified @{link PersistentEntity}. - * @param entity - * @return - */ - public static String getMappedDomainName(PersistentEntity entity) { - @SuppressWarnings("unchecked") - ClassMapping classMapping = entity.getMapping(); - SimpleDBDomainClassMappedForm mappedForm = classMapping.getMappedForm(); - String entityFamily = getFamily(entity, mappedForm); - return entityFamily; - } - - private static String getFamily(PersistentEntity persistentEntity, SimpleDBDomainClassMappedForm mappedForm) { - String table = null; - if (mappedForm != null) { - table = mappedForm.getFamily(); - } - if (table == null) table = persistentEntity.getJavaClass().getSimpleName(); - return table; - } - - public static List collectAttributeValues(Item item, String attributeName) { - List ids = new LinkedList(); - for (Attribute attribute : item.getAttributes()) { - if (attributeName.equals(attribute.getName())) { - ids.add(attribute.getValue()); - } - } - return ids; - } - - public static List collectItemNames(List items) { - if (items.isEmpty()) { - return Collections.emptyList(); - } - - List ids = new LinkedList(); - for (Item item : items) { - ids.add(item.getName()); - } - return ids; - } - - /** - * Used in case we need to re-submit request to AWS when it throws 'AWS Error Code: ServiceUnavailable, AWS Error Message: Service AmazonSimpleDB is currently unavailable. Please try again ' - * @param attemptNumber - */ - public static void sleepBeforeRetry(int attemptNumber) { - long sleepMS; - if (attemptNumber < 5) { - sleepMS = 100; - } else if (attemptNumber < 10) { - sleepMS = 1000; - } else if (attemptNumber < 15) { - sleepMS = 5000; - } else if (attemptNumber < 20) { - sleepMS = 30000; - } else { - sleepMS = 60000; - } - try { - Thread.sleep(sleepMS); - } catch (InterruptedException e) { - } - } -} diff --git a/grails-datastore-web/build.gradle b/grails-datastore-web/build.gradle deleted file mode 100644 index 9cd8e845a..000000000 --- a/grails-datastore-web/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ -dependencies { - compile project(":grails-datastore-core") - compile "org.springframework:spring-web:$springVersion", { - exclude group:'commons-logging',module:'commons-logging' - 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-aop' - } - compile "org.springframework:spring-context:$springVersion", { - exclude group:'commons-logging',module:'commons-logging' - exclude group:'org.springframework', module:'spring-core' - exclude group:'org.springframework', module:'spring-expression' - exclude group:'org.springframework', module:'spring-aop' - exclude group:'org.springframework', module:'spring-beans' - exclude group:'org.springframework', module:'spring-asm' - } -} diff --git a/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/web/support/OpenSessionInViewInterceptor.java b/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/web/support/OpenSessionInViewInterceptor.java deleted file mode 100644 index ddb31df95..000000000 --- a/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/web/support/OpenSessionInViewInterceptor.java +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (C) 2010 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.mapping.web.support; - -import javax.persistence.FlushModeType; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.core.DatastoreUtils; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.transactions.SessionHolder; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.ui.ModelMap; -import org.springframework.web.context.request.WebRequest; -import org.springframework.web.context.request.WebRequestInterceptor; - -/** - * A {@link org.springframework.web.context.request.WebRequestInterceptor} instance that - * handles opening a Datastore session within the scope of a request - */ -public class OpenSessionInViewInterceptor implements WebRequestInterceptor { - - private static final Log LOG = LogFactory.getLog(OpenSessionInViewInterceptor.class); - - Datastore datastore; - FlushModeType flushMode = FlushModeType.AUTO; - - public void setDatastore(Datastore datastore) { - this.datastore = datastore; - } - - public Datastore getDatastore() { - return datastore; - } - - public void preHandle(WebRequest webRequest) throws Exception { - if (hasSessionBound()) { - return; - } - - // single session mode - LOG.debug("Opening single Datastore Session in OpenSessionInViewInterceptor"); - - Session session = DatastoreUtils.getSession(datastore, true); - session.setFlushMode(flushMode); - if (!hasSessionBound()) { - DatastoreUtils.bindSession(session); - } - } - - public void postHandle(WebRequest webRequest, ModelMap modelMap) throws Exception { - // Only potentially flush in single session mode. - if (!hasSessionBound()) { - return; - } - - SessionHolder sessionHolder = - (SessionHolder) TransactionSynchronizationManager.getResource(getDatastore()); - LOG.debug("Flushing single Datastore Session in OpenSessionInViewInterceptor"); - final Session session = sessionHolder.getSession(); - - if (session.getFlushMode() == FlushModeType.AUTO) { - session.flush(); - } - } - - protected boolean hasSessionBound() { - return TransactionSynchronizationManager.getResource(getDatastore()) != null; - } - - public void afterCompletion(WebRequest webRequest, Exception e) throws Exception { - if (!hasSessionBound()) { - return; - } - - // single session mode - SessionHolder sessionHolder = - (SessionHolder) TransactionSynchronizationManager.unbindResource(getDatastore()); - LOG.debug("Closing single Datastore Session in OpenSessionInViewInterceptor"); - DatastoreUtils.closeSession(sessionHolder.getSession()); - } -} diff --git a/grails-documentation-core/build.gradle b/grails-documentation-core/build.gradle deleted file mode 100644 index 27d21832e..000000000 --- a/grails-documentation-core/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -task assemble(dependsOn:docs) << { - group = "docs" -} \ No newline at end of file diff --git a/grails-documentation-core/src/docs/doc.properties b/grails-documentation-core/src/docs/doc.properties deleted file mode 100644 index c7b0a329c..000000000 --- a/grails-documentation-core/src/docs/doc.properties +++ /dev/null @@ -1,3 +0,0 @@ -title=GORM Datastore API -version=1.0.0 -authors=Graeme Rocher \ No newline at end of file diff --git a/grails-documentation-core/src/docs/guide/1. Introduction.gdoc b/grails-documentation-core/src/docs/guide/1. Introduction.gdoc deleted file mode 100644 index 30450ce5b..000000000 --- a/grails-documentation-core/src/docs/guide/1. Introduction.gdoc +++ /dev/null @@ -1,19 +0,0 @@ -This documentation describes the GORM API mechanics and how a datastore implementation can be built to interface to any database providing a GORM API onto it. This documentation is mainly targeted at developers interested in creating implementations of GORM ontop of alternative datastores. - -As of this writing the project has several implementations of GORM against a variety of different datastore implementations. Current implementations include: - -* Hibernate (currently part of the Grails source code) -* JPA -* MongoDB -* Redis -* Neo4j -* Riak -* Amazon SimpleDB -* java.util.ConcurrentHashMap (the fastest datastore in the world) - -The remainder of this document describes how to project is structured, how to build a project and how to implement a GORM provider. - - - - - diff --git a/grails-documentation-core/src/docs/guide/2. Getting Started.gdoc b/grails-documentation-core/src/docs/guide/2. Getting Started.gdoc deleted file mode 100644 index d69be20f6..000000000 --- a/grails-documentation-core/src/docs/guide/2. Getting Started.gdoc +++ /dev/null @@ -1,81 +0,0 @@ -h3. Checking out and Building - -The project is currently hosted on Github at [https://github.com/SpringSource/grails-data-mapping]. - -You are free to fork the project from there or clone it anonymously using git: - -{code} -git clone git@github.com:SpringSource/grails-data-mapping.git -cd grails-data-mapping -{code} - -The project has a [Gradle|http://gradle.org] build. You can generate Eclipse or Intellij project files to open the project using: - -{code} -./gradlew eclipse -{code} - -Or - -{code} -./gradlew idea -{code} - -Once this is done your can import the project into Eclipse, or in the case of Intellij open up the generated @grails-data-mapping.ipr@ file. - -{note} -The version of Gradle used has a bug whereby a subproject is generated for the root directory called "grails-data-mapping". You should remove this subproject from your Intellij Modules or delete it it from Eclipse. -{note} - -To build the project you can run the @assemble@ task: - -{code} -./gradlew assemble -{code} - -To install the jar files for the various subprojects into your local Maven repository you can run: - -{code} -./gradlew install -{code} - -To build all of the documentation run the command: - -{code} -./gradlew allDocs -{code} - -Documentation will produced in the @build/docs@ directory. - -{note} -If you experience PermGen errors when building documentation you may need to increase the JVM permgen inside GRADLE_OPTS -{note} - -h3. Project Structure - -The project is essentially a multi-project Gradle build. There is a core API and then subprojects that implement that API. The core API subprojects include: - -* @grails-datastore-core@ - The core API, this provides core interfaces for implementing a GORM provider -* @grails-datastore-gorm@ - The runtime meta-programming and AST transformation infrastructure behind GORM. Also provides end users APIs like @grails.gorm.CriteriaBuilder@ and @grails.gorm.DetachedCriteria@ -* @grails-datastore-gorm-plugin-support@ - Support classes for easing the writing of a GORM plugin for Grails -* @grails-datastore-gorm-tck@ - The TCK that includes hundreds of Spock specifications that a GORM implementation will need to pass -* @grails-datastore-web@ - Classes required to integrate GORM into a web tier - -Beyond these core subprojects there are implementations for various datastores. For example: - -* @grails-datastore-gemfire/grails-datastore-gorm-gemfire@ - GORM for Gemfire project [http://grails.org/plugin/gemfire] -* @grails-datastore-jpa/grails-datastore-gorm-jpa@ - GORM for JPA project [http://grails.org/plugin/gorm-jpa] -* @grails-datastore-mongo/grails-datastore-gorm-mongo@ - GORM for MongoDB project [http://grails.org/plugin/mongodb] -* @grails-datastore-neo4j@ - GORM for Neo4j project [http://grails.org/plugin/neo4j] -* @grails-datastore-redis/grails-datastore-gorm-redis@ - GORM for Redis project [http://grails.org/plugin/redis] -* @grails-datastore-riak/grails-datastore-gorm-riak@ - GORM for Riak project [http://grails.org/plugin/riak] -* @grails-datastore-simpledb/grails-datastore-gorm-simpledb@ - GORM for SimpleDB project [http://grails.org/plugin/simpledb] - -Some implementations are split into 2 subprojects others are not. It depends whether the author chooses to divide the Java parts and the Groovy parts of the project implementation. It is not a requirement to do so. - -The documentation for each implementation is kept in the documentation subprojects that start with @grails-documentation@. There are documentation projects for the core API, MongoDB, Neo4j, Redis, Riak and Amazon SimpleDB. - -Finally the Grails plugins that are used to distribute the GORM implementations to end users can be found in the @grails-plugins@ directory. - - - diff --git a/grails-documentation-core/src/docs/guide/3. Understanding the Low-level API.gdoc b/grails-documentation-core/src/docs/guide/3. Understanding the Low-level API.gdoc deleted file mode 100644 index e7535332d..000000000 --- a/grails-documentation-core/src/docs/guide/3. Understanding the Low-level API.gdoc +++ /dev/null @@ -1,7 +0,0 @@ -h3. Introduction - -The GORM Datastore API is split into a low-level API that implementors need to implement for each individual datastore and then set of higher level APIs that enhance domain classes with things regular users see such as dynamic finders, criteria queries and so on. - -The low-level API classes are found in the @grails-datastore-core@ subproject, whilst the higher level APIs used to enhance domain classes are found in @grails-datastore-gorm@. In this section we will discuss the low-level API. - - diff --git a/grails-documentation-core/src/docs/guide/3.1 Datastore Basics.gdoc b/grails-documentation-core/src/docs/guide/3.1 Datastore Basics.gdoc deleted file mode 100644 index 3d3f7ac54..000000000 --- a/grails-documentation-core/src/docs/guide/3.1 Datastore Basics.gdoc +++ /dev/null @@ -1,90 +0,0 @@ -h3. The MappingContext - -The @org.grails.datastore.mapping.model.MappingContext@ interface is used to obtain metadata about the classes that are configured for persistence. There are @org.grails.datastore.mapping.model.PersistentEntity@ and @org.grails.datastore.mapping.model.PersistentProperty@ interfaces that represent a class and its properties respectively. These can be obtained and introspected via the @MappingContext@. - -There are various concrete implementations of the @MappingContext@ interface such as: - -* @DocumentMappingContext@ - Used for document stores, subclassed by @MongoMappingContext@ -* @JpaMappingContext@ - Used for JPA -* @KeyValueMappingContext@ - Used by key/value stores - -Creating a new @MappingContext@ may be useful because it allows users to configure how a class is mapped to the underlying datastore using GORM's @mapping@ block as well as allowing registration of custom type converters and so on. The implementation for Neo4j looks like this: - -{code} -class Neo4jMappingContext extends AbstractMappingContext { - - MappingFactory mappingFactory - MappingConfigurationStrategy syntaxStrategy - - Neo4jMappingContext() { - mappingFactory = new GraphGormMappingFactory() - syntaxStrategy = new GormMappingConfigurationStrategy(mappingFactory) - //addTypeConverter(new StringToNumberConverterFactory().getConverter(BigDecimal)) - addTypeConverter(new StringToShortConverter()) - addTypeConverter(new StringToBigIntegerConverter()) - ... - } - - @Override - protected PersistentEntity createPersistentEntity(Class javaClass) { - GraphPersistentEntity persistentEntity = new GraphPersistentEntity(javaClass, this) - mappingFactory.createMappedForm(persistentEntity) // populates mappingFactory.entityToPropertyMap as a side effect - persistentEntity - } - - MappingConfigurationStrategy getMappingSyntaxStrategy() { - syntaxStrategy - } - - MappingFactory getMappingFactory() { - mappingFactory - } -} -{code} - - -Notice how Neo4j provides a custom @GraphGormMappingFactory@ and @GraphPersistentEntity@ to allow the domain class configuration to be changed for a given Neo4j @Node@. - -h3. The Datastore Interface - -The @org.grails.datastore.mapping.core.Datastore@ interface is the equivalent of a SQL @DataSource@ where by it provides the necessary capability to create a connection. In most cases one can simply subclass the @AbstractDatastore@ super class and implement the @createSession@ method. The following implementation is from the @SimpleMapDatastore@ which implements GORM ontop of a @ConcurrentHashMap@: - -{code} -@Override -protected Session createSession(Map connectionDetails) { - return new SimpleMapSession(this, getMappingContext(), getApplicationEventPublisher()); -} -{code} - -The implementation depends a lot on the underlying datastore. For example for JPA the following implementation is used: - -{code} -@Override -protected Session createSession(Map connDetails) { - return new JpaSession(this, new JpaTemplate(entityManagerFactory), transactionManager); -} -{code} - -Notice that the @Datastore@ also has a reference to the @MappingContext@ discussed in the previous section. - - -h3. The Session Interface - -The @org.grails.datastore.mapping.core.Session@ interface represents an active connection. It can be either stateful or stateless, depending on the implementation. For example of embedded databases where there is no network connection, a stateful session is not particularly useful, but a datastore that creates network connections you may want to cache returned instances to reduce load. - -The @AbstractSession@ class provides some support for creating stateful sessions, if you prefer a stateless implementation then simply implement @Session@ or subclass @AbstractAttributeStoringSession@. - -In general if you subclass @AbstractSession@ the minimum you need to do is implement the @createPersister@ method: - -{code} -protected Persister createPersister(Class cls, MappingContext mappingContext) { - PersistentEntity entity = mappingContext.getPersistentEntity(cls.getName()); - if (entity == null) { - return null; - } - return new SimpleMapEntityPersister(mappingContext, entity, this, - (SimpleMapDatastore) getDatastore(), publisher); -} -{code} - -The example above is from the @SimpleMapSession@ implementation, which creates a @SimpleMapEntityPersister@ instance and returns it. Returning null indicates that the class cannot be persisted and an exception will be thrown \ No newline at end of file diff --git a/grails-documentation-core/src/docs/guide/3.2 Implementing CRUD.gdoc b/grails-documentation-core/src/docs/guide/3.2 Implementing CRUD.gdoc deleted file mode 100644 index 3fcf330cb..000000000 --- a/grails-documentation-core/src/docs/guide/3.2 Implementing CRUD.gdoc +++ /dev/null @@ -1,173 +0,0 @@ -h4. The EntityPersister Interface - -The @EntityPersister@ interface is used to implement the basic Create, Read, Update and Delete (CRUD) operations. There are individual methods to implement such as @persistEntity@, @updateEntity@, @deleteEntity@ and so on. - -In many cases there is a representation of an entity in its "native" form as supplied by the datastore driver. For example in Cassandra this could be a @ColumnFamily@, or in MongoDB a @DBCollection@. - -To support implementation such cases there is an abstract @NativeEntryEntityPersister@ super class that provides the basis for an implementation that maps a native entry, such as a MongoDB @DBObject@ or a Neo4j @Node@ to a persist entity and back again. - -The 2 generic types of this superclass indicate the native entry type (example @DBObject@ in MongoDB) and the native key type (example @ObjectId@ in MongoDB). The MongoDB implementation looks like this: - -{code} -public class MongoEntityPersister extends NativeEntryEntityPersister -{code} - -Note that @Object@ is used for the key since MongoDB also supports Long and String-based identifiers. - -They key methods that need implementing are defined below: - -* @getEntityFamily()@ - Defines the the name of the entity group or family. This could be a database table, a Cassandra Column Family or a MongoDB collection. -* @T createNewEntry(String family)@ - Creates a native entry ready to be inserted -* @Object getEntryValue(T nativeEntry, String property)@ - Retrieves a value of entry and returns its Java object form. For example a "date" property stored as a String in the datastore would need to b returned as a java.util.Date at this point -* @setEntryValue(T nativeEntry, String key, Object value)@ - Sets a value of the native entry, converting any Java objects to the required native format -* @deleteEntry(String family, K key, Object entry)@ - Deletes an entry for the given family, native key and entry -* @T retrieveEntry(PersistentEntity persistentEntity, String family, Serializable key)@ - Retrieves a native entry for the given entity, family and key -* @K storeEntry(PersistentEntity persistentEntity, EntityAccess entityAccess, K storeId, T nativeEntry)@ - Stores a native entry for the given id -* @updateEntry(PersistentEntity persistentEntity, EntityAccess entityAccess, K key, T entry)@ - Updates an entry -* @K generateIdentifier(PersistentEntity persistentEntity, T entry)@ - Generate an identifier for the given native entry -* @PropertyValueIndexer getPropertyIndexer(PersistentProperty property)@ - If the datastore requires manual indexing you'll need to implement a @PropertyIndexer@ otherwise return null -* @AssociationIndexer getAssociationIndexer(T nativeEntry, Association association)@ - If the datastore requires manual indexing you'll need to implement a @AssociationIndexer@ otherwise return null - - - - -h4. Create - -The @createNewEntry@ method is used to create a native record that will be inserted into the datastore. In MongoDB this is a @DBObject@ whilst in the implementation for @ConcurrentHashMap@ it is another @Map@: - -{code} -@Override -protected DBObject createNewEntry(String family) { - return new BasicDBObject(); -} -{code} - -h4. Read - -The @retrieveEntry@ method is used to retrieve a native record for a given key: - -{code} -protected DBObject retrieveEntry(final PersistentEntity persistentEntity, - String family, final Serializable key) { - return mongoTemplate.execute(new DbCallback() { - public DBObject doInDB(DB con) throws MongoException, DataAccessException { - DBCollection dbCollection = con.getCollection(getCollectionName(persistentEntity)); - return dbCollection.findOne(key); - } - }); -} -{code} - -Here you can see the @MongoDB@ implementation that uses a Spring Data @MongoTemplate@ to find a @DBObject@ for the given key. There is a separate @storeEntry@ method that is used to actually store the native object. In @MongoDB@ this looks like: - -{code} -@Override -protected Object storeEntry(final PersistentEntity persistentEntity, final EntityAccess entityAccess, - final Object storeId, final DBObject nativeEntry) { - return mongoTemplate.execute(new DbCallback() { - public Object doInDB(DB con) throws MongoException, DataAccessException { - nativeEntry.put(MONGO_ID_FIELD, storeId); - return storeId; - } - }); -} -{code} - -Notice it doesn't actually do anything native insert into a MongoDB collection. This is because the Datastore API supports the notion of batch insert operations and flushing. In the case of @MongoDB@ the @MongoSession@ implementation overrides the @flushPendingInserts@ method of @AbstractSession@ and performs a batch insert of multiple MongoDB documents (ie @DBObject@s) at once: - -{code} -collection.insert(dbObjects.toArray(new DBObject[dbObjects.size()]), writeConcernToUse); -{code} - -Other datastores that do not support batch inserts would instead to the insert in the @storeEntry@ method itself. For example the implementation for @ConcurrentHashMap@ looks like (note Groovy code): - -{code} -protected storeEntry(PersistentEntity persistentEntity, EntityAccess entityAccess, storeId, Map nativeEntry) { - if (!persistentEntity.root) { - nativeEntry.discriminator = persistentEntity.discriminator - } - datastore[family].put(storeId, nativeEntry) - return storeId -} -{code} - -h4. Update - -The @updateEntry@ method is used to update an entry: - -{code} -public void updateEntry(final PersistentEntity persistentEntity, final EntityAccess ea, - final Object key, final DBObject entry) { - mongoTemplate.execute(new DbCallback() { - public Object doInDB(DB con) throws MongoException, DataAccessException { - String collectionName = getCollectionName(persistentEntity, entry); - DBCollection dbCollection = con.getCollection(collectionName); - if (isVersioned(ea)) { - // TODO this should be done with a CAS approach if possible - DBObject previous = dbCollection.findOne(key); - checkVersion(ea, previous, persistentEntity, key); - } - - MongoSession mongoSession = (MongoSession) session; - dbCollection.update(dbo, entry, false, false, mongoSession.getWriteConcern()); - return null; - } - }); -} -{code} - -As you can see again the underlying database specific @update@ method is used, in this case the @DBCollection@'s @update@ method. - -h4. Delete - -The @deleteEntry@ method is used to delete an entry. For example in the @ConcurrentHashMap@ implementation it is simply removed from the map: - -{code} -protected void deleteEntry(String family, key, entry) { - datastore[family].remove(key) -} -{code} - -Whilst in @MongoDB@ the @DBCollection@ object's @remove@ method is called: - -{code} -@Override -protected void deleteEntry(String family, final Object key, final Object entry) { - mongoTemplate.execute(new DbCallback() { - public Object doInDB(DB con) throws MongoException, DataAccessException { - DBCollection dbCollection = getCollection(con); - - MongoSession mongoSession = (MongoSession) session; - dbCollection.remove(key, mongoSession.getWriteConcern()); - return null; - } - - protected DBCollection getCollection(DB con) { - return con.getCollection(getCollectionName(getPersistentEntity())); - } - }); -} -{code} - -Note that if the underlying datastore supports batch delete operations you may want override and implement the @deleteEntries@ method which allows for deleting multiple entries in a single operation. The implementation for MongoDB looks like: - -{code} -protected void deleteEntries(String family, final List keys) { - mongoTemplate.execute(new DbCallback() { - public Object doInDB(DB con) throws MongoException, DataAccessException { - String collectionName = getCollectionName(getPersistentEntity()); - DBCollection dbCollection = con.getCollection(collectionName); - - MongoSession mongoSession = (MongoSession) getSession(); - MongoQuery query = mongoSession.createQuery(getPersistentEntity().getJavaClass()); - query.in(getPersistentEntity().getIdentity().getName(), keys); - - dbCollection.remove(query.getMongoQuery()); - - return null; - } - }); -} -{code} - -You'll notice this implementation uses a @MongoQuery@ instance. Note that implementing an @EntityPersister@ you have enabled basic CRUD operations, but not querying, which is a topic of the following sections. First, however secondary indices need to covered since they are required for querying. \ No newline at end of file diff --git a/grails-documentation-core/src/docs/guide/3.3 Secondary Indices.gdoc b/grails-documentation-core/src/docs/guide/3.3 Secondary Indices.gdoc deleted file mode 100644 index 95e02a22f..000000000 --- a/grails-documentation-core/src/docs/guide/3.3 Secondary Indices.gdoc +++ /dev/null @@ -1,64 +0,0 @@ -Many datastores do not support secondary indices or require you to build your own. In cases like this you will need to implement a @PropertyIndexer@. - -{note} -If the underlying datastore supports secondary indexes then it is ok to just return a @null@ PropertyIndexer and let the datastore handle the indexing -{note} - -For example the @ConcurrentHashMap@ implementation creates secondary indices by populating another @Map@ containing the indices: - -{code} -void index(value, primaryKey) { - - def index = getIndexName(value) - def indexed = indices[index] - if (indexed == null) { - indexed = [] - indices[index] = indexed - } - if (!indexed.contains(primaryKey)) { - indexed << primaryKey - } -} -{code} - -The implementation for Redis is very similar and stores the primary key in a Redis set: - -{code} -public void index(final Object value, final Long primaryKey) { - if (value == null) { - return; - } - final String primaryIndex = createRedisKey(value); - redisTemplate.sadd(primaryIndex, primaryKey); -} - -{code} - -An index name is typically built from the entity name, property name and property value. The primary key of the entity is stored in this index for later querying. In fact there is a @query@ method that needs to be implemented on @PropertyIndexer@. The @ConcurrentHashMap@ implementation looks like this: - -{code} -List query(value, int offset, int max) { - def index = getIndexName(value) - - def indexed = indices[index] - if (!indexed) { - return Collections.emptyList() - } - return indexed[offset..max] -} -{code} - -Depending on the characteristics of the underlying database you may want to do the indexing asynchronously or you may want to index into a search library such as Lucene. For datastores that are eventually consistent for example it makes sense to do all indexing asynchronously. - -Finally, when an object is deleted it will need to removed from the indices. This can be done with the @deindex@ method: - -{code} -void deindex(value, primaryKey) { - def index = getIndexName(value) - def indexed = indices[index] - if (indexed) { - indexed.remove(primaryKey) - } -} -{code} - diff --git a/grails-documentation-core/src/docs/guide/3.4 Implementing Querying.gdoc b/grails-documentation-core/src/docs/guide/3.4 Implementing Querying.gdoc deleted file mode 100644 index 814f977a9..000000000 --- a/grails-documentation-core/src/docs/guide/3.4 Implementing Querying.gdoc +++ /dev/null @@ -1,97 +0,0 @@ -h3. Introduction - -The @org.grails.datastore.mapping.query.Query@ abstract class defines the query model and it is the job of the GORM implementor to translate this query model into an underlying database query. This is different depending on the implementation and may involve: - -* Generating a String-based query such as SQL or JPA-QL -* Creating a query object such as MongoDB's use of a @DBObject@ to define queries -* Generating for use with manually created Secondary indices as is the case with Redis - -The @Query@ object defines the following: - -* One or many @Criterion@ that define the criteria to query by. -* Zero or many @Projection@ instances that define what the data you want back will look like. -* Pagination parameters such as @max@, @offset@ -* Sorting parameters - -There are many types of @Criterion@ for each specific type of query, examples include @Equals@, @Between@, @Like@ etc. Depending on the capabilities of the underlying datastore you may implement only a few of these. - -There are also many types of @Projection@ such as @SumProjection@, @MaxProjection@ and @CountProjection@. Again you may implement only a few of these. - -{note} -If the underlying datastore doesn't for example support calculating a @sum@ or @max@ of a particular property, there is a @ManualProjections@ class that you can use to perform these operations in memory on the client. -{note} - -Writing a @Query@ implementation is probably the most complex part of implementing a GORM provider, but starts by subclassing the @Query@ class and implementing the @executeQuery@ method: - -{code} -public class MongoQuery extends Query implements QueryArgumentsAware { - ... - -} -{code} - -h3. Using the Query Model - -To implement querying you need to understand the Query model. As discussed a @Query@ contains a list of @Criterion@, however the root @Criterion@ could be a conjunction (an AND query) or a disjunction (an OR query). The @Query@ may also contain a combination of regular criterion (=, !=, LIKE etc.) and junctions (AND, OR or NOT). Implementing a @Query@ therefore requires writing a recursive method. The implementation for @ConcurrentHashMap@ looks like - -{code} -Collection executeSubQueryInternal(criteria, criteriaList) { - SimpleMapResultList resultList = new SimpleMapResultList(this) - for (Query.Criterion criterion in criteriaList) { - if (criterion instanceof Query.Junction) { - resultList.results << executeSubQueryInternal(criterion, criterion.criteria) - } - else { - PersistentProperty property = getValidProperty(criterion) - def handler = handlers[criterion.getClass()] - - def results = handler?.call(criterion, property) ?: [] - resultList.results << results - } - } -} -{code} - -Notice that if a @Junction@ is encountered (which represents an AND, OR or NOT) then the method recurses to handle the junctions, otherwise a handler for the @Criterion@ class is obtained and executed. The @handlers@ map is a map of @Criterion@ class to query handlers. The implementation for @Equals@ looks like: - -{code} -def handlers = [ - ... - (Query.Equals): { Query.Equals equals, PersistentProperty property-> - def indexer = entityPersister.getPropertyIndexer(property) - final value = subqueryIfNecessary(equals) - return indexer.query(value) - } - ... -] -{code} - -Which simply uses the property indexer to query for all identifiers. Of course here we are a describing a case of a datastore (in this case @ConcurrentHashMap@) which doesn't support secondary indices. It may be that instead of manually querying the secondary indices in this way that you simply build a String-based or native query. For example in MongoDB this looks like: - -{code} -queryHandlers.put(Equals.class, new QueryHandler() { - public void handle(PersistentEntity entity, Equals criterion, DBObject query) { - String propertyName = getPropertyName(entity, criterion); - Object value = criterion.getValue(); - PersistentProperty property = entity.getPropertyByName(criterion.getProperty()); - MongoEntityPersister.setDBObjectValue(query, propertyName, value, entity.getMappingContext()); - } -}); -{code} - -Notice how the query in this case is a @DBObject@. For Gemfire again the implementation is different: - -{code} -queryHandlers.put(Equals.class, new QueryHandler() { - public int handle(PersistentEntity entity, Criterion criterion, StringBuilder q, List params, int index) { - Equals eq = (Equals) criterion; - final String name = eq.getProperty(); - validateProperty(entity, name, Equals.class); - - q.append(calculateName(entity, name)); - return appendOrEmbedValue(q, params, index, eq.getValue(), EQUALS); - } -}); -{code} - -In this case a @StringBuilder@ is used to construct a OQL query from the @Query@ model. \ No newline at end of file diff --git a/grails-documentation-core/src/docs/guide/4. GORM Enhancer.gdoc b/grails-documentation-core/src/docs/guide/4. GORM Enhancer.gdoc deleted file mode 100644 index a1ae4419d..000000000 --- a/grails-documentation-core/src/docs/guide/4. GORM Enhancer.gdoc +++ /dev/null @@ -1,37 +0,0 @@ -Once you have implemented the lower-level APIs you can trivially provide a GORM API to a set of Grails domain classes. For example consider the following simple domain class: - -{code} -import grails.persistence.* - -@Entity -class Book { - String title -} -{code} - - -The following setup code can be written to enable GORM for MongoDB: - -{code} -// create context -def context = new MongoMappingContext(databaseName) -context.addPersistentEntity(Book) - -// create datastore -def mongoDatastore = new MongoDatastore(context) -mongoDatastore.afterPropertiesSet() - -// enhance -def enhancer = new MongoGormEnhancer(mongoDatastore, new DatastoreTransactionManager(datastore: mongoDatastore)) -enhancer.enhance() - -// use GORM! -def books = Book.list() -{code} - -They key part to enabling the usage of all the GORM methods (@list()@, dynamic finders etc.) is the usage of the @MongoGormEnhancer@. This class subclasses @org.grails.datastore.gorm.GormEnhancer@ and provides some extensions to GORM specific to MongoDB. A subclass is not required however and if you don't require any datastore specific extensions you can just as easily use the regular @GormEnhancer@: - -{code} -def enhancer = new GormEnhancer(mongoDatastore, new DatastoreTransactionManager(datastore: mongoDatastore)) -enhancer.enhance() -{code} \ No newline at end of file diff --git a/grails-documentation-core/src/docs/guide/4.1 GORM APIs.gdoc b/grails-documentation-core/src/docs/guide/4.1 GORM APIs.gdoc deleted file mode 100644 index c56c8cfdd..000000000 --- a/grails-documentation-core/src/docs/guide/4.1 GORM APIs.gdoc +++ /dev/null @@ -1,39 +0,0 @@ -The @GormEnhancer@ class defines three methods called @getStaticApi@, @getInstanceApi@ and @getValidationApi@ that return instances of @GormStaticApi@, @GormInstanceApi@ and @GormValidationApi@ respectively. If you wish to provide custom GORM functionality then you can subclass each of these and override one of the aforementioned methods to provide said functionality. - -For example GORM for MongoDB does this to provide access to the underlying @DBCollection@: - -{code} -class MongoGormStaticApi extends GormStaticApi { - ... - /** - * The actual collection that this entity maps to. - * - * @return The actual collection - */ - DBCollection getCollection() { - MongoDatastore ms = datastore - def template = ms.getMongoTemplate(persistentEntity) - - def coll = template.getCollection(ms.getCollectionName(persistentEntity)) - DBCollectionPatcher.patch(coll) - return coll - } -} -{code} - -With this method in place users of GORM for MongoDB can access the underlying MongoDB API directly: - -{code} -def dbo = Book.collection.findOne() -{code} - -The enable usage of this API the @MongoGormEnhancer@ extends and overrides the @getStaticApi@ method: - -{code} -class MongoGormEnhancer extends GormEnhancer { - ... - protected GormStaticApi getStaticApi(Class cls) { - return new MongoGormStaticApi(cls, datastore, finders) - } -} -{code} \ No newline at end of file diff --git a/grails-documentation-core/src/docs/guide/5. Using the Test Compatibility Kit.gdoc b/grails-documentation-core/src/docs/guide/5. Using the Test Compatibility Kit.gdoc deleted file mode 100644 index 8106f04ba..000000000 --- a/grails-documentation-core/src/docs/guide/5. Using the Test Compatibility Kit.gdoc +++ /dev/null @@ -1,56 +0,0 @@ -The @grails-datastore-gorm-tck@ project provides a few hundred tests that ensure a particular GORM implementation is compliant. To use the TCK you need to define a dependency on the TCK in the subprojects @build.gradle@ file: - -{code} -testCompile project(':grails-datastore-gorm-tck') -{code} - -Then create a @Setup.groovy@ file that sets up your custom datastore in your implementation. - -For example the @ConcurrentHashMap@ implementation has one defined in @grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/Setup.groovy@: - -{code} -class Setup { - - static destroy() { - // noop - } - static Session setup(classes) { - - def ctx = new GenericApplicationContext() - ctx.refresh() - def simple = new SimpleMapDatastore(ctx) - - ... - for (cls in classes) { - simple.mappingContext.addPersistentEntity(cls) - } - - ... - def enhancer = new GormEnhancer(simple, new DatastoreTransactionManager(datastore: simple)) - enhancer.enhance() - - simple.mappingContext.addMappingContextListener({ e -> enhancer.enhance e } as MappingContext.Listener) - - simple.applicationContext.addApplicationListener new DomainEventListener(simple) - simple.applicationContext.addApplicationListener new AutoTimestampEventListener(simple) - - return simple.connect() - } -} -{code} - -Some setup code has been omitted for clarity but basically the @Setup.groovy@ class should initiase the @Datastore@ and return a @Session@ from the static @setup@ method which gets passed a list of classes that need to be configured. - -With this done all of the TCK tests will run against the subproject. If a particular test cannot be implemented because the underlying datastore doesn't support the feature then you can create a test that matches the name of the test that is failing and it will override said test. - -For example SimpleDB doesn't support pagination so there is a @grails.gorm.tests.PagedResultSpec@ class that overrides the one from the TCK. Each test is a Spock specification and Spock has an @Ignore@ annotation that can be used to ignore a particular test: - -{code} -/** - * Ignored for SimpleDB because SimpleDB doesn't support pagination - */ -@Ignore -class PagedResultSpec extends GormDatastoreSpec{ - ... -} -{code} \ No newline at end of file diff --git a/grails-documentation-core/src/docs/guide/6. Creating a GORM implementatio Step by Step.gdoc b/grails-documentation-core/src/docs/guide/6. Creating a GORM implementatio Step by Step.gdoc deleted file mode 100644 index 2b6550a99..000000000 --- a/grails-documentation-core/src/docs/guide/6. Creating a GORM implementatio Step by Step.gdoc +++ /dev/null @@ -1,140 +0,0 @@ -To get started with your a new GORM implementation the following steps are required: - -h3. Initial Directory Creation - -{code} -$ git clone git@github.com:SpringSource/grails-data-mapping.git -$ cd grails-data-mapping -$ mkdir grails-datastore-gorm-xyz - -{code} - -h3. Setup Gradle Build - -Create build.gradle: - -{code} -$ vi grails-datastore-gorm-xyz/build.gradle -{code} - -With contents: - -{code} -dependencies { - compile project(':grails-datastore-gorm'), - project(':grails-datastore-web'), - project(':grails-datastore-gorm-plugin-support') - - testCompile project(':grails-datastore-gorm-test'), - project(':grails-datastore-gorm-tck') - testRuntime 'javax.servlet:servlet-api:2.5' - testRuntime 'org.grails:grails-gorm:$grailsVersion' - testRuntime 'org.grails:grails-web:$grailsVersion' - -} -{code} - -Add new project to settings.gradle in root project: - -{code} -$ vi settings.gradle -{code} - -Changes shown below: - -{code} -// GORM Implementations -'grails-datastore-gorm-jpa', -'grails-datastore-gorm-neo4j', -'grails-datastore-gorm-xyz', -.... -{code} - -h3. Create Project Source Directories - -{code} -$ mkdir grails-datastore-gorm-xyz/src/main/groovy -$ mkdir grails-datastore-gorm-xyz/src/test/groovy -{code} - -h3. Generate IDE Project Files and Import into IDE - -{code} -$ gradlew grails-datastore-gorm-xyz:idea -{code} - -Or - -{code} -$ gradlew grails-datastore-gorm-xyz:eclipse -{code} - -h3. Implement Required Interfaces - -In @src/main/groovy@ create implementations: - -* @org.grails.datastore.xyz.XyzDatastore@ extends and implements @org.grails.datastore.mapping.core.AbstractDatastore@ -* @org.grails.datastore.xyz.XyzSession@ extends and implements @org.grails.datastore.mapping.core.AbstractSession@ -* @org.grails.datastore.xyz.engine.XyzEntityPersister@ extends and implements @org.grails.datastore.mapping.engine.NativeEntryEntityPersister@ -* @org.grails.datastore.xyz.query.XyzQuery@ extends and implements @org.grails.datastore.mapping.query.Query@ - -h3. Create Test Suite - -In @src/test/groovy@ create @org.grails.datastore.gorm.Setup@ class to configure TCK: - -{code} -class Setup { - - static xyz - static destroy() { - xyz.disconnect() - } - static Session setup(classes) { - def ctx = new GenericApplicationContext() - ctx.refresh() - xyz = new XyzDatastore(ctx) - for (cls in classes) { - xyz.mappingContext.addPersistentEntity(cls) - } - - - def enhancer = new GormEnhancer(xyz, new DatastoreTransactionManager(datastore: xyz)) - enhancer.enhance() - - xyz.mappingContext.addMappingContextListener({ e -> enhancer.enhance e } as MappingContext.Listener) - xyz.applicationContext.addApplicationListener new DomainEventListener(xyz) - xyz.applicationContext.addApplicationListener new AutoTimestampEventListener(xyz) - - xyz.connect() - } -} - -{code} - -Then in @src/test/groovy@ create test suite class to allow running tests in IDE (without this you won't be able to run TCK tests from the IDE). Example test suite: - -{code} -package org.grails.datastore.gorm - -import org.junit.runners.Suite.SuiteClasses -import org.junit.runners.Suite -import org.junit.runner.RunWith -import grails.gorm.tests.* - -/** - * @author graemerocher - */ -@RunWith(Suite) -@SuiteClasses([ - FindByMethodSpec, - ListOrderBySpec -]) -class XyzTestSuite { -} - -{code} - -h3. Implement the TCK! - -Keep iterating until you have implemented all the tests in the TCK. - diff --git a/grails-documentation-core/src/docs/ref/Implementations/ConcurrentHashMap.gdoc b/grails-documentation-core/src/docs/ref/Implementations/ConcurrentHashMap.gdoc deleted file mode 100644 index 0ad1d7cef..000000000 --- a/grails-documentation-core/src/docs/ref/Implementations/ConcurrentHashMap.gdoc +++ /dev/null @@ -1,13 +0,0 @@ -h1. ConcurrentHashMap - -h2. Purpose - -An implementation that creates a GORM API on top of @java.util.ConcurrentHashMap@. Designed for use with unit testing to emulate the GORM API without an actual database being involved. - -h2. Description - -Sub-projects: - -* @grails-datastore-simple@ -* @grails-datastore-gorm-test@ - diff --git a/grails-documentation-core/src/docs/ref/Implementations/Hibernate.gdoc b/grails-documentation-core/src/docs/ref/Implementations/Hibernate.gdoc deleted file mode 100644 index 2a8d6331e..000000000 --- a/grails-documentation-core/src/docs/ref/Implementations/Hibernate.gdoc +++ /dev/null @@ -1,9 +0,0 @@ -h1. Hibernate - -h2. Purpose - -GORM API onto [Hibernate|http://hibernate.org]. Original GORM implementation and most complete. - -h2. Description - -Implemented in the @grails-hibernate@ subproject of Grails itself. See @HibernateGormEnhancer@ diff --git a/grails-documentation-core/src/docs/ref/Implementations/JPA.gdoc b/grails-documentation-core/src/docs/ref/Implementations/JPA.gdoc deleted file mode 100644 index 66fea1038..000000000 --- a/grails-documentation-core/src/docs/ref/Implementations/JPA.gdoc +++ /dev/null @@ -1,13 +0,0 @@ -h1. JPA - -h2. Purpose - -An implementation that creates a GORM API on top of the Java Persistence API (JPA). - -h2. Description - -Sub-projects: - -* @grails-datastore-jpa@ -* @grails-datastore-gorm-jpa@ - diff --git a/grails-documentation-core/src/docs/ref/Implementations/MongoDB.gdoc b/grails-documentation-core/src/docs/ref/Implementations/MongoDB.gdoc deleted file mode 100644 index cfc5f573a..000000000 --- a/grails-documentation-core/src/docs/ref/Implementations/MongoDB.gdoc +++ /dev/null @@ -1,13 +0,0 @@ -h1. MongoDB - -h2. Purpose - -An implementation that creates a GORM API on top of [MongoDB|http://mongodb.org] - -h2. Description - -Sub-projects: - -* @grails-datastore-mongo@ -* @grails-datastore-gorm-mongo@ - diff --git a/grails-documentation-core/src/docs/ref/Implementations/Neo4j.gdoc b/grails-documentation-core/src/docs/ref/Implementations/Neo4j.gdoc deleted file mode 100644 index 00aacdad5..000000000 --- a/grails-documentation-core/src/docs/ref/Implementations/Neo4j.gdoc +++ /dev/null @@ -1,12 +0,0 @@ -h1. Neo4j - -h2. Purpose - -An implementation that creates a GORM API on top of [Neo4j|http://neo4j.org] - -h2. Description - -Sub-projects: - -* @grails-datastore-gorm-neo4j@ - diff --git a/grails-documentation-core/src/docs/ref/Implementations/Redis.gdoc b/grails-documentation-core/src/docs/ref/Implementations/Redis.gdoc deleted file mode 100644 index 7954f283b..000000000 --- a/grails-documentation-core/src/docs/ref/Implementations/Redis.gdoc +++ /dev/null @@ -1,13 +0,0 @@ -h1. Redis - -h2. Purpose - -An implementation that creates a GORM API on top of [Redis|http://redis.io] - -h2. Description - -Sub-projects: - -* @grails-datastore-redis@ -* @grails-datastore-gorm-redis@ - diff --git a/grails-documentation-core/src/docs/ref/Implementations/Riak.gdoc b/grails-documentation-core/src/docs/ref/Implementations/Riak.gdoc deleted file mode 100644 index 52d924770..000000000 --- a/grails-documentation-core/src/docs/ref/Implementations/Riak.gdoc +++ /dev/null @@ -1,13 +0,0 @@ -h1. Riak - -h2. Purpose - -An implementation that creates a GORM API on top of [Riak|http://basho.com/products/riak-overview/] - -h2. Description - -Sub-projects: - -* @grails-datastore-riak@ -* @grails-datastore-gorm-riak@ - diff --git a/grails-documentation-core/src/docs/ref/Implementations/SimpleDB.gdoc b/grails-documentation-core/src/docs/ref/Implementations/SimpleDB.gdoc deleted file mode 100644 index a5436289c..000000000 --- a/grails-documentation-core/src/docs/ref/Implementations/SimpleDB.gdoc +++ /dev/null @@ -1,13 +0,0 @@ -h1. Amazon SimpleDB - -h2. Purpose - -An implementation that creates a GORM API on top of [Amazon SimpleDB|http://aws.amazon.com/simpledb/] - -h2. Description - -Sub-projects: - -* @grails-datastore-simpledb@ -* @grails-datastore-gorm-simpledb@ - diff --git a/grails-documentation-dynamodb/build.gradle b/grails-documentation-dynamodb/build.gradle deleted file mode 100644 index 27d21832e..000000000 --- a/grails-documentation-dynamodb/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -task assemble(dependsOn:docs) << { - group = "docs" -} \ No newline at end of file diff --git a/grails-documentation-dynamodb/src/docs/doc.properties b/grails-documentation-dynamodb/src/docs/doc.properties deleted file mode 100644 index 0ec433cfa..000000000 --- a/grails-documentation-dynamodb/src/docs/doc.properties +++ /dev/null @@ -1,4 +0,0 @@ -title=GORM for AWS DynamoDB -version=0.1 -authors=Roman Stepanenko -footer=Official production and development support for plugin is available via OSMoss: http://www.osmoss.com/project/grails-gorm-dynamodb \ No newline at end of file diff --git a/grails-documentation-dynamodb/src/docs/guide/gettingStarted.gdoc b/grails-documentation-dynamodb/src/docs/guide/gettingStarted.gdoc deleted file mode 100644 index 38f9431c9..000000000 --- a/grails-documentation-dynamodb/src/docs/guide/gettingStarted.gdoc +++ /dev/null @@ -1,6 +0,0 @@ -To get started with GORM for DynamoDB you need to install the plugin into a Grails application: - -{code} -grails install-plugin dynamodb -{code} - diff --git a/grails-documentation-dynamodb/src/docs/guide/gettingStarted/configurationOptions.gdoc b/grails-documentation-dynamodb/src/docs/guide/gettingStarted/configurationOptions.gdoc deleted file mode 100644 index 16c9b8096..000000000 --- a/grails-documentation-dynamodb/src/docs/guide/gettingStarted/configurationOptions.gdoc +++ /dev/null @@ -1,83 +0,0 @@ -h3. Configuration options for dynamodb plugin - -dynamodb plugin supports the following configuration options: -{table} -*Name* | *Required* | *Description* -accessKey | Y | AWS access key value. IMPORTANT: *You have to properly guard this value. Do not keep it in version control system if anyone except authorized persons has access to your VCS* -secretKey | Y | AWS secret key value. IMPORTANT: *You have to properly guard this value. Do not keep it in version control system if anyone except authorized persons has access to your VCS* -tableNamePrefix | N | if this property is specified, the value will be prefixed to all AWS table names. It is handy when the same AWS account is shared between more than one environment. -defaultReadCapacityUnits | N | If individual domain class does not explicitly declare its read throughput capacity, this value will be used. If this property is not provided, plugin will use minimum allowed DynamoDB value of 3 -defaultWriteCapacityUnits | N | If individual domain class does not explicitly declare its write throughput capacity, this value will be used. If this property is not provided, plugin will use minimum allowed DynamoDB value of 5 -dbCreate | N | similar to GORM for hibernate. Currently supports *'drop'* (will drop the tables for domain classes at startup), *'create'* (will create tables for domain classes at startup if they do not exist), *'drop-create'* (at startup will ensure that all domains are present and are *empty* - do not use in PROD environment!) -disableDrop | N | boolean property used as an extra protection against accidentally dropping data by setting dbCreate flag to 'drop' or 'drop-create'. Typically, this property would be set to true in PROD configuration after initial release of the application. Since AWS DynamoDB does not provide backup, accidentally dropping PROD tables can have a devastating effect. If the value of this property is true, the plugin will throw an exception if dbCreate is 'drop' or 'create-drop'. -{table} - -To configure, provide the following in the Config.groovy or your custom MyApp.groovy config file: -{code} -grails { - dynamodb { - accessKey = '...' - secretKey = '...' - tableNamePrefix = 'DEV_' //optional, used when the same AWS account is shared between more than one environment - dbCreate = 'drop-create' // optional, one of 'drop', 'create', 'drop-create' - } -} -{code} - -Per-environment configuration works as well. For example: -{code} -grails { - dynamodb { - accessKey = '...' - secretKey = '...' - } -} - -environments { - production { - grails { - dynamodb { - disableDrop = true //extra protection against accidental misconfiguration of the 'dbCreate' flag - tableNamePrefix = 'PROD_' //this setting is optional, used when the same AWS account is shared between more than one environment - dbCreate = 'create' // one of 'drop, 'create', 'drop-create' - } - } - } - development { - grails { - dynamodb { - tableNamePrefix = 'DEV_' //this setting is optional, used when the same AWS account is shared between more than one environment - dbCreate = 'drop-create' // one of 'drop, 'create', 'drop-create' - } - } - } -} -{code} - -Or, if you use separate AWS accounts for PROD and dev: -{code} -environments { - production { - grails { - dynamodb { - accessKey = '... production account ...' - secretKey = '... production account ...' - dbCreate = 'create' // one of 'drop, 'create', 'drop-create' - } - } - } - development { - grails { - dynamodb { - accessKey = '... dev account ...' - secretKey = '... dev account ...' - tableNamePrefix = 'DEV_' //this setting is optional, used when the same AWS account is shared between more than one environment - dbCreate = 'drop-create' // one of 'drop, 'create', 'drop-create' - } - } - } -} -{code} - - - diff --git a/grails-documentation-dynamodb/src/docs/guide/introduction.gdoc b/grails-documentation-dynamodb/src/docs/guide/introduction.gdoc deleted file mode 100644 index c363d3dfe..000000000 --- a/grails-documentation-dynamodb/src/docs/guide/introduction.gdoc +++ /dev/null @@ -1,21 +0,0 @@ -DynamoDB is a web service providing structured data storage in the cloud and backed by clusters -of Amazon-managed database servers using SSD drives for storage. - -The dynamodb plugin aims to provide an object-mapping layer on top of DynamoDB to ease common activities such as: - -* Marshalling from DynamoDB to Groovy/Java types and back again -* Support for GORM dynamic finders, criteria and named queries -* Session-managed transactions -* Validating domain instances backed by the DynamoDB datastore - -For example, this is all that is needed to persist a domain class in DynamoDB: - -{code} -class Book { - String id - String title - int pages - - static mapWith = "dynamodb" -} -{code} diff --git a/grails-documentation-dynamodb/src/docs/guide/introduction/currentFeatureSet.gdoc b/grails-documentation-dynamodb/src/docs/guide/introduction/currentFeatureSet.gdoc deleted file mode 100644 index 860cd4680..000000000 --- a/grails-documentation-dynamodb/src/docs/guide/introduction/currentFeatureSet.gdoc +++ /dev/null @@ -1,38 +0,0 @@ -This implementation tries to be as compatible as possible with GORM for Hibernate. -In general you can refer to the [GORM documentation|http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html] -for usage information. - -The following key features are supported by the current version dynamodb plugin: - -* Simple persistence methods -* Dynamic finders -* Criteria queries -* Named queries -* Inheritance of domain classes (parent properties are stored in the child) -* Query by example -* Customizable AWS DynamoDB table name per domain object -* Customizable AWS DynamoDB attribute name per attribute in domain object -* Customizable (optional) prefix for all AWS DynamoDB table - useful when same AWS account is used for more than one environment (DEV and QA) -* Hilo numeric id generator to use as alternative to default UUID -* Enum fields are supported -* Declaration of provisioned read and write throughput on per-domain class level (and ability to use application-wide default values as well) - -The current version of dynamodb plugin has the following limitations: - -* Does not support Embedded types -* Does not support HQL queries -* Does not support Dirty checking methods -* Does not support Range keys (feature of DynamoDB) -* Does not support Many-to-many associations (these can be modelled with a mapping class) -* Does not support Any direct interaction with the Hibernate API -* Does not support Custom Hibernate user types - -There may be other limitations not mentioned here so in general it shouldn't be -expected that an application based on GORM for Hibernate will work without some tweaking involved. -Furthermore, migration from SQL to NoSQL storage with eventual consistency (such as DynamoDB) -will require a re-design of the application -at the fundamental level (see 'eventual consistency' in the next chapter). -Having said that, the large majority of common GORM functionality is supported, and this dynamodb plugin is a good option -(in author's eyes) for a from-scratch rapid project development. In this scenario AWS DynamoDB allows developer to -focus purely on the grails application without setting up and managing a dev/production cluster of database server instances. - diff --git a/grails-documentation-dynamodb/src/docs/guide/introduction/dynamoDBSpecifics.gdoc b/grails-documentation-dynamodb/src/docs/guide/introduction/dynamoDBSpecifics.gdoc deleted file mode 100644 index aa5309667..000000000 --- a/grails-documentation-dynamodb/src/docs/guide/introduction/dynamoDBSpecifics.gdoc +++ /dev/null @@ -1,50 +0,0 @@ -AWS DynamoDB imposes several critical restrictions. - -h3. Eventual consistency model - -DynamoDB is based on the premise of eventual consistency model. -With eventual consistency, when you submit an update to DynamoDB, the database server handling your -request will forward the update to the other database servers where that table -is replicated. The full update of all replicas does not happen before your update -request returns. The replication continues in the background while other requests are handled. -In other words, -if you update an object and do a query right after -updating it, you might get an old value back. There are ways to force strong consistency behavior but they go against the -whole premise of choosing DynamoDB in the first place - DynamoDB is best used by applications able to deal with -eventual consistency and benefit from the ability to remain available in the midst of a failure. Future -versions of the plugin might add support for strong consistency though. - -The best way to fight eventual consistency in the application is *not* to assume that the information is -available right after create/update/delete and store the objects you just modified or created in the cache. Generally, -information becomes visible within a couple of seconds, however it is a really bad idea to try to -implement artificial delay in the application layer because when AWS experiences some problems the -eventually consistency window might be -drastically increased. Design for failure and you will get fewer surprises when they happen. - -DynamoDB does allow enforcing consistent behavior but it is not currently supported by the plugin. - -h3. No indexes -Unlike SimpleDB, DynamoDB does not index non-primary key columns and so the only way GORM queries can work is by scanning all -records in the table to match specified criteria, which can have potential performance impact when the number of records grows. - -h3. No OR -All scan filters in DynamoDB assume 'AND' behavior, which means the only way for plugin to implement -GORM finder (name = 'Mike' OR name = 'Bob') is internally to execute two scans and then build unique list of items in memory. - -*It is highly adivisable to avoid or minimize using OR clauses in your queries* for the sake of performance. - -h3. No Negation clause -DynamoDB does provide NE (not equals) comparison operator but does not provide support for negation clause. Current plugin implementation -does not support negation clause either ('not equals' comparison is supported though). - -h3. No ordering -DynamoDB does not support ordering or results, which means plugin has to order results in memory. - -h3. Transactions -AWS DynamoDB doesn't support explicit transactional boundaries or isolation levels. There is no notion of -a commit or a rollback. There is some implicit support for atomic writes, but it only applies within the -scope of each individual item being written. - -However, GORM for DynamoDB does batch up inserts -and updates until the session is flushed. This makes it possible to support some rollback options. See more details -in 'Transactions' chapter diff --git a/grails-documentation-dynamodb/src/docs/guide/mapping.gdoc b/grails-documentation-dynamodb/src/docs/guide/mapping.gdoc deleted file mode 100644 index 3e02c304f..000000000 --- a/grails-documentation-dynamodb/src/docs/guide/mapping.gdoc +++ /dev/null @@ -1,83 +0,0 @@ -h3. Mapping to AWS Tables - -The way GORM for DynamoDB works is to map each domain class to a AWS DynamoDB domain. -For example, given a domain class such as: - -{code} -class Person { - String id - String firstName - String lastName - static hasMany = [pets:Pet] - - static mapWith = "dynamodb" -} -{code} - -The plugin will map @Person@ class to a DynamoDB table called "Person". -By default the table name will be the class name, however it can be explicitly specified: - -{code} -class Person { - String id - String firstName - String lastName - static hasMany = [pets:Pet] - - static mapWith = "dynamodb" - static mapping = { - table 'PEOPLE' - } -} -{code} - -In this case @Person@ class will be mapped to 'PEOPLE' DynamoDB table. - -Please note: _if you specified a table name prefix in the configuration, all table names will be prefixed_. For example, if you specified -{code} -grails { - dynamodb { - accessKey = '...' - secretKey = '...' - tableNamePrefix = 'DEV_' //optional, used when the same AWS account is shared between more than one environment - } -} -{code} -then resulting table name will be DEV_Person for first example and DEV_PEOPLE for second example. - -h3. Mapping to AWS Attributes - -By default, each java property will be mapped as an identically named AWS DynamoDB attribute. -For example, given a domain class such as: - -{code} -class Person { - String id - String firstName - String lastName - - static mapWith = "dynamodb" -} -{code} - -will result in the following attribute names in 'Person' domain: -* firstName -* lastName - -@id@ field is always mapped to @itemName()@ for the record representing this domain class instance. - -It is possible to specify custom AWS attribute names for each java attribute: - -{code} -class Person { - String id - String firstName - String lastName - - static mapWith = "dynamodb" - static mapping = { - firstName key:'FIRST_NAME' - lastName key:'LAST_NAME' - } -} -{code} diff --git a/grails-documentation-dynamodb/src/docs/guide/mapping/identityGeneration.gdoc b/grails-documentation-dynamodb/src/docs/guide/mapping/identityGeneration.gdoc deleted file mode 100644 index 1dc915df6..000000000 --- a/grails-documentation-dynamodb/src/docs/guide/mapping/identityGeneration.gdoc +++ /dev/null @@ -1,29 +0,0 @@ -The plugin works only with String identifiers. Assignment and generation of ids is done automatically, however the String -id field must be currently explicitly declared in the domain class: - -{code} -class Person { - String id - String firstName - String lastName - - static mapWith = "dynamodb" -} -{code} - -By default, generated ids are generated with @java.lang.UUID@. It is also possible to use hilo numeric value generator -(please note that the id field must still be declared as String): -{code} -class Person { - String id - String firstName - String lastName - - static mapWith = "dynamodb" - - static mapping = { - id_generator type: 'hilo', maxLo: 500 - } -} -{code} - diff --git a/grails-documentation-dynamodb/src/docs/guide/mapping/provisionedThroughput.gdoc b/grails-documentation-dynamodb/src/docs/guide/mapping/provisionedThroughput.gdoc deleted file mode 100644 index 6e0f189d6..000000000 --- a/grails-documentation-dynamodb/src/docs/guide/mapping/provisionedThroughput.gdoc +++ /dev/null @@ -1,17 +0,0 @@ -DynamoDB gives you complete control of the performance characteristics for each table via read and write throughput provisioning. -Complete details can be found at [Amazon DynamoDB documentation|http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/WorkingWithDDTables.html#ProvisionedThroughput] - -Developer can specify read or write (or both) throughput on a per-domain class basis using the following syntax: -{code} -class Person { - String id - String firstName - String lastName - - static mapWith = "dynamodb" - static mapping = { - throughput read:4, write:6 //optional, if not specified default values will be used - } -} -{code} -The implementation of plugin will use specified values, or will fall back to default read and write throughput values specified in the configuration options. diff --git a/grails-documentation-dynamodb/src/docs/guide/releaseNotes.gdoc b/grails-documentation-dynamodb/src/docs/guide/releaseNotes.gdoc deleted file mode 100644 index 519a1a6ef..000000000 --- a/grails-documentation-dynamodb/src/docs/guide/releaseNotes.gdoc +++ /dev/null @@ -1,13 +0,0 @@ -Below are the details of the changes across releases: - -h4. Version 0.1 - -Initial implementation of the DynamoDB support with: -* Dynamic finders -* Criteria queries -* Named queries -* Hilo numeric id generator to use as alternative to default UUID -* Support of Enum fields -* Automatic retry of load/save operations when AWS rejects request with 'ServiceUnavailable' error code -* Behind-the-scenes working with lastEvaluatedKey when more than 1MB worth of records are returned/scanned - diff --git a/grails-documentation-dynamodb/src/docs/guide/toc.yml b/grails-documentation-dynamodb/src/docs/guide/toc.yml deleted file mode 100644 index 3b0b29517..000000000 --- a/grails-documentation-dynamodb/src/docs/guide/toc.yml +++ /dev/null @@ -1,13 +0,0 @@ -introduction: - title: Introduction - currentFeatureSet: Current Feature Set - dynamoDBSpecifics: DynamoDB Specifics -gettingStarted: - title: Getting Started - configurationOptions: Configuration Options -mapping: - title: Mapping Domain Classes to DynamoDB - identityGeneration: IdentityGeneration - provisionedThroughput: Provisioned Throughput -transactions: Transactions -releaseNotes: Release Notes \ No newline at end of file diff --git a/grails-documentation-dynamodb/src/docs/guide/transactions.gdoc b/grails-documentation-dynamodb/src/docs/guide/transactions.gdoc deleted file mode 100644 index 65e476747..000000000 --- a/grails-documentation-dynamodb/src/docs/guide/transactions.gdoc +++ /dev/null @@ -1,29 +0,0 @@ -AWS DynamoDB doesn't support explicit transactional boundaries or isolation levels. There is no notion of -a commit or a rollback. There is some implicit support for atomic writes, but it only applies within the -scope of each individual item being written. - -However, dynamodb plugin does batch up inserts -and updates until the session is flushed. This makes it possible to support some rollback options. - -You can use either transactional services or the static @withTransaction@ method. To mark a service as using the DynamoDB transaction manager, use the static @transactional@ property with the value @'dynamodb'@: - -{code} -static transactional = 'dynamodb' -{code} - -Alternately you can do ad-hoc transactions using the @withTransaction@ method: - -{code} -Person.withTransaction { status -> - new Person(firstName: "Bob").save() - throw new RuntimeException("bad") - new Person(firstName: "Fred").save() -} -{code} - -For example in this case neither @Person@ object will be persisted to the database, -because underneath the surface a persistence session is being used to batch up both insert -operations into a single insert. When the exception is thrown neither insert is ever -executed, hence we allow for some transactional semantics. - - diff --git a/grails-documentation-mongo/build.gradle b/grails-documentation-mongo/build.gradle deleted file mode 100644 index 27d21832e..000000000 --- a/grails-documentation-mongo/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -task assemble(dependsOn:docs) << { - group = "docs" -} \ No newline at end of file diff --git a/grails-documentation-mongo/src/docs/doc.properties b/grails-documentation-mongo/src/docs/doc.properties deleted file mode 100644 index 1b39b6cb4..000000000 --- a/grails-documentation-mongo/src/docs/doc.properties +++ /dev/null @@ -1,3 +0,0 @@ -title=GORM for Mongo -version=1.3.0.GA -authors=Graeme Rocher, Burt Beckwith \ No newline at end of file diff --git a/grails-documentation-mongo/src/docs/guide/1. Introduction.gdoc b/grails-documentation-mongo/src/docs/guide/1. Introduction.gdoc deleted file mode 100644 index 55e6e3d16..000000000 --- a/grails-documentation-mongo/src/docs/guide/1. Introduction.gdoc +++ /dev/null @@ -1,11 +0,0 @@ -MongoDB bridges the gap between key-value stores (which are fast and highly scalable) and traditional RDBMS systems (which provide rich queries and deep functionality). - -MongoDB (from "humongous") is a scalable, high-performance, open source, document-oriented database. - -This project aims to provide an object-mapping layer on top of Mongo to ease common activities such as: - -* Marshalling from Mongo to Groovy/Java types and back again -* Support for GORM dynamic finders, criteria and named queries -* Session-managed transactions -* Validating domain instances backed by the Mongo datastore - diff --git a/grails-documentation-mongo/src/docs/guide/1.1 Compatibility with GORM for Hibernate.gdoc b/grails-documentation-mongo/src/docs/guide/1.1 Compatibility with GORM for Hibernate.gdoc deleted file mode 100644 index 483692dd8..000000000 --- a/grails-documentation-mongo/src/docs/guide/1.1 Compatibility with GORM for Hibernate.gdoc +++ /dev/null @@ -1,22 +0,0 @@ -This implementation tries to be as compatible as possible with GORM for Hibernate. In general you can refer to the [GORM documentation|http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html] and the "Domain Classes" section of the [reference guide|http://grails.org/doc/latest/] (see the left nav) for usage information. - -The following key features are supported by GORM for Mongo: - -* Simple persistence methods -* Dynamic finders -* Criteria queries -* Named queries -* Inheritance -* Embedded types -* Query by example - -However, some features are not supported: - -* HQL queries -* Dirty checking methods -* Composite primary keys -* Many-to-many associations (these can be modelled with a mapping class) -* Any direct interaction with the Hibernate API -* Custom Hibernate user types - -There may be other limitations not mentioned here so in general it shouldn't be expected that an application based on GORM for Hibernate will "just work" without some tweaking involved. Having said that, the large majority of common GORM functionality is supported. diff --git a/grails-documentation-mongo/src/docs/guide/1.2 Release Notes.gdoc b/grails-documentation-mongo/src/docs/guide/1.2 Release Notes.gdoc deleted file mode 100644 index 0c221f36f..000000000 --- a/grails-documentation-mongo/src/docs/guide/1.2 Release Notes.gdoc +++ /dev/null @@ -1,41 +0,0 @@ -Below are the details of the changes across releases: - -h4. 1.3 - -* Support for stateless mode to improve read performance -* Support for dynamically switching which database or collection to persist to at runtime - -h4. 1.2 - -{warning} -MongoDB plugin 1.2 and above requires Grails 2.1.5 or 2.2.1 as a minimum Grails version, if you are using older versions of Grails you will need to stay with 1.1 -{warning} - -h4. 1.1 GA - -* DBRefs no longer used by default for associations -* Upgrade to GMongo 1.0 and Spring Data MongoDB 1.1 -* Support for global mapping configuration - -h5. Upgrading to 1.1 GA - -{warning} -MongoDB plugin 1.1 GA and above requires Grails 2.0.x as a minimum Grails version, if you are using Grails 1.3.x you will need to stay with 1.0 -{warning} - -If you are using 1.0 and are upgrading to 1.1 you need to either migrate your database to note use DBRefs or configure the plugin to use DBRefs when upgrading, otherwise you will experience data integrity issues. - -To configure the plugin to use DBRefs (1.0 behavior), specify a global mapping configuration in Config.groovy of: - -{code} -grails.mongo.default.mapping = { - '*'(reference: true) -} -{code} - -This will make all associations reference types. - - -h4. 1.0 GA - -* Initial feature complete 1.0 release diff --git a/grails-documentation-mongo/src/docs/guide/2. Getting Started.gdoc b/grails-documentation-mongo/src/docs/guide/2. Getting Started.gdoc deleted file mode 100644 index fb3416d79..000000000 --- a/grails-documentation-mongo/src/docs/guide/2. Getting Started.gdoc +++ /dev/null @@ -1,40 +0,0 @@ -To get started with GORM for Mongo you need configure it as a dependency in @BuildConfig.groovy@: - -{code} -plugins { - compile ':mongodb:1.2.0' // or whatever is the latest vesrion -} -{code} - -With that done you need to set up a running MongoDB server. Refer to the [MongoDB Quick Start guide|http://www.mongodb.org/display/DOCS/Quickstart] for an explanation on how to startup a Mongo instance. Once installed starting Mongo is typically a matter of executing the following command: - -{code} -MONGO_HOME/bin/mongod -{code} - -With the above commands executed in a terminal window you should see output like the following appear: - -{code} -Thu Nov 11 16:54:08 MongoDB starting : pid=4600 port=27017 dbpath=/data/db/ 64-bit -Thu Nov 11 16:54:08 db version v1.6.3, pdfile version 4.5 -Thu Nov 11 16:54:08 git version: 278bd2ac2f2efbee556f32c13c1b6803224d1c01 -Thu Nov 11 16:54:08 sys info: Darwin erh2.10gen.cc 9.6.0 Darwin Kernel Version 9.6.0: Mon Nov 24 17:37:00 PST 2008; root:xnu-1228.9.59~1/RELEASE_I386 i386 BOOST_LIB_VERSION=1_40 -Thu Nov 11 16:54:08 [initandlisten] waiting for connections on port 27017 -Thu Nov 11 16:54:08 [websvr] web admin interface listening on port 28017 -{code} - -As you can see the server is running on port 27017, but don't worry the Mongodb plugin for Grails will automatically configure itself to look for Mongodb on that port by default. - -If you want to configure how Grails connects to Mongo then you can do so using the following settings in @grails-app/conf/DataSource.groovy@: - -{code} -grails { - mongo { - host = "localhost" - port = 27017 - username = "blah" - password = "blah" - databaseName = "foo" - } -} -{code} diff --git a/grails-documentation-mongo/src/docs/guide/2.1 Using Mongo Standalone.gdoc b/grails-documentation-mongo/src/docs/guide/2.1 Using Mongo Standalone.gdoc deleted file mode 100644 index 2db5849a1..000000000 --- a/grails-documentation-mongo/src/docs/guide/2.1 Using Mongo Standalone.gdoc +++ /dev/null @@ -1,13 +0,0 @@ -If you plan to use Mongo as your primary datastore then you need to remove the Hibernate plugin from the @grails-app/conf/BuildConfig.groovy@ file by commenting out the hibernate line in the plugins block - -{code} -compile ':hibernate:2.0.0' -{code} - -With this done all domain classes in grails-app/domain will be persisted via Mongo and not Hibernate. You can create a domain class by running the regular @create-domain-class@ command: - -{code} -grails create-domain-class Person -{code} - -The @Person@ domain class will automatically be a persistent entity that can be stored in Mongo. diff --git a/grails-documentation-mongo/src/docs/guide/2.2 Combining Mongo and Hibernate.gdoc b/grails-documentation-mongo/src/docs/guide/2.2 Combining Mongo and Hibernate.gdoc deleted file mode 100644 index a8fc62c3e..000000000 --- a/grails-documentation-mongo/src/docs/guide/2.2 Combining Mongo and Hibernate.gdoc +++ /dev/null @@ -1,16 +0,0 @@ -If you have both the Hibernate and Mongo plugins installed then by default all classes in the @grails-app/domain@ directory will be persisted by Hibernate and not Mongo. If you want to persist a particular domain class with Mongo then you must use the @mapWith@ property in the domain class: - -{code} -static mapWith = "mongo" -{code} - -Alternatively you can persist Hibernate entities to Mongo using the special @mongo@ scope added to all Hibernate entities: - -{code} -def hibernatePerson = Person.get(1) - -hibernatePerson.mongo.save() - -def mongoPerson = Person.mongo.get(1) -{code} - diff --git a/grails-documentation-mongo/src/docs/guide/2.3 Advanced Configuration.gdoc b/grails-documentation-mongo/src/docs/guide/2.3 Advanced Configuration.gdoc deleted file mode 100644 index ad6982dbc..000000000 --- a/grails-documentation-mongo/src/docs/guide/2.3 Advanced Configuration.gdoc +++ /dev/null @@ -1,67 +0,0 @@ -h4. Mongo Database Connection Configuration - -As mentioned the GORM for Mongo plugin will configure all the defaults for you, but if you wish to customize those defaults you can do so in the your @grails-app/conf/DataSource.groovy@ file: - -{code} -grails { - mongo { - host = "localhost" - port = 27107 - username = "blah" - password = "blah" - databaseName = "foo" - } -} -{code} - -The @databaseName@ setting configures the default database name. If not specified the @databaseName@ will default to the name of your application. - -You can also customize the Mongo connection settings using an @options@ block: - -{code} -grails { - mongo { - options { - autoConnectRetry = true - connectTimeout = 300 - } - } -} -{code} - -Available options and their descriptions are defined in the [MongoOptions|http://api.mongodb.org/java/current/com/mongodb/MongoOptions.html] javadoc. - -In production scenarios you will typically use more than one Mongo server in either [master/slave|http://www.mongodb.org/display/DOCS/Master+Slave] or [replication|http://www.mongodb.org/display/DOCS/Replication] scenarios. The plugin allows you to configure [replica pairs|http://www.mongodb.org/display/DOCS/Replica+Pairs]: - -{code} -grails { - mongo { - replicaPair = [ "localhost:27017", "localhost:27018"] - } -} -{code} - -Or [replica sets|http://www.mongodb.org/display/DOCS/Replica+Sets]: - -{code} -grails { - mongo { - replicaSet = [ "localhost:27017", "localhost:27018"] - } -} -{code} - -The replica sets are defined using a list of strings that conform to the Mongo [DBAddress|http://api.mongodb.org/java/current/com/mongodb/DBAddress.html] specification. - -h4. Global Mapping Configuration - -Using the @grails.mongo.default.mapping@ setting in @Config.groovy@ you can configure global mapping options across your domain classes. This is useful if, for example, you want to disable optimistic locking globally or you wish to use @DBRefs@ in your association mappings. For example, the following configuration will disable optimistic locking globally and use @DBRefs@ for all properties: - -{code} -grails.mongo.default.mapping = { - version false - '*'(reference:true) -} -{code} - -The @*@ method is used to indicate that the setting applies to all properties. diff --git a/grails-documentation-mongo/src/docs/guide/3. Mapping Domain Classes to Mongo Collections.gdoc b/grails-documentation-mongo/src/docs/guide/3. Mapping Domain Classes to Mongo Collections.gdoc deleted file mode 100644 index 0ab75019b..000000000 --- a/grails-documentation-mongo/src/docs/guide/3. Mapping Domain Classes to Mongo Collections.gdoc +++ /dev/null @@ -1,95 +0,0 @@ -h4. Basic Mapping - -The way GORM for Mongo works is to map each domain class to a Mongo collection. For example given a domain class such as: - -{code} -class Person { - String firstName - String lastName - static hasMany = [pets:Pet] -} -{code} - -This will map onto a Mongo [DBCollection|http://api.mongodb.org/java/current/com/mongodb/DBCollection.html] called "person". - -h4. Embedded Documents - -It is quite common in Mongo to embed documents within documents (nested documents). This can be done with GORM embedded types: - -{code} -class Person { - String firstName - String lastName - Address address - static embedded = ['address'] -} -{code} - -You can map embedded lists and sets of documents/domain classes: - -{code} -class Person { - String firstName - String lastName - Address address - List otherAddresses - static embedded = ['address', 'otherAddresses'] -} -{code} - -h4. Basic Collection Types - -You can also map lists and maps of basic types (such as strings) simply by defining the appropriate collection type: - -{code} -class Person { - List friends - Map pets -} - -... - -new Person(friends:['Fred', 'Bob'], pets:[chuck:"Dog", eddie:'Parrot']).save(flush:true) -{code} - -Basic collection types are stored as native ArrayList and BSON documents within the Mongo documents. - -h4. Customized Collection and Database Mapping - -You may wish to customize how a domain class maps onto a @DBCollection@. This is possible using the @mapping@ block as follows: - -{code} -class Person { - .. - static mapping = { - collection "mycollection" - database "mydb" - } -} -{code} - -In this example we see that the @Person@ entity has been mapped to a collection called "mycollection" in a database called "mydb". - -You can also control how an individual property maps onto a Mongo Document field (the default is to use the property name itself): - -{code} -class Person { - .. - static mapping = { - firstName attr:"first_name" - } -} -{code} - -For non-embedded associations by default GORM for MongoDB will map links between documents using MongoDB [database references|http://www.mongodb.org/display/DOCS/Database+References] also known as @DBRefs@. - -If you prefer not to use DBRefs then you tell GORM to use direct links by using the @reference:false@ mapping: - -{code} -class Person { - .. - static mapping = { - address reference:false - } -} -{code} diff --git a/grails-documentation-mongo/src/docs/guide/3.1 Identity Generation.gdoc b/grails-documentation-mongo/src/docs/guide/3.1 Identity Generation.gdoc deleted file mode 100644 index e89145277..000000000 --- a/grails-documentation-mongo/src/docs/guide/3.1 Identity Generation.gdoc +++ /dev/null @@ -1,27 +0,0 @@ -By default in GORM entities are supplied with an integer-based identifier. So for example the following entity: - -{code} -class Person {} -{code} - -Has a property called @id@ of type @java.lang.Long@. In this case GORM for Mongo will generate a sequence based identifier using the technique [described in the Mongo documentation|http://www.mongodb.org/display/DOCS/Atomic+Operations] on Atomic operations. - -However, sequence based integer identifiers are not ideal for environments that require [sharding|http://www.mongodb.org/display/DOCS/Sharding] (one of the nicer features of Mongo). Hence it is generally advised to use either String based ids: - -{code} -class Person { - String id -} -{code} - -Or a native BSON [ObjectId|http://api.mongodb.org/java/current/org/bson/types/ObjectId.html]: - -{code} -import org.bson.types.ObjectId - -class Person { - ObjectId id -} -{code} - -BSON @ObjectId@ instances are generated in a similar fashion to @UUIDs@. \ No newline at end of file diff --git a/grails-documentation-mongo/src/docs/guide/3.2 Indexing Queries.gdoc b/grails-documentation-mongo/src/docs/guide/3.2 Indexing Queries.gdoc deleted file mode 100644 index f2bef34ac..000000000 --- a/grails-documentation-mongo/src/docs/guide/3.2 Indexing Queries.gdoc +++ /dev/null @@ -1,55 +0,0 @@ -h4. Basics - -Mongo doesn't require that you specify indices to query, but like a relational database without specifying indices your queries will be significantly slower. - -With that in mind it is important to specify the properties you plan to query using the mapping block: - -{code} -class Person { - String name - static mapping = { - name index:true - } -} -{code} - -With the above mapping a Mongo index will be automatically created for you. You can customize the index options using the @indexAttributes@ configuration parameter: - -{code} -class Person { - String name - static mapping = { - name index:true, indexAttributes: [unique:true, dropDups:true] - } -} -{code} - -You can use MongoDB [Query Hints|http://www.mongodb.org/display/DOCS/Optimization#Optimization-Hint] by passing the @hint@ argument to any dynamic finder: - -{code} -def people = Person.findByName("Bob", [hint:[name:1]]) -{code} - -Or in a criteria query using the query "arguments" method - -{code} -Person.withCriteria { - eq 'firstName', 'Bob' - arguments hint:["firstName":1] -} -{code} - -h4. Compound Indices - -MongoDB supports the notion of [compound keys|http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeys]. GORM for MongoDB enables this feature at the mapping level using the @compoundIndex@ mapping: - -{code} -class Person { - ... - static mapping = { - compoundIndex name:1, age:-1 - } -} -{code} - -As per the MongoDB docs 1 is for ascending and -1 is for descending. \ No newline at end of file diff --git a/grails-documentation-mongo/src/docs/guide/3.3 Customizing the WriteConcern.gdoc b/grails-documentation-mongo/src/docs/guide/3.3 Customizing the WriteConcern.gdoc deleted file mode 100644 index 4fa2a8567..000000000 --- a/grails-documentation-mongo/src/docs/guide/3.3 Customizing the WriteConcern.gdoc +++ /dev/null @@ -1,18 +0,0 @@ -A feature of Mongo is its ability to customize how important a database write is to the user. The Java client models this as a [WriteConcern|http://api.mongodb.org/java/current/com/mongodb/WriteConcern.html] and there are various options that indicate whether the client cares about server or network errors, or whether the data has been successfully written or not. - -If you wish to customize the @WriteConcern@ for a domain class you can do so in the mapping block: - -{code} -import com.mongodb.WriteConcern - -class Person { - String name - static mapping = { - writeConcern WriteConcern.FSYNC_SAFE - } -} -{code} - -{note} -For versioned entities, if a lower level of WriteConcern than WriteConcern.ACKNOWLEDGE is specified, WriteConcern.ACKNOWLEDGE will also be used for updates, to ensure that optimistic locking failures are reported. -{note} \ No newline at end of file diff --git a/grails-documentation-mongo/src/docs/guide/3.4 Dynamic Attributes.gdoc b/grails-documentation-mongo/src/docs/guide/3.4 Dynamic Attributes.gdoc deleted file mode 100644 index 07c999b5a..000000000 --- a/grails-documentation-mongo/src/docs/guide/3.4 Dynamic Attributes.gdoc +++ /dev/null @@ -1,24 +0,0 @@ -Unlike a relational database, Mongo allows for "schemaless" persistence where there are no limits to the number of attributes a particular document can have. A GORM domain class on the other hand has a schema in that there are a fixed number of properties. For example consider the following domain class: - -{code} -class Plant { - boolean goesInPatch - String name -} -{code} - -Here there are two fixed properties, @name@ and @goesInPatch@, that will be persisted into the Mongo document. Using GORM for Mongo you can however use dynamic properties via the Groovy subscript operator. For example: - -{code} -def p = new Plant(name:"Pineapple") -p['color'] = 'Yellow' -p['hasLeaves'] = true -p.save() - -p = Plant.findByName("Pineapple") - -println p['color'] -println p['hasLeaves'] -{code} - -Using the subscript operator you can add additional attributes to the underlying @DBObject@ instance that gets persisted to the Mongo allowing for more dynamic domain models. \ No newline at end of file diff --git a/grails-documentation-mongo/src/docs/guide/3.5 Dynamic Database or Collection Switching.gdoc b/grails-documentation-mongo/src/docs/guide/3.5 Dynamic Database or Collection Switching.gdoc deleted file mode 100644 index d0c7a87cf..000000000 --- a/grails-documentation-mongo/src/docs/guide/3.5 Dynamic Database or Collection Switching.gdoc +++ /dev/null @@ -1,18 +0,0 @@ -In addition to storing dynamic attributes, as of version 1.3.0 of the plugin you can also switch which database and/or collection to persist to at runtime. - -For example: - -{code} -Person.withDatabase("administrators") { - new Person(name:"Bob").save() -} -{code} - -The above example will save a @Person@ instance to the 'administrators' database. The database is used for the scope of the closure. You can switch database for the scope of the active session: - -{code} -Person.useDatabase("administrators") -new Person(name:"Bob").save() -{code} - -In addition, there are equivalent @withCollection@ and @useCollection@ methods for switching collection at runtime. diff --git a/grails-documentation-mongo/src/docs/guide/3.6 Geospacial Querying.gdoc b/grails-documentation-mongo/src/docs/guide/3.6 Geospacial Querying.gdoc deleted file mode 100644 index d5eae3bd8..000000000 --- a/grails-documentation-mongo/src/docs/guide/3.6 Geospacial Querying.gdoc +++ /dev/null @@ -1,80 +0,0 @@ -It is possible to use Mongo's [Geospacial querying|http://www.mongodb.org/display/DOCS/Geospatial+Indexing] capability by mapping a list or map property using the @geoIndex@ mapping: - -{code} -class Hotel { - String name - List location - - static mapping = { - location geoIndex:true - } -} -{code} - -By default the index creation assumes latitude/longitude and thus is configured for a -180..180 range. If you are indexing something else you can customise this with @indexAttributes@ - -{code} -class Hotel { - String name - List location - - static mapping = { - location geoIndex:true, indexAttributes:[min:-500, max:500] - } -} - -{code} - -You can then save Geo locations using a two dimensional list: - -{code} -new Hotel(name:"Hilton", location:[50, 50]).save() -{code} - -Alternatively you can use a map with keys representing latitude and longitude: - -{code} -new Hotel(name:"Hilton", location:[lat: 40.739037d, long: 73.992964d]).save() -{code} - -{note} -You must specify whether the number of a floating point or double by adding a 'd' or 'f' at the end of the number eg. 40.739037d. Groovy's default type for decimal numbers is @BigDecimal@ which is not supported by MongoDB. -{note} - -Once you have your data indexed you can use Mongo specific dynamic finders to find hotels near a given a location: - -{code} -def h = Hotel.findByLocationNear([50, 60]) -assert h.name == 'Hilton' -{code} - -You can also find a location within a box (bound queries). Boxes are defined by specifying the lower-left and upper-right corners: - -{code} -def box = [[40.73083d, -73.99756d], [40.741404d, -73.988135d]] -def h = Hotel.findByLocationWithinBox(box) -{code} - -You can also find a location within a circle. Circles are specified using a center and radius: - -{code} -def center = [50, 50] -def radius = 10 -def h = Hotel.findByLocationWithinCircle([center, radius]) -{code} - -If you plan on querying a location and some other value it is recommended to use a compound index: - -{code} -class Hotel { - String name - List location - int stars - - static mapping = { - compoundIndex location:"2d", stars:1 - } -} -{code} - -In the example above you an index is created for both the location and the number of stars a @Hotel@ has. diff --git a/grails-documentation-mongo/src/docs/guide/3.7 Custom User Types.gdoc b/grails-documentation-mongo/src/docs/guide/3.7 Custom User Types.gdoc deleted file mode 100644 index 265d77f7f..000000000 --- a/grails-documentation-mongo/src/docs/guide/3.7 Custom User Types.gdoc +++ /dev/null @@ -1,132 +0,0 @@ -GORM for MongoDB will persist all common known Java types like String, Integer, URL etc., however if you want to persist one of your own classes that is not a domain class you can implement a custom user type. For example consider the following class: - -{code} -class Birthday implements Comparable{ - Date date - - Birthday(Date date) { - this.date = date - } - - @Override - int compareTo(Object t) { - date.compareTo(t.date) - } -} -{code} - -{note} -Custom types should go in src/groovy not grails-app/domain -{note} - -If you attempt to reference this class from a domain class it will not automatically be persisted for you. However you can create a custom type implementation and register it with Spring. For example: - -{code} -import com.mongodb.BasicDBObject; -import com.mongodb.DBObject; -import org.grails.datastore.mapping.engine.types.AbstractMappingAwareCustomTypeMarshaller; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.mongo.query.MongoQuery; -import org.grails.datastore.mapping.query.Query; - -class BirthdayType extends AbstractMappingAwareCustomTypeMarshaller { - BirthdayType() { - super(Birthday) - } - @Override - protected Object writeInternal(PersistentProperty property, String key, Birthday value, DBObject nativeTarget) { - final converted = value.date.time - nativeTarget.put(key, converted) - return converted - } - - @Override - protected void queryInternal(PersistentProperty property, String key, Query.PropertyCriterion criterion, DBObject nativeQuery) { - if(criterion instanceof Between) { - def dbo = new BasicDBObject() - dbo.put(MongoQuery.MONGO_GTE_OPERATOR, criterion.getFrom().date.time); - dbo.put(MongoQuery.MONGO_LTE_OPERATOR, criterion.getTo().date.time); - nativeQuery.put(key, dbo) - } - else { - nativeQuery.put(key, criterion.value.date.time) - } - - } - - @Override - protected Birthday readInternal(PersistentProperty property, String key, DBObject nativeSource) { - final num = nativeSource.get(key) - if(num instanceof Long) { - return new Birthday(new Date(num)) - } - return null - } -} -{code} - -The above @BirthdayType@ class is a custom user type implementation for MongoDB for the @Birthday@ class. It provides implementations for three methods: @readInternal@, @writeInternal@ and the optional @queryInternal@. If you do not implement @queryInternal@ your custom type can be persisted but not queried. - -The @writeInternal@ method gets passed the property, the key to store it under, the value and the native DBObject where the custom type is to be stored: - -{code} -@Override -protected Object writeInternal(PersistentProperty property, String key, Birthday value, DBObject nativeTarget) { - final converted = value.date.time - nativeTarget.put(key, converted) - return converted -} -{code} - -You can then read the values of the custom type and register them with the @DBObject@. The @readInternal@ method gets passed the @PersistentProperty@, the key the user type info is stored under (although you may want to use multiple keys) and the @DBObject@: - -{code} -@Override -protected Birthday readInternal(PersistentProperty property, String key, DBObject nativeSource) { - final num = nativeSource.get(key) - if(num instanceof Long) { - return new Birthday(new Date(num)) - } - return null -} -{code} - -You can then construct the custom type by reading values from the @DBObject@. Finally the @queryInternal@ method allows you to handle how a custom type is queried: - -{code} -@Override -protected void queryInternal(PersistentProperty property, String key, Query.PropertyCriterion criterion, DBObject nativeQuery) { - if(criterion instanceof Between) { - def dbo = new BasicDBObject() - dbo.put(MongoQuery.MONGO_GTE_OPERATOR, criterion.getFrom().date.time); - dbo.put(MongoQuery.MONGO_LTE_OPERATOR, criterion.getTo().date.time); - nativeQuery.put(key, dbo) - } - else if(criterion instanceof Equals){ - nativeQuery.put(key, criterion.value.date.time) - } - else { - throw new RuntimeException("unsupported query type for property $property") - } -} -{code} - -The method gets passed a @criterion@ which is the type of query and depending on the type of query you may handle the query differently. For example the above implementation supports @between@ and @equals@ style queries. So the following 2 queries will work: - -{code} -Person.findByBirthday(new Birthday(new Date()-7)) // find someone who was born 7 days ago -Person.findByBirthdayBetween(new Birthday(new Date()-7), new Birthday(new Date())) // find someone who was born in the last 7 days -{code} - -However "like" or other query types will not work. - -To register a custom type in a grails application simply register it as Spring bean. For example, to register the above @BirthdayType@ add the following to grails-app/conf/spring/resources.groovy: - -{code} -import com.example.BirthdayType - -// Place your Spring DSL code here -beans = { - birthdayType(BirthdayType) -} -{code} diff --git a/grails-documentation-mongo/src/docs/guide/3.8 Stateful vs. Stateless Domain Classes.gdoc b/grails-documentation-mongo/src/docs/guide/3.8 Stateful vs. Stateless Domain Classes.gdoc deleted file mode 100644 index fdd5524e4..000000000 --- a/grails-documentation-mongo/src/docs/guide/3.8 Stateful vs. Stateless Domain Classes.gdoc +++ /dev/null @@ -1,102 +0,0 @@ -GORM for MongoDB supports both stateless and stateful modes for mapping domain classes to MongoDB. In general stateful mapping is superior for write heavy applications and stateless mode better for read heavy applications (particularily when large amounts of data is involved). - -h4. Stateful mode - -Domain classes are by default stateful, which means when they are read from a MongoDB document their state is stored in the user session (which is typically bound to the request in Grails). This has several advantages for write heavy applications: - -* GORM can automatically detect whether a call to save() is a an update or an insert and act appropriately -* GORM store the state of the read MongoDB document and therefore updates to schemaless properties don't require an extra query -* GORM can store the version and therefore implement optimistic locking -* Repeated reads of the same entity can be retrieved from the cache, thus optimizing reads as well - -For an example of when a stateful domain class is better consider the following: - -{code} -def b = Book.get(1) -b['pages'] = 400 -b['publisher'] = 'Manning' -b['rating'] = 5 -b.save(flush:true) -{code} - -With a stateful entity the updates to the three properties can be batched up and executed in the save() call, when there is no state then 3 updates needs to be executed for each schemaless property (ouch!). - - -h4. Stateless Domain classes - -However, stateful domain classes can cause problems for read-heavy applications. Take for example the following code: - -{code} -def books = Book.list() // read 100,000 books -for(b in books) { - println b.title -} -{code} - -The above example will read 100,000 books and print the title of each. In stateful mode this will almost certainly run out of memory as each MongoDB document is stored in user memory as is each book. Rewriting the code as follows will solve the problem: - -{code} -Book.withStatelessSession { - def books = Book.list() // read 100,000 books - for(b in books) { - println b.title - } -} -{code} - -Alternatively you can map the domain class as stateless, in which case its state will never be stored in the session: - -{code} -class Book { - ... - static mapping = { - stateless true - } -} -{code} - -h4. Disadvantages of Stateless Mode - -There are several disadvantages to using stateless domain classes as the default. One disadvantage is that if you are using assigned identifiers GORM cannot detect whether you want to do an insert or an update so you have to be explicit about which one you want: - -{code} -def b = new Book(id:"The Book") -b.insert() -{code} - -In the above case we use the explicit 'insert' method to tell Grails this is an insert not an udpate. Another disadvantage is that reading of schemaless/dynamic properties is more costly. For example: - - -{code} -def books = Book.list() // read 100,000 books -for(b in books) { - println b['pages'] - println b['rating'] -} -{code} - -Here GORM has to execute an additional read method for each schemaless property! This is better written as: - -{code} -def books = Book.list() // read 100,000 books -for(b in books) { - def dbo = b.dbo - println dbo['pages'] - println dbo['rating'] -} -{code} - -Thus only requiring one query. Or alternatively you can use the native API: - -{code} -def books = Book.collection.find() // read 100,000 books -for(dbo in books) { - Book b = dbo as Book - println dbo['pages'] - println dbo['rating'] -} -{code} - -Which would be more efficient. - - diff --git a/grails-documentation-mongo/src/docs/guide/4. Low-level API.gdoc b/grails-documentation-mongo/src/docs/guide/4. Low-level API.gdoc deleted file mode 100644 index bb03d76fd..000000000 --- a/grails-documentation-mongo/src/docs/guide/4. Low-level API.gdoc +++ /dev/null @@ -1,68 +0,0 @@ -A lower level API is provided by the plugin that is based on the [GMongo|http://github.com/poiati/gmongo] project. - -GMongo is a simple Groovy wrapper around the regular [Mongo Java Driver|http://www.mongodb.org/display/DOCS/Java+Language+Center]. In general you can refer to the Mongo Java Drivers [Javadoc API|http://api.mongodb.org/java/current/index.html] when using GMongo. - -GMongo provides some nice enhancements like easy access to collections using the dot operator and support for Groovy operator overloading. - -{note} -There is an excellent tutorial on how to use the Mongo Java driver's API directly in the [Mongo documentation|http://www.mongodb.org/display/DOCS/Java+Tutorial] -{note} - -An example of GMongo usage can be seen below: - -{code} -// Get a db reference in the old fashion way -def db = mongo.getDB("gmongo") - -// Collections can be accessed as a db property (like the javascript API) -assert db.myCollection instanceof com.mongodb.DBCollection -// They also can be accessed with array notation -assert db['my.collection'] instanceof com.mongodb.DBCollection - -// Insert a document -db.languages.insert([name: 'Groovy']) -// A less verbose way to do it -db.languages.insert(name: 'Ruby') -// Yet another way -db.languages << [name: 'Python'] - -// Insert a list of documents -db.languages << [[name: 'Javascript', type: 'prototyped'], [name: 'Ioke', type: 'prototyped']] -{code} - - -To get hold of the @mongo@ instance (which is an of the [com.mongodb.Mongo|http://api.mongodb.org/java/current/com/mongodb/Mongo.html] class) inside a controller or service simple define a @mongo@ property: - -{code} -def mongo -def myAction = { - def db = mongo.getDB("mongo") - db.languages.insert([name: 'Groovy']) -} -{code} - -A request scoped bean is also available for the default database (typically the name of your application, unless specified by the @databaseName@ config option, plus the suffix "DB"). - -{code} -def peopleDB -def myAction = { - peopleDB.languages.insert([name: 'Fred']) -} -{code} - -Each domain class you define also has a @collection@ property that allows easy access to the underlying @DBCollection@ instance and hence the GMongo API: - -{code} -Person.collection.count() == 1 -Person.collection.findOne(firstName:"Fred").lastName == "Flintstone" -{code} - -{note} -If you are using Hibernate entities with Mongo then the collection will be scoped in the @mongo@ namespace. Example: Person.mongo.collection.count() -{note} - -You can easily convert from a native MongoDB @DBObject@ into an entity using a cast: - -{code} -def fred = Person.collection.findOne(firstName:"Fred") as Person -{code} \ No newline at end of file diff --git a/grails-documentation-mongo/src/docs/guide/5. Transactions.gdoc b/grails-documentation-mongo/src/docs/guide/5. Transactions.gdoc deleted file mode 100644 index dba5e49ee..000000000 --- a/grails-documentation-mongo/src/docs/guide/5. Transactions.gdoc +++ /dev/null @@ -1,21 +0,0 @@ -Mongo doesn't support transactions directly, however GORM for Mongo does batch up inserts and updates until the session is flushed. This makes it possible to support some rollback options. - -You can use either transactional services or the static @withTransaction@ method. To mark a service as using the Mongo transaction manager, use the static @transactional@ property with the value @'mongo'@: - -{code} -static transactional = 'mongo' -{code} - -Alternately you can do ad-hoc transactions using the @withTransaction@ method: - -{code} -Person.withTransaction { status -> - new Person(name:"Bob", age:50).save() - throw new RuntimeException("bad") - new Person(name:"Fred", age:45).save() -} -{code} - -For example in this case neither @Person@ object will be persisted to the database, because underneath the surface a persistence session is being used to batch up both insert operations into a single insert. When the exception is thrown neither insert is ever executed, hence we allow for some transactional semantics are the GORM-level. - -Using the lower level API you can of course also take advantage of Mongo's support for [Atomic operations|http://www.mongodb.org/display/DOCS/Atomic+Operations]. diff --git a/grails-documentation-mongo/src/docs/guide/6. Unit Testing.gdoc b/grails-documentation-mongo/src/docs/guide/6. Unit Testing.gdoc deleted file mode 100644 index e6d9619c4..000000000 --- a/grails-documentation-mongo/src/docs/guide/6. Unit Testing.gdoc +++ /dev/null @@ -1,40 +0,0 @@ -If you are using Grails 1.3.x then the Mongo plugin provides a Groovy mixin called [DatastoreUnitTestMixin|testing] for testing purposes. For Grails 2.0.x and above you can use the normal @TestFor support and Grails' built in testing mechanism. - -{note} -The below documentation applies to Grails 1.3.x only. Grails 2.0.x users can use the built in GORM testing support that ships with Grails 2.0. -{note} - -This mixin sets up a datastore implementation that operates against an in-memory @ConcurrentHashMap@. The datastore implementation that operates against an in-memory map is as complete as the one for Mongo and provides support for: - -* Simple persistence methods -* Dynamic finders -* Criteria -* Named queries -* Inheritance - -You can easily write tests that use the mixin using Groovy's @Mixin@ annotation on any existing unit test: - -{code} -import grails.datastore.test.DatastoreUnitTestMixin - -@Mixin(DatastoreUnitTestMixin) -class PersonTests extends GroovyTestCase { - void testPersist() { - mockDomain(Person) - def s = new Person(name:"Bob") - s.save() - - assert s.id != null - - s = Person.get(s.id) - - assert s != null - } - - void tearDown() { - disconnect() - } -} -{code} - -You should call the @mockDomain()@ method to mock a domain instance and then the remainder of the API is the same. Note that you should call @disconnect()@ in @tearDown()@ otherwise your tests will share data. diff --git a/grails-documentation-mongo/src/docs/ref/Beans/mongo.gdoc b/grails-documentation-mongo/src/docs/ref/Beans/mongo.gdoc deleted file mode 100644 index 2f440c493..000000000 --- a/grails-documentation-mongo/src/docs/ref/Beans/mongo.gdoc +++ /dev/null @@ -1,23 +0,0 @@ -h1. mongo - -h2. Purpose - -A Spring bean that provides access to the lower level Mongo API based on GMongo - -h2. Examples - -{code} -def mongo - -def foo = { - def mongo - def myAction = { - def db = mongo.getDB("mongo") - db.languages.insert([name: 'Groovy']) - } -} -{code} - -h2. Description - -See the [GMongo|https://github.com/poiati/gmongo] docs and the API for [Mongo Java Driver|http://api.mongodb.org/java/current/] for API usage info. diff --git a/grails-documentation-mongo/src/docs/ref/Domain Classes/DB.gdoc b/grails-documentation-mongo/src/docs/ref/Domain Classes/DB.gdoc deleted file mode 100644 index 5921a8c07..000000000 --- a/grails-documentation-mongo/src/docs/ref/Domain Classes/DB.gdoc +++ /dev/null @@ -1,15 +0,0 @@ -h1. DB - -h2. Purpose - -Returns the MongoDB [DB|http://api.mongodb.org/java/current/com/mongodb/DB.html] object. - -h2. Examples - -{code:java} -def dbCollection = Book.DB.getCollection("books") -{code} - -h2. Description - -The @DB@ property allows access to the underlying MongoDB [DB|http://api.mongodb.org/java/current/com/mongodb/DB.html] object, thus allowing easy access to the low-level MongoDB Java driver. diff --git a/grails-documentation-mongo/src/docs/ref/Domain Classes/collection.gdoc b/grails-documentation-mongo/src/docs/ref/Domain Classes/collection.gdoc deleted file mode 100644 index c4f132a00..000000000 --- a/grails-documentation-mongo/src/docs/ref/Domain Classes/collection.gdoc +++ /dev/null @@ -1,15 +0,0 @@ -h1. collection - -h2. Purpose - -Returns the MongoDB [collection|http://api.mongodb.org/java/current/com/mongodb/DBCollection.html] used for the current domain class - -h2. Examples - -{code:java} -def bookBson = Book.collection.findOne() -{code} - -h2. Description - -The @collection@ property allows access to the underlying MongoDB [DBCollection|http://api.mongodb.org/java/current/com/mongodb/DBCollection.html] object, thus allowing direct access to the low-level MongoDB driver. diff --git a/grails-documentation-mongo/src/docs/ref/Domain Classes/collectionName.gdoc b/grails-documentation-mongo/src/docs/ref/Domain Classes/collectionName.gdoc deleted file mode 100644 index a2eab306d..000000000 --- a/grails-documentation-mongo/src/docs/ref/Domain Classes/collectionName.gdoc +++ /dev/null @@ -1,15 +0,0 @@ -h1. collectionName - -h2. Purpose - -Returns the name of the MongoDB [collection|http://api.mongodb.org/java/current/com/mongodb/DBCollection.html] used for the current domain class - -h2. Examples - -{code:java} -println Book.collectionName -{code} - -h2. Description - -The @collectionName@ property allows introspection of the name of the [DBCollection|http://api.mongodb.org/java/current/com/mongodb/DBCollection.html] object used by a given domain class. Can be used in conjunction with @useCollection@ to switch to different collections and back again. diff --git a/grails-documentation-mongo/src/docs/ref/Domain Classes/dbo.gdoc b/grails-documentation-mongo/src/docs/ref/Domain Classes/dbo.gdoc deleted file mode 100644 index de2aa5490..000000000 --- a/grails-documentation-mongo/src/docs/ref/Domain Classes/dbo.gdoc +++ /dev/null @@ -1,17 +0,0 @@ -h1. dbo - -h2. Purpose - -Returns the MongoDB [DBObject|http://api.mongodb.org/java/current/com/mongodb/DBObject.html] for an instance of a domain class - -h2. Examples - -{code:java} -def b = Book.get(1) - -println b.dbo -{code} - -h2. Description - -The @dbo@ property allows access to the underlying MongoDB [DBObject|http://api.mongodb.org/java/current/com/mongodb/DBObject.html], which is a respresentation of the stored BSON document that can be manipulated in memory. diff --git a/grails-documentation-mongo/src/docs/ref/Domain Classes/useCollection.gdoc b/grails-documentation-mongo/src/docs/ref/Domain Classes/useCollection.gdoc deleted file mode 100644 index 2bd600a3a..000000000 --- a/grails-documentation-mongo/src/docs/ref/Domain Classes/useCollection.gdoc +++ /dev/null @@ -1,15 +0,0 @@ -h1. useCollection - -h2. Purpose - -Allows switching which collection to use to persist for the domain class for the scope of the current session (connection). - -h2. Examples - -{code:java} -Book.useCollection("non-fiction") -{code} - -h2. Description - -The @useCollection@ method allows switching, at runtime, the collection used persist and retrieve domain classes. The @collectionName@ property will return the current collection being used. Note that the method switches the collection used for the scope of the current session/connection (ie. it is not permanent). If you wish to permanently change the collection used then you need to configure the mapping of the domain class. diff --git a/grails-documentation-mongo/src/docs/ref/Domain Classes/useDatabase.gdoc b/grails-documentation-mongo/src/docs/ref/Domain Classes/useDatabase.gdoc deleted file mode 100644 index ada729797..000000000 --- a/grails-documentation-mongo/src/docs/ref/Domain Classes/useDatabase.gdoc +++ /dev/null @@ -1,15 +0,0 @@ -h1. useDatabase - -h2. Purpose - -Allows switching which database to use to persist for the domain class for the scope of the current session (connection). - -h2. Examples - -{code:java} -Book.useDatabase("non-fiction") -{code} - -h2. Description - -The @useDatabase@ method allows switching, at runtime, the database used persist and retrieve domain classes. The @DB@ property will return the current database being used. Note that the method switches the database used for the scope of the current session/connection (ie. it is not permanent). If you wish to permanently change the database used then you need to configure the mapping of the domain class. diff --git a/grails-documentation-mongo/src/docs/ref/Domain Classes/withCollection.gdoc b/grails-documentation-mongo/src/docs/ref/Domain Classes/withCollection.gdoc deleted file mode 100644 index 480b925a1..000000000 --- a/grails-documentation-mongo/src/docs/ref/Domain Classes/withCollection.gdoc +++ /dev/null @@ -1,17 +0,0 @@ -h1. withCollection - -h2. Purpose - -Allows switching which collection to use to persist for the domain class for the scope of the given closure - -h2. Examples - -{code:java} -Book.withCollection("non-fiction") { - // code here -} -{code} - -h2. Description - -The @useCollection@ method allows switching, at runtime, the collection used persist and retrieve domain classes. The @collectionName@ property will return the current collection being used. Note that the method switches the collection used for the scope of given closure (ie. it is not permanent). If you wish to permanently change the collection used then you need to configure the mapping of the domain class. diff --git a/grails-documentation-mongo/src/docs/ref/Domain Classes/withDatabase.gdoc b/grails-documentation-mongo/src/docs/ref/Domain Classes/withDatabase.gdoc deleted file mode 100644 index 3723da153..000000000 --- a/grails-documentation-mongo/src/docs/ref/Domain Classes/withDatabase.gdoc +++ /dev/null @@ -1,17 +0,0 @@ -h1. withDatabase - -h2. Purpose - -Allows switching which database to use to persist for the domain class for the scope of the given closure. - -h2. Examples - -{code:java} -Book.withDatabase("non-fiction") { - // code here -} -{code} - -h2. Description - -The @withDatabase@ method allows switching, at runtime, the database used persist and retrieve domain classes. The @DB@ property will return the current database being used. Note that the method switches the database used for the scope of the given closure (ie. it is not permanent). If you wish to permanently change the database used then you need to configure the mapping of the domain class. diff --git a/grails-documentation-mongo/src/docs/ref/Testing/DatastoreUnitTestMixin.gdoc b/grails-documentation-mongo/src/docs/ref/Testing/DatastoreUnitTestMixin.gdoc deleted file mode 100644 index cfd12b397..000000000 --- a/grails-documentation-mongo/src/docs/ref/Testing/DatastoreUnitTestMixin.gdoc +++ /dev/null @@ -1,36 +0,0 @@ -h1. DatastoreUnitTestMixin - -h2. Purpose - -A mixin for setting up unit testing of datastores such as the Mongo datastore. - -h2. Examples - -{code} -import grails.datastore.test.DatastoreUnitTestMixin - -@Mixin(DatastoreUnitTestMixin) -class PersonTests extends GroovyTestCase { - void testPersist() { - mockDomain(Person) - def s = new Person(name:"Bob") - s.save() - - assert s.id != null - - s = Person.get(s.id) - - assert s != null - } - - void tearDown() { - disconnect() - } -} -{code} - -h2. Description - -@DatastoreUnitTestMixin@ allows you to test datastore interactions by mocking the complete GORM API including simple persistence methods, dynamic finders, criteria queries and named queries. - -If you want to make sure that tests do not share data, add an implementation of @tearDown()@ (or the equivalent in your test framework) that calls the @disconnect()@ method. Also make sure to call the super class method if necessary! diff --git a/grails-documentation-neo4j/build.gradle b/grails-documentation-neo4j/build.gradle deleted file mode 100644 index 27d21832e..000000000 --- a/grails-documentation-neo4j/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -task assemble(dependsOn:docs) << { - group = "docs" -} \ No newline at end of file diff --git a/grails-documentation-neo4j/resources/img/mapping.png b/grails-documentation-neo4j/resources/img/mapping.png deleted file mode 100644 index 6076e2a85..000000000 Binary files a/grails-documentation-neo4j/resources/img/mapping.png and /dev/null differ diff --git a/grails-documentation-neo4j/src/docs/doc.properties b/grails-documentation-neo4j/src/docs/doc.properties deleted file mode 100644 index 0c76c60f4..000000000 --- a/grails-documentation-neo4j/src/docs/doc.properties +++ /dev/null @@ -1,3 +0,0 @@ -title=GORM for Neo4j -version=1.0.0 -authors=Stefan Armbruster \ No newline at end of file diff --git a/grails-documentation-neo4j/src/docs/guide/advancedConfiguration.gdoc b/grails-documentation-neo4j/src/docs/guide/advancedConfiguration.gdoc deleted file mode 100644 index fd029b516..000000000 --- a/grails-documentation-neo4j/src/docs/guide/advancedConfiguration.gdoc +++ /dev/null @@ -1,95 +0,0 @@ -As mentioned the GORM for Neo4j plugin will configure all the defaults for you, but if you wish to customize those defaults you can do so in the your @grails-app/conf/DataSource.groovy@ file: - -{code} -grails { - neo4j { - type = "embedded" - location = "/var/neo4j" - params = [] - } -} -{code} - -The @type@ provides currently the following choices: - -h4. type = "embedded" -Runs the Neo4j in embedded mode, Neo4j and Tomcat use the same JVM. No seperate setup outside the Grails application is required. @location@ specifies the directory where Neo4j stores its data. - -Example: -{code} -grails { - neo4j { - type = "embedded" - location = "/var/neo4j" - } -} -{code} - -{note} -If your configuration is empty, 'embedded' is used as default. -{note} - -h4. type = "rest" -Uses a @org.neo4j.rest.graphdb.RestGraphDatabase@ instance to connect to a Neo4j database. See [http://docs.neo4j.org/chunked/stable/server.html|http://docs.neo4j.org/chunked/stable/server.html] for how to setup a Neo4j server. - -@location@ specifies the URL of he Neo4j REST server. When using the Heroku neo4j addon, omit the location. In this case location will default to env.NEO4J_URL that is provided by Heroku. - -Example: -{code} -grails { - neo4j { - type = "rest" - location = "http://localhost:7474/db/data/" - } -} -{code} - -Additionally you must add another dependency to your application's @grails-app/conf/BuildConfig.groovy@: - -{code} -compile("org.neo4j:neo4j-rest-graphdb:1.6") -{code} - -h4. type = "ha" -Uses a Neo4j HA setup, for details see [http://docs.neo4j.org/chunked/stable/ha.html|http://docs.neo4j.org/chunked/stable/ha.html]. In this case params must at least contain - -{note} -For Neo4j HA either a commercial license is [required|http://neo4j.org/licensing-guide/], or you could use AGPL. -{note} - -Example: -{code} -grails { - neo4j { - type = "ha" - location = "/var/neo4j" - params = [ // see http://docs.neo4j.org/chunked/stable/ha-configuration.html - 'ha.server_id': 1, - 'ha.coordinators': 'localhost:2181,localhost:2182,localhost:2183' - ] - } -} -{code} - -Additionally you must add another dependency to your application's @grails-app/conf/BuildConfig.groovy@: - -{code} -compile('org.neo4j:neo4j-enterprise:1.8.RC1') -{code} - -h4. type = "impermanent" -Uses [ImpermanentGraphDatabase|https://github.com/neo4j/community/blob/master/kernel/src/test/java/org/neo4j/test/ImpermanentGraphDatabase.java]. -This option required a dependency to artifact [group: "org.neo4j", name:"neo4j-kernel", version:neo4jVersion, classifier:'tests'] in BuildConfig.groovy. -ImpermanentGraphDatabase is intended to be used for testing. - -h4. custom graph database -If you use a custom implementation of GraphDatabaseService, you can use -{code} -grails { - neo4j { - type = "my.fancy.custom.GraphDatabaseServiceImplementation" - location = "/var/neo4j" - params = [ :] - } -} -{code} diff --git a/grails-documentation-neo4j/src/docs/guide/combiningNeo4jAndHibernate.gdoc b/grails-documentation-neo4j/src/docs/guide/combiningNeo4jAndHibernate.gdoc deleted file mode 100644 index 874dba13c..000000000 --- a/grails-documentation-neo4j/src/docs/guide/combiningNeo4jAndHibernate.gdoc +++ /dev/null @@ -1,16 +0,0 @@ -If you have both the Hibernate and Neo4j plugins installed then by default all classes in the @grails-app/domain@ directory will be persisted by Hibernate and not Neo4j. If you want to persist a particular domain class with Neo4j then you must use the @mapWith@ property in the domain class: - -{code} -static mapWith = "neo4j" -{code} - -Alternatively you can persist Hibernate entities to Neo4j using the special @neo4j@ scope added to all Hibernate entities: - -{code} -def hibernatePerson = Person.get(1) - -hibernatePerson.neo4j.save() - -def neo4jPerson = Person.neo4j.get(1) -{code} - diff --git a/grails-documentation-neo4j/src/docs/guide/compatibility.gdoc b/grails-documentation-neo4j/src/docs/guide/compatibility.gdoc deleted file mode 100644 index 1b216b63d..000000000 --- a/grails-documentation-neo4j/src/docs/guide/compatibility.gdoc +++ /dev/null @@ -1,22 +0,0 @@ -This implementation tries to be as compatible as possible with GORM for Hibernate. In general you can refer to the [GORM documentation|http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html] and the "Domain Classes" section of the [reference guide|http://grails.org/doc/latest/] (see the left nav) for usage information. - -The following key features are supported by GORM for Neo4j: - -* Simple persistence methods -* Dynamic finders -* Criteria queries -* Named queries -* Inheritance -* Embedded types -* Query by example -* Many-to-many associations (these can be modelled with a mapping class) - -However, some features are not supported: - -* HQL queries -* Dirty checking methods -* Composite primary keys -* Any direct interaction with the Hibernate API -* Custom Hibernate user types - -There may be other limitations not mentioned here so in general it shouldn't be expected that an application based on GORM for Hibernate will "just work" without some tweaking involved. Having said that, the large majority of common GORM functionality is supported. diff --git a/grails-documentation-neo4j/src/docs/guide/gettingStarted.gdoc b/grails-documentation-neo4j/src/docs/guide/gettingStarted.gdoc deleted file mode 100644 index 2795f1321..000000000 --- a/grails-documentation-neo4j/src/docs/guide/gettingStarted.gdoc +++ /dev/null @@ -1,17 +0,0 @@ -To get started with GORM for Neo4j you need to install the plugin into a Grails application: - -{code} -grails install-plugin neo4j -{code} - -Or configure it as a dependency in @BuildConfig.groovy@: - -{code} -plugins { - compile "\:neo4j:latest.version" -} -{code} - -By default Neo4j will used as embedded database inside the JVM, the default directory for the Neo4j datastore is @data/neo4j@. - - diff --git a/grails-documentation-neo4j/src/docs/guide/introduction.gdoc b/grails-documentation-neo4j/src/docs/guide/introduction.gdoc deleted file mode 100644 index 46c8c5f09..000000000 --- a/grails-documentation-neo4j/src/docs/guide/introduction.gdoc +++ /dev/null @@ -1,12 +0,0 @@ -[Neo4j|http://www.neo4j.org] is (as of now) the only graph database that fits nicely in a Grails application. - -The goal of this grails-data-mapping subproject is to provide a 'as-complete-as-possible' GORM implemenatition that maps domain classes and instances to the Neo4j nodespace. The following features are supported: - -* Marshalling from Neo4j nodespace to Groovy/Java types and back again -* Support for GORM dynamic finders, criteria and named queries -* Session-managed transactions -* Validating domain instances -* access to Neo4j's traversal capabilities -* access the Neo4j graph database in all flavours (Embedded, REST and HA) -* using Neo4j autoindexing - diff --git a/grails-documentation-neo4j/src/docs/guide/mapping.gdoc b/grails-documentation-neo4j/src/docs/guide/mapping.gdoc deleted file mode 100644 index fc45738ec..000000000 --- a/grails-documentation-neo4j/src/docs/guide/mapping.gdoc +++ /dev/null @@ -1,22 +0,0 @@ -Since the nodespace in Neo4j has no schema as opposed to SQL, there must be some structure applied to map a given -set of domain classes. - -Starting with "Neo4j's reference node":http://api.neo4j.org/current/org/neo4j/graphdb/GraphDatabaseService.html#getReferenceNode(), -each domain class itself is represented by a subreference node. The subreference node has a relationship to the reference node, -type "SUBREFERENCE". Each instance of this domain class is represented by a node connected to the respective subreference -node by a relationship of type "INSTANCE". - -All simple properties of a domain instance are mapped to the node's properties. Since a node can only store primitives, -Strings and arrays of both, properties of any other type must be converted before persisting. The conversion uses Spring's -ConversionService, [Neo4jMappingContext|https://github.com/SpringSource/grails-data-mapping/blob/master/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/Neo4jMappingContext.groovy] -adds a couple of converters to it. References to other domain classes are mapped by relationships. - -{note} -Type conversion is not 100% complete for now. If you experience conversion problems, please file a ticket in Github's -issue tracker. -{note} - -The described mapping of domain classes to the node space is best illustrated with an picture: - -!mapping.png! -!https://github.com/SpringSource/grails-data-mapping/raw/master/grails-documentation-neo4j/resources/img/mapping.png! \ No newline at end of file diff --git a/grails-documentation-neo4j/src/docs/guide/neo4jEnhancements.gdoc b/grails-documentation-neo4j/src/docs/guide/neo4jEnhancements.gdoc deleted file mode 100644 index 95d19fd41..000000000 --- a/grails-documentation-neo4j/src/docs/guide/neo4jEnhancements.gdoc +++ /dev/null @@ -1,31 +0,0 @@ -Inspired by a [Github issue ticket|https://github.com/SpringSource/grails-data-mapping/issues/66] the Neo4j Grails contains some -enhancements to the Neo4j core API. These enhancements are implemented using Groovy's ExpandoMetaClass. - -h4. setting properties on nodes/relationships - -Assigning an arbitrary property onto a Neo4j node or relationship can be simply done by using Groovy's property -mechanism: -{code} -def node = graphDatabaseService.createNode() -node.myProperty = myValue -{code} - -The same words for getting properties: - -{code} -def node = ... -def value = node.myProperty -{code} - -{note} -There is a important convention: when the property ends with "Date" then a date type is assumed. The node property then -helds respective millis. -{note} - -h4. JSON marshalling -Neo4j nodes and relationships can be easily marshalled to JSON, e.g. in a controller using: - -{code} -def node = graphDatabaseService.getNodeById(myid) -render node as JSON -{code} \ No newline at end of file diff --git a/grails-documentation-neo4j/src/docs/guide/releaseNotes.gdoc b/grails-documentation-neo4j/src/docs/guide/releaseNotes.gdoc deleted file mode 100644 index 4b2f45bd7..000000000 --- a/grails-documentation-neo4j/src/docs/guide/releaseNotes.gdoc +++ /dev/null @@ -1,15 +0,0 @@ -Below are the details of the changes across releases: - -h4. 1.0.0 - -* works with Neo4j HA -* implementing new GORM property criteria filters -* uses Neo4j 1.8.2 - -h4. 0.9-SNAPSHOT -* first GORM compliant version of the plugin -* works with embedded and REST Neo4j databases -* exposing traversal options to domain classes - -h4. up to 0.3.1 -* uses non GORM compliant implementation. diff --git a/grails-documentation-neo4j/src/docs/guide/sampleApp.gdoc b/grails-documentation-neo4j/src/docs/guide/sampleApp.gdoc deleted file mode 100644 index 2c0c90e63..000000000 --- a/grails-documentation-neo4j/src/docs/guide/sampleApp.gdoc +++ /dev/null @@ -1,7 +0,0 @@ -There is a demo application available at "https://github.com/sarmbruster/neo4jsample":https://github.com/sarmbruster/neo4jsample -As of now this application contains just a small set of domain classes with scaffolding controllers. - -The demo app uses by default a REST datasource. If you want to use a local embedded instance you need to change -@grails-app/conf/Datasource.groovy@ to fit your needs. - -... more to come here... diff --git a/grails-documentation-neo4j/src/docs/guide/toc.yml b/grails-documentation-neo4j/src/docs/guide/toc.yml deleted file mode 100644 index 43b66a088..000000000 --- a/grails-documentation-neo4j/src/docs/guide/toc.yml +++ /dev/null @@ -1,12 +0,0 @@ -introduction: - title: Introduction - compatibility: Compatibility with GORM for Hibernate - releaseNotes: Release Notes -gettingStarted: - title: Getting Started - usingNeo4jStandalone: Using Neo4j Standalone - combiningNeo4jAndHibernate: Combining Neo4j And Hibernate - advancedConfiguration: Advanced Configuration -mapping: Mapping domain classes to Neo4j node space -neo4jEnhancements: Enhancements to Neo4j core API -sampleApp: Sample Application diff --git a/grails-documentation-neo4j/src/docs/guide/usingNeo4jStandalone.gdoc b/grails-documentation-neo4j/src/docs/guide/usingNeo4jStandalone.gdoc deleted file mode 100644 index 36be33eb6..000000000 --- a/grails-documentation-neo4j/src/docs/guide/usingNeo4jStandalone.gdoc +++ /dev/null @@ -1,19 +0,0 @@ -If you plan to use Neo4j as your primary datastore then you need to uninstall the Hibernate plugin: - -{code} -grails uninstall-plugin hibernate -{code} - -Or if it has been defined in the @grails-app/conf/BuildConfig.groovy@ file comment out the hibernate line in the plugins block - -{code} -compile "\:hibernate:$grailsVersion" -{code} - -With this done all domain classes in grails-app/domain will be persisted via Neo4j and not Hibernate. You can create a domain class by running the regular @create-domain-class@ command: - -{code} -grails create-domain-class Person -{code} - -The @Person@ domain class will automatically be a persistent entity that can be stored in Neo4j. diff --git a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/createInstanceForNode.gdoc b/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/createInstanceForNode.gdoc deleted file mode 100644 index 01cf20402..000000000 --- a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/createInstanceForNode.gdoc +++ /dev/null @@ -1,42 +0,0 @@ -h1. createInstanceForNode - -h2. Purpose - -Retrieve a domain class instance associated with the given node. - -h2. Example - -Assume some domain class: -{code} -class Person { - String name -} -{code} - - -{code} -def person = new Person(name:'Joe') -person.save(flush:true) - -// somewhere later - -Node node = .... // some code returning a Neo4j node -def samePerson = Person.createInstanceForNode(node) - -// works also with nodeId -samePerson = Person.createInstanceForNode(person.id) -{code} - -h2. Description - -{code}def createInstanceForNode(nodeOrId) {code} - -@createInstanceForNode@ may by invoke statically on each domain class and returns a domain class instance that is -represented by that node. - -h3. Arguments - -@nodeOrId@: a Neo4j node or the node's id - -h3. Return value -A domain class instance or null if the node does not represent an entity. \ No newline at end of file diff --git a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/cypher.gdoc b/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/cypher.gdoc deleted file mode 100644 index 3c5aec2e9..000000000 --- a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/cypher.gdoc +++ /dev/null @@ -1,33 +0,0 @@ -h1. cypher - -h2. Purpose - -Execute a cypher query. - -h2. Example - -{code} -setup: -def person = new Person(firstName: "Bob", lastName: "Builder") -def petType = new PetType(name: "snake") -def pet = new Pet(name: "Fred", type: petType, owner: person) -person.addToPets(pet) -person.save(flush: true) -session.clear() - -when: -def result = person.cypher("start n=node({this}) match n-[:pets]->m return m") - -then: -result.iterator().size() == 1 -{code} - -h2. Description - -@cypher@ is invoked on any domain instance and returns a "ExecutionResult":http://api.neo4j.org/current/org/neo4j/cypher/javacompat/ExecutionResult.html -The parameters passed are: -* cypher query string. The query string might use a implizit @this@ parameter pointing to the instance's node -* a optional map of cypher parameters - - - diff --git a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/cypherStatic.gdoc b/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/cypherStatic.gdoc deleted file mode 100644 index fb8c7dcce..000000000 --- a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/cypherStatic.gdoc +++ /dev/null @@ -1,31 +0,0 @@ -h1. cypherStatic - -h2. Purpose - -Execute a cypher query. - -h2. Example - -{code} -setup: -new Person(lastName:'person1').save() -new Person(lastName:'person2').save() -session.flush() -session.clear() - -when: -def result = Person.cypherStatic("start n=node({this}) match n-[:INSTANCE]->m where m.lastName='person1' return m") - -then: -result.iterator().size()==1 -{code} - -h2. Description - -@cypherStatic@ is invoked on any domain class and returns a "ExecutionResult":http://api.neo4j.org/current/org/neo4j/cypher/javacompat/ExecutionResult.html -The parameters passed are: -* cypher query string. The query string might use a implicit @this@ parameter pointing to the domain class's (aka subreference) node -* a optional map of cypher parameters - - - diff --git a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/getNode.gdoc b/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/getNode.gdoc deleted file mode 100644 index eb6abc636..000000000 --- a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/getNode.gdoc +++ /dev/null @@ -1,16 +0,0 @@ -h1. getNode - -h2. Purpose - -Provide acces to the Neo4j node associated with this domain instance. - -h2. Example - -{code} - def person = Person.findByName("Joe") - def node = person.node -{code} - -h2. Description - -Returns a "Neo4j's Node":http://api.neo4j.org/current/org/neo4j/graphdb/Node.html instance. \ No newline at end of file diff --git a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/getSubreferenceNode.gdoc b/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/getSubreferenceNode.gdoc deleted file mode 100644 index d98480ed0..000000000 --- a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/getSubreferenceNode.gdoc +++ /dev/null @@ -1,11 +0,0 @@ -h1. getSubreferenceNode - -h2. Purpose - -Return the subReference node representing a domain class in the nodespace. - -h2. Example - -{code} -Node subReference = person.subReferenceNode -{code} diff --git a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/schemaless attributes.gdoc b/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/schemaless attributes.gdoc deleted file mode 100644 index 14ca2d200..000000000 --- a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/schemaless attributes.gdoc +++ /dev/null @@ -1,73 +0,0 @@ -h1. schemaless attributes - -h2. Purpose - -For domain classes mapped by Neo4j you can put and get arbitrary attributes on a instances by using the dot operator or -map semantics on the domain instance. - -{note} -Setting arbitrary attribute in only allowed when the domain instance is persisted (aka @save@ has been called)! -{note} - -h2. Example - -A simple domain class: -{code} -class Person implements Serializable { - String firstName - String lastName - Integer age = 0 -} -{code} - -h3. using map semantics -{code} -when: -def person = new Person(lastName:'person1').save() -person['notDeclaredProperty'] = 'someValue' // n.b. the 'dot' notation is not valid for undeclared properties -person['emptyArray'] = [] -person['someIntArray'] = [1,2,3] -person['someStringArray'] = ['a', 'b', 'c'] -person['someDoubleArray'] = [0.9, 1.0, 1.1] -session.flush() -session.clear() -person = Person.get(person.id) - -then: -person['notDeclaredProperty'] == 'someValue' -person['lastName'] == 'person1' // declared properties are also available via map semantics -person['someIntArray'] == [1,2,3] -person['someStringArray'] == ['a', 'b', 'c'] -person['someDoubleArray'] == [0.9, 1.0, 1.1] -{code} - -h3. using dot operator -{code} -when: -def person = new Person(lastName:'person1').save(flush:true) -session.clear() -person = Person.load(person.id) -person.notDeclaredProperty = 'someValue' // n.b. the 'dot' notation is not valid for undeclared properties -person.emptyArray = [] -person.someIntArray = [1,2,3] -person.someStringArray = ['a', 'b', 'c'] -person.someDoubleArray= [0.9, 1.0, 1.1] -session.flush() -session.clear() -person = Person.get(person.id) - -then: -person.notDeclaredProperty == 'someValue' -person.lastName == 'person1' // declared properties are also available via map semantics -person.someIntArray == [1,2,3] -person.someStringArray == ['a', 'b', 'c'] -person.emptyArray == [] -person.someDoubleArray == [0.9, 1.0, 1.1] -{code} - -h2. Description - -The non declared attribtes are stored a regular properties on the domain instance's node. The values of the schemaless -attributes must be a valid type for Neo4j property (String, primitives and arrays of the former two). - - diff --git a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/traverse.gdoc b/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/traverse.gdoc deleted file mode 100644 index 181a39caf..000000000 --- a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/traverse.gdoc +++ /dev/null @@ -1,61 +0,0 @@ -h1. traverse - -h2. Purpose - -Perform a Neo4j node taversal starting at the node of this domain instance. - -h2. Example - -{code} -given: -def person = new Person(lastName: "person1") -person.save() -new Person(lastName: "person2").save() - -when: -def traverserResult = person.traverse(Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH) -def size = traverserResult.size() - -then: - -size == person.traverse(StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH).size() - -size+1 == person.traverse(Traverser.Order.BREADTH_FIRST, - { TraversalPosition p -> false }, - { TraversalPosition p -> true }, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH).size() - -size+1 == person.traverse( - { TraversalPosition p -> false }, - { TraversalPosition p -> true }, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH).size() - -size+1 == person.traverse( - { TraversalPosition p -> false }, - { TraversalPosition p -> true } ).size() - -Person.count() == person.traverse( - { TraversalPosition p -> false }, - { TraversalPosition p -> p.currentNode().getProperty("__type__",null) == Person.name } ).size() - -2 == person.traverse( - { TraversalPosition p -> true }, - { TraversalPosition p -> true } ).size() -{code} - -h2. Description - -@traverse@ is invoked on any domain instance and comes in 4 variants - -{code} -def traverse(Traverser.Order order, StopEvaluator stopEvaluator, ReturnableEvaluator returnableEvaluator, Object... args ) -def traverse(StopEvaluator stopEvaluator, ReturnableEvaluator returnableEvaluator, Object... args) -def traverse(Closure stopEvaluator, Closure returnableEvaluator, Object... args) -def traverse(Traverser.Order order, Closure stopEvaluator, Closure returnableEvaluator, Object... args) -{code} - -All variants return a collection of domain class instances (if the matching nodes can be mapped to a domain class) or of nodes. -See also the "Neo4j API":http://api.neo4j.org/current/ - diff --git a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/traverseStatic.gdoc b/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/traverseStatic.gdoc deleted file mode 100644 index e2385225b..000000000 --- a/grails-documentation-neo4j/src/docs/ref/Additional Gorm Methods/traverseStatic.gdoc +++ /dev/null @@ -1,60 +0,0 @@ -h1. traverseStatic - -h2. Purpose - -Perform a Neo4j node taversal starting at the domain class' subreference node. - -h2. Example - -{code} -given: -new Person(lastName: "person1").save() -new Person(lastName: "person2").save() - -when: -def traverserResult = Person.traverseStatic(Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH) -def size = traverserResult.size() - -then: - -size == Person.traverseStatic(StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH).size() - -size+1 == Person.traverseStatic(Traverser.Order.BREADTH_FIRST, - { TraversalPosition p -> false }, - { TraversalPosition p -> true }, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH).size() - -size+1 == Person.traverseStatic( - { TraversalPosition p -> false }, - { TraversalPosition p -> true }, - GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH).size() - -size+1 == Person.traverseStatic( - { TraversalPosition p -> false }, - { TraversalPosition p -> true } ).size() - -Person.count() == Person.traverseStatic( - { TraversalPosition p -> false }, - { TraversalPosition p -> p.currentNode().getProperty("__type__",null) == Person.name } ).size() - -Person.count()+2 == Person.traverseStatic( // +2: referenceNode + self (aka subreferenceNode) - { TraversalPosition p -> true }, - { TraversalPosition p -> true } ).size() -{code} - -h2. Description - -@traverseStatic@ is invoked statically on each domain class and comes in 4 variants - -{code} -def traverseStatic(Traverser.Order order, StopEvaluator stopEvaluator, ReturnableEvaluator returnableEvaluator, Object... args ) -def traverseStatic(StopEvaluator stopEvaluator, ReturnableEvaluator returnableEvaluator, Object... args) -def traverseStatic(Closure stopEvaluator, Closure returnableEvaluator, Object... args) -def traverseStatic(Traverser.Order order, Closure stopEvaluator, Closure returnableEvaluator, Object... args) -{code} - -All variants return a collection of domain class instances (if the matching nodes can be mapped to a domain class) or of nodes. -See also the "Neo4j API":http://api.neo4j.org/current/ - diff --git a/grails-documentation-neo4j/src/docs/ref/Beans/graphDatabaseService.gdoc b/grails-documentation-neo4j/src/docs/ref/Beans/graphDatabaseService.gdoc deleted file mode 100644 index b45d7b372..000000000 --- a/grails-documentation-neo4j/src/docs/ref/Beans/graphDatabaseService.gdoc +++ /dev/null @@ -1,27 +0,0 @@ -h1. graphDatabaseService - -h2. Purpose - -A Spring bean that provides access to the lower level Neo4j GraphDatabaseService instance. - -h2. Examples - -{code} -def graphDatabaseService - -def foo = { - def graphDatabaseService - def myAction = { - def node = graphDatabaseService.createNode() // create - ... do something with node ...s - } -} -{code} - -h2. Description - -See the [Neo4j Api doc|http://api.neo4j.org/current/org/neo4j/graphdb/GraphDatabaseService.html] docs for how to use the graphDatabaseService bean. - -h2. Configuration - -tbd diff --git a/grails-documentation-redis/build.gradle b/grails-documentation-redis/build.gradle deleted file mode 100644 index 27d21832e..000000000 --- a/grails-documentation-redis/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -task assemble(dependsOn:docs) << { - group = "docs" -} \ No newline at end of file diff --git a/grails-documentation-redis/src/docs/doc.properties b/grails-documentation-redis/src/docs/doc.properties deleted file mode 100644 index 36278986b..000000000 --- a/grails-documentation-redis/src/docs/doc.properties +++ /dev/null @@ -1,3 +0,0 @@ -title=Redis GORM -version=1.0.0.M8 -authors=Graeme Rocher \ No newline at end of file diff --git a/grails-documentation-redis/src/docs/guide/1. Introduction.gdoc b/grails-documentation-redis/src/docs/guide/1. Introduction.gdoc deleted file mode 100644 index a71e9d00a..000000000 --- a/grails-documentation-redis/src/docs/guide/1. Introduction.gdoc +++ /dev/null @@ -1,9 +0,0 @@ -Redis is an advanced key-value store. It is similar to memcached except the dataset is not volatile. Like memcached, Redis can store string values, but it can also store lists, sets, and ordered sets. All these data types can be manipulated with atomic operations that push, pop, add and remove elements, perform server side union, intersection, difference between sets, and more. Redis also supports different kinds of sorting. - -This project aims to provide an object-mapping layer on top of Redis to ease common activities such as: - -* Marshalling from Redis strings to Groovy/Java types and back again -* Creating and caching indices for querying -* Working with transactions -* Validating domain instances backed by the Redis datastore - diff --git a/grails-documentation-redis/src/docs/guide/1.1 Compatibility with GORM for Hibernate.gdoc b/grails-documentation-redis/src/docs/guide/1.1 Compatibility with GORM for Hibernate.gdoc deleted file mode 100644 index 6c9b6222b..000000000 --- a/grails-documentation-redis/src/docs/guide/1.1 Compatibility with GORM for Hibernate.gdoc +++ /dev/null @@ -1,21 +0,0 @@ -This implementation tries to be as compatible as possible with GORM for Hibernate. In general you can refer to the [GORM documentation|http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html] and the "Domain Classes" section of the [reference guide|http://grails.org/doc/latest/] (see the left nav) for usage information. - -The following key features are supported by GORM for Redis: - -* Simple persistence methods -* Dynamic finders -* Criteria queries -* Named queries -* Inheritance - -However, some features are not supported: - -* HQL queries -* Dirty checking methods -* Composite primary keys -* Many-to-many associations (these can be modelled with a mapping class) -* Any direct interaction with the Hibernate API -* Sorting on strings -* Custom Hibernate user types - -There may be other limitations not mentioned here so in general it shouldn't be expected that an application based on GORM for Hibernate will "just work" without some tweaking involved. Having said that, the large majority of common GORM functionality is supported. diff --git a/grails-documentation-redis/src/docs/guide/2. Getting Started.gdoc b/grails-documentation-redis/src/docs/guide/2. Getting Started.gdoc deleted file mode 100644 index f6f049aab..000000000 --- a/grails-documentation-redis/src/docs/guide/2. Getting Started.gdoc +++ /dev/null @@ -1,33 +0,0 @@ -To get started with GORM for Redis you need to install the plugin into a Grails application: - -{code} -grails install-plugin redis-gorm -{code} - -With that done you need to set up a running Redis server. GORM for Redis requires Redis 2.0.0 or above which you can download at on the [Redis download page|http://code.google.com/p/redis/downloads/list]. Once downloaded extract the archive and run the following commands from the @redis-2.0.0@ directory: - -{code} -make -./redis-server -{code} - -With the above commands executed in a terminal window you should see output like the following appear: - -{code} -[66243] 03 Sep 17:35:12 * Server started, Redis version 2.0.0 -[66243] 03 Sep 17:35:12 * DB loaded from disk: 0 seconds -[66243] 03 Sep 17:35:12 * The server is now ready to accept connections on port 6379 -{code} - -As you can see the server is running on port 6379, but don't worry the Redis plugin for Grails will automatically configure itself to look for Redis on that port by default. - -If you want to configure how Grails connects to redis then you can do so using the following settings in @grails-app/conf/Config.groovy@: - -{code} -grails.'redis-gorm'.host="myserver" -grails.'redis-gorm'.port=6380 -grails.'redis-gorm'.password="secret" -grails.'redis-gorm'.pooled=true -grails.'redis-gorm'.resources=15 -grails.'redis-gorm'.timeout=5000 -{code} diff --git a/grails-documentation-redis/src/docs/guide/2.1 Using Redis Standalone.gdoc b/grails-documentation-redis/src/docs/guide/2.1 Using Redis Standalone.gdoc deleted file mode 100644 index 6d47d492e..000000000 --- a/grails-documentation-redis/src/docs/guide/2.1 Using Redis Standalone.gdoc +++ /dev/null @@ -1,13 +0,0 @@ -If you plan to use Redis as your primary datastore then you need to uninstall the Hibernate plugin: - -{code} -grails uninstall-plugin hibernate -{code} - -With this done all domain classes in grails-app/domain will be persisted via Redis and not Hibernate. You can create a domain class by running the regular @create-domain-class@ command: - -{code} -grails create-domain-class Person -{code} - -The @Person@ domain class will automatically be a persistent entity that can be stored in Redis. \ No newline at end of file diff --git a/grails-documentation-redis/src/docs/guide/2.2 Combining Redis and Hibernate.gdoc b/grails-documentation-redis/src/docs/guide/2.2 Combining Redis and Hibernate.gdoc deleted file mode 100644 index 08065f6dc..000000000 --- a/grails-documentation-redis/src/docs/guide/2.2 Combining Redis and Hibernate.gdoc +++ /dev/null @@ -1,24 +0,0 @@ -If you have both the Hibernate and Redis plugins installed then by default all classes in the @grails-app/domain@ directory will be persisted by Hibernate and not Redis. If you want to persist a particular domain class with Redis then you must use the @mapWith@ property in the domain class: - -{code} -static mapWith = "redis" -{code} - -Alternatively you can persist Hibernate entities to Redis using the special @redis@ scope added to all Hibernate entities: - -{code} -def hibernatePerson = Person.get(1) - -hibernatePerson.redis.save() - -def redisPerson = Person.redis.get(1) -{code} - -This makes it really easy to use Redis as a cache for Hibernate entities and take advantage of some nice Redis features like randomization: - -{code} -def people = Person.list() -people.each { person -> person.redis.save() } - -def randomRedisPerson = Person.redis.random() -{code} \ No newline at end of file diff --git a/grails-documentation-redis/src/docs/guide/3. Object Mapping.gdoc b/grails-documentation-redis/src/docs/guide/3. Object Mapping.gdoc deleted file mode 100644 index 462cccf69..000000000 --- a/grails-documentation-redis/src/docs/guide/3. Object Mapping.gdoc +++ /dev/null @@ -1,32 +0,0 @@ -Object mapping works largely as described in the [documentation on GORM|http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html]. In general you can continue to model your associations using typical GORM notation such as @hasMany@, @belongsTo@ and so on. - -The one notable exception is that the [mapping block|http://grails.org/doc/latest/ref/Database%20Mapping/Usage.html] works differently to GORM for Hibernate. Most of the mapping configuration options available to GORM for Hibernate are specific to SQL databases and hence don't make sense to Redis. - -Here is an example of a domain class that can be persisted to Redis: - -{code} -class Person { - - String firstName - String lastName - - static constraints = { - firstName blank:false - lastName blank:false - } - - static mapping = { - lastName index:true - } -} -{code} - -Note that one key difference with GORM for Redis is that you *must* specify the properties you want to index before you can execute any query against the property. In the example above the @lastName@ property can be queried with a dynamic finder such as: - -{code} -Person.findByLastName("Simpson") -{code} - -However, the @firstName@ property cannot be queried and an error will be thrown if you attempt the equivalent dynamic finder for the @firstName@ property unless you specify @index:true@ for that property too. - -In other words, unlike SQL where every single property can be queried with Redis you must specify which properties can be queried up front. diff --git a/grails-documentation-redis/src/docs/guide/4. Querying.gdoc b/grails-documentation-redis/src/docs/guide/4. Querying.gdoc deleted file mode 100644 index f0330d2df..000000000 --- a/grails-documentation-redis/src/docs/guide/4. Querying.gdoc +++ /dev/null @@ -1,17 +0,0 @@ -As mentioned in the previous section you must specify the properties that can be queried with @index:true@ in your mapping block. Once a property can be queried upon then there are several ways to do it including: - -* [Dynamic Finders|http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html#5.4.1%20Dynamic%20Finders] -* [Criteria|http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html#5.4.2%20Criteria] -* [Named Queries|http://grails.org/doc/latest/ref/Domain%20Classes/namedQueries.html] - -These queries operate in largely the same way as they do with GORM for Hibernate. Note, however, that each criterion used in a query results in querying another index and although GORM for Redis caches query results you should be careful not to use too many criteria as it will impact query performance. - -A good way to debug your query performance is to go to your Redis distribution and type the following in a command or terminal window: - -{code} -$ ./redis-cli -$ MONITOR -{code} - -The @MONITOR@ command will allow you to monitor the commands that the currently running Redis server is receiving and responding to. Great for debugging! - diff --git a/grails-documentation-redis/src/docs/guide/4.1 Query Limitations.gdoc b/grails-documentation-redis/src/docs/guide/4.1 Query Limitations.gdoc deleted file mode 100644 index bea45b17b..000000000 --- a/grails-documentation-redis/src/docs/guide/4.1 Query Limitations.gdoc +++ /dev/null @@ -1,4 +0,0 @@ -There are some limitations with queries in Redis that you should be aware of, after all Redis is not a relational database. Below are some of the known limitations: - -* Sorting can only be done on dates and numbers and not String values / complex types -* Querying associations via nested criteria is not currently supported \ No newline at end of file diff --git a/grails-documentation-redis/src/docs/guide/5. Transactions.gdoc b/grails-documentation-redis/src/docs/guide/5. Transactions.gdoc deleted file mode 100644 index 3a275b254..000000000 --- a/grails-documentation-redis/src/docs/guide/5. Transactions.gdoc +++ /dev/null @@ -1,28 +0,0 @@ -Transactions in Redis (using MULTI/EXEC) operate differently to SQL transactions. In fact they are more a way to do bulk operations that can be discarded rather than full transactions (see the documentation on [MULTI/EXEC|http://code.google.com/p/redis/wiki/MultiExecCommand] for further information). - -One limitation of Redis' MULT/EXEC command is that even reads are batched up in the transaction. This trickles down to usage within GORM for Redis. So for example you can execute a transaction such as: - -{code} -Person.withTransaction { - new Person(firstName:"Bob").save() - new Person(firstName:"Fred").save() -} -{code} - -However, you cannot execute any queries (only write operations) in the middle of a transaction unless you do so with a separate connection such as: - -{code} -Person.withTransaction { - new Person(firstName:"Bob").save() - - def fred - Person.withNewSession { - fred = Person.findByFirstName("Fred") - } - if (!fred) { - new Person(firstName:"Fred").save() - } -} -{code} - -In other words all read operations have to happen in a separate session/connection which can be achieved with the @withNewSession@ method. diff --git a/grails-documentation-redis/src/docs/guide/6. Redis Specific Extensions.gdoc b/grails-documentation-redis/src/docs/guide/6. Redis Specific Extensions.gdoc deleted file mode 100644 index c6c279525..000000000 --- a/grails-documentation-redis/src/docs/guide/6. Redis Specific Extensions.gdoc +++ /dev/null @@ -1,14 +0,0 @@ -As well as all the regular capabilities offered by the GORM API there are a couple of additional GORM methods that take advantage of some key Redis features. The first one is the [random|domainClasses] method which will return a random instance of the domain class: - -{code} -def randomPerson = Person.random() -{code} - -Implementing a random function in a SQL database is typically quite hard to do in a performant way whilst something like Redis makes it easy. - -There is also a [pop|domainClasses] method that will return and remove a random domain instance in one step: - -{code} -def randomPerson = Person.pop() -{code} - diff --git a/grails-documentation-redis/src/docs/guide/7. The Low-level API.gdoc b/grails-documentation-redis/src/docs/guide/7. The Low-level API.gdoc deleted file mode 100644 index 74fa710fd..000000000 --- a/grails-documentation-redis/src/docs/guide/7. The Low-level API.gdoc +++ /dev/null @@ -1,68 +0,0 @@ -There is a lower-level API that provides access to the majority of commands from the [Redis Command Reference|http://code.google.com/p/redis/wiki/CommandReference]. The API is available via a Spring bean called @redis@ that you can inject into your own artifacts. - -For example in a controller: - -{code} -class MyController { - def redis - - def foo = { - redis.select(2) - redis.flushdb() - redis["message"] = "World" - - render "Hello ${redis["message"]}!" - } -} -{code} - -See the @org.grails.redis.util.RedisTemplate@ interface for the full list of available methods. - -The low-level API gives you an easy way to work with Redis lists, sets and hashes via the @list@, @set@ and @hash@ methods. For example, the @list@ method returns a normal Java @java.util.List@ that is backed onto a Redis list: - -{code} -def list = redis.list("my.list") -list << 1 << 2 << 3 -assert 3 == list.size() -assert 1 == list[0] as Integer -assert 2 == list[1] as Integer -assert 3 == list[2] as Integer -{code} - -whilst the @set@ method returns a Java @java.util.Set@: - -{code} -def set = redis.set("my.set") -set << 1 << 2 << 3 << 1 << 2 -assert 3 == set.size() -assert set.contains(1) -{code} - -And finally the @hash@ method returns a Java @java.util.Map@: - -{code} -def hash = redis.hash("my.hash") - -hash["foo"] = "bar" - -assert "bar" == hash["foo"] -{code} - -There is also an @entities@ helper method for obtaining domain classes from a Redis set or list. This is useful when you want to build your own indices: - -{code} -def theSimpsons = Person.findAllByLastName("Simpson") - -def list = redis.list("the.simpsons") -theSimpsons.each { list << it.id } - -{code} - -and later query them: - -{code} -def theSimpsons = redis.entities(Person, "the.simpsons") -theSimpsons.each { - println it.firstName -} -{code} diff --git a/grails-documentation-redis/src/docs/guide/8. Testing.gdoc b/grails-documentation-redis/src/docs/guide/8. Testing.gdoc deleted file mode 100644 index 52c2c8ecc..000000000 --- a/grails-documentation-redis/src/docs/guide/8. Testing.gdoc +++ /dev/null @@ -1,34 +0,0 @@ -The Redis plugin provides a Groovy mixin called [DatastoreUnitTestMixin|testing] for testing purposes. This mixin sets up a datastore implementation that operates against an in-memory @ConcurrentHashMap@. The datastore implementation that operates against an in-memory map is as complete as the one for Redis and provides support for: - -* Simple persistence methods -* Dynamic finders -* Criteria -* Named queries -* Inheritance - -You can easily write tests that use the mixin using Groovy's @Mixin@ annotation on any existing unit test: - -{code} -import grails.datastore.test.DatastoreUnitTestMixin - -@Mixin(DatastoreUnitTestMixin) -class PersonTests extends GroovyTestCase { - void testPersist() { - mockDomain(Person) - def s = new Simple(name:"Bob") - s.save() - - assert s.id != null - - s = Simple.get(s.id) - - assert s != null - } - - void tearDown() { - disconnect() - } -} -{code} - -You should call the @mockDomain()@ method to mock a domain instance and then the remainder of the API is the same. Note that you should call @disconnect()@ in @tearDown()@ otherwise your tests will share data. diff --git a/grails-documentation-redis/src/docs/ref/Beans/redis.gdoc b/grails-documentation-redis/src/docs/ref/Beans/redis.gdoc deleted file mode 100644 index 6c0edc21d..000000000 --- a/grails-documentation-redis/src/docs/ref/Beans/redis.gdoc +++ /dev/null @@ -1,23 +0,0 @@ -h1. redis - -h2. Purpose - -A Spring bean that provides access to the lower level Redis API - -h2. Examples - -{code} -def redis - -def foo = { - redis.select(2) - redis.flushdb() - redis["message"] = "World" - - render "Hello ${redis["message"]}!" -} -{code} - -h2. Description - -See the @org.grails.redis.util.RedisTemplate@ interface for the full list of available methods. diff --git a/grails-documentation-redis/src/docs/ref/Domain Classes/expire.gdoc b/grails-documentation-redis/src/docs/ref/Domain Classes/expire.gdoc deleted file mode 100644 index 5fb2f6f1e..000000000 --- a/grails-documentation-redis/src/docs/ref/Domain Classes/expire.gdoc +++ /dev/null @@ -1,24 +0,0 @@ -h1. expire - -h2. Purpose - -Expires a domain instance using the given time to live (TTL) in seconds - -h2. Examples - -Instance method: - -{code} -def person = Person.get(1) -person.expire(60) // expire after 60 seconds -{code} - -Static method: - -{code} -Person.expire(1, 60) // expire Person:1 after 60 seconds -{code} - -h2. Description - -Redis supports expiring of individual entries after a timeout (time to live) period. The @expire@ method allows you to expire an object persisted to Redis. diff --git a/grails-documentation-redis/src/docs/ref/Domain Classes/pop.gdoc b/grails-documentation-redis/src/docs/ref/Domain Classes/pop.gdoc deleted file mode 100644 index 8628a6d9d..000000000 --- a/grails-documentation-redis/src/docs/ref/Domain Classes/pop.gdoc +++ /dev/null @@ -1,15 +0,0 @@ -h1. pop - -h2. Purpose - -Returns and deletes random domain instance. - -h2. Examples - -{code} -def randomPerson = Person.pop() -{code} - -h2. Description - -Similar to the @random@ method but deletes the domain instance at the same time. diff --git a/grails-documentation-redis/src/docs/ref/Domain Classes/random.gdoc b/grails-documentation-redis/src/docs/ref/Domain Classes/random.gdoc deleted file mode 100644 index 3514ccd81..000000000 --- a/grails-documentation-redis/src/docs/ref/Domain Classes/random.gdoc +++ /dev/null @@ -1,15 +0,0 @@ -h1. random - -h2. Purpose - -Returns a random domain instance. - -h2. Examples - -{code} -def randomPerson = Person.random() -{code} - -h2. Description - -One of the major benifits of Redis is its great support for set operations including returning random set elements. This method takes advantage of that capability by returning a random instance of the corresponding domain class. diff --git a/grails-documentation-redis/src/docs/ref/Testing/DatastoreUnitTestMixin.gdoc b/grails-documentation-redis/src/docs/ref/Testing/DatastoreUnitTestMixin.gdoc deleted file mode 100644 index 4825f5d28..000000000 --- a/grails-documentation-redis/src/docs/ref/Testing/DatastoreUnitTestMixin.gdoc +++ /dev/null @@ -1,36 +0,0 @@ -h1. DatastoreUnitTestMixin - -h2. Purpose - -A mixin for setting up unit testing of datastores such as the Redis datastore. - -h2. Examples - -{code} -import grails.datastore.test.DatastoreUnitTestMixin - -@Mixin(DatastoreUnitTestMixin) -class PersonTests extends GroovyTestCase { - void testPersist() { - mockDomain(Person) - def s = new Simple(name:"Bob") - s.save() - - assert s.id != null - - s = Simple.get(s.id) - - assert s != null - } - - void tearDown() { - disconnect() - } -} -{code} - -h2. Description - -@DatastoreUnitTestMixin@ allows you to test datastore interactions by mocking the complete GORM API including simple persistence methods, dynamic finders, criteria queries and named queries. - -If you want to make sure that tests do not share data, add an implementation of @tearDown()@ (or the equivalent in your test framework) that calls the @disconnect()@ method. Also make sure to call the super class method if necessary! diff --git a/grails-documentation-rest-client/build.gradle b/grails-documentation-rest-client/build.gradle deleted file mode 100644 index 27d21832e..000000000 --- a/grails-documentation-rest-client/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -task assemble(dependsOn:docs) << { - group = "docs" -} \ No newline at end of file diff --git a/grails-documentation-rest-client/src/docs/doc.properties b/grails-documentation-rest-client/src/docs/doc.properties deleted file mode 100644 index 34a51bac3..000000000 --- a/grails-documentation-rest-client/src/docs/doc.properties +++ /dev/null @@ -1,3 +0,0 @@ -title=GORM REST Client -version=1.0.0.M1 -authors=Graeme Rocher \ No newline at end of file diff --git a/grails-documentation-rest-client/src/docs/guide/1. Introduction.gdoc b/grails-documentation-rest-client/src/docs/guide/1. Introduction.gdoc deleted file mode 100644 index 8a135e54c..000000000 --- a/grails-documentation-rest-client/src/docs/guide/1. Introduction.gdoc +++ /dev/null @@ -1 +0,0 @@ -The GORM REST Client plugin tries to provide a GORM-like API to interact with REST Web Services. Building on the REST features of Grails 2.3.x, this plugin works only with Grails 2.3.x and above. Note that in its current state the GORM REST Client plugin only implements basic CRUD operations and should be seen as convenience for easily converting between REST representations and a domain model rather than a full object mapping tool. \ No newline at end of file diff --git a/grails-documentation-rest-client/src/docs/guide/1.2 Release Notes.gdoc b/grails-documentation-rest-client/src/docs/guide/1.2 Release Notes.gdoc deleted file mode 100644 index 18eeab538..000000000 --- a/grails-documentation-rest-client/src/docs/guide/1.2 Release Notes.gdoc +++ /dev/null @@ -1,5 +0,0 @@ -Below are the details of the changes across releases: - -h4. 1.0 M1 - -* Initial milestone release diff --git a/grails-documentation-rest-client/src/docs/guide/2. Getting Started.gdoc b/grails-documentation-rest-client/src/docs/guide/2. Getting Started.gdoc deleted file mode 100644 index 6218afe7f..000000000 --- a/grails-documentation-rest-client/src/docs/guide/2. Getting Started.gdoc +++ /dev/null @@ -1,121 +0,0 @@ -To quickly get started with GORM for REST first you need a REST server. This is pretty simple with Grails 2.3.0. Simply follow these steps on the command line: - -{code} -$ grails create-app amazon -$ cd amazon -$ grails create-domain-class Book -$ vi grails-app/domain/amazon/Book.groovy -{code} - -Modify the @Book@ domain class to look like: - -{code} -import grails.rest.* - -@Resource(uri="/books") -class Book { - - String title - String author - int pages - - static constraints = { - title blank:false - author blank:false - } -} -{code} - -This will automatically expose the domain class as a REST service. You can start the application with: - -{code} -$ grails run-app -{code} - -To verify that is running try the following (Assumes a Unix system): - -{code} -$ curl -i http://localhost:8080/amazon/books -{code} - -You should get an XML response: - -{code} -HTTP/1.1 200 OK -Server: Apache-Coyote/1.1 -Content-Type: text/xml;charset=UTF-8 -Transfer-Encoding: chunked -Date: Tue, 10 Sep 2013 13:14:52 GMT - - -{code} - -You can obtain a JSON response with: - -{code} -$ curl -H "Accept:application/json" -i http://localhost:8080/amazon/books -{code} - -Now to create the client create a separate Grails application: - - -{code} -$ grails create-app amazon-client -$ cd amazon-client -$ grails create-domain-class Book -{code} - - -And configure GORM for REST as a dependency in @grails-app/conf/BuildConfig.groovy@: - -{code} -plugins { - // or whatever is the latest version - compile ':gorm-rest-client:1.0.0.M1' -} -{code} - -{note} -Note if you plan to remove the Hibernate plugin, then in 2.3.0 of Grails you also need to remove the 'database-migration' plugin -{note} - -Then open up the @grails-app/domain/amazon/client/Book.groovy@ domain class and modify it as follows: - -{code} -package amazon.client - -class Book { - String title - String author - int pages - - static constraints = { - title blank:false - author blank:false - } - static mappedWith = "restclient" - static mapping = { - url "http://localhost:8080/amazon/books" - } -} -{code} - -Now fire up the Grails console: - -{code} -$ grails console -{code} - -And try the following: - -{code} -def book = new Book(title:"The Stand", author:"Stephen King", pages:1200) -book.save(flush:true) - -Book.list().each { b -> - println b.title - println b.author -} -{code} - -Essentially GORM for REST will transparently issue the appropriate POST request to create a REST resource and the the appropriate GET request to retrieve REST resources. \ No newline at end of file diff --git a/grails-documentation-rest-client/src/docs/guide/3. Making REST Calls.gdoc b/grails-documentation-rest-client/src/docs/guide/3. Making REST Calls.gdoc deleted file mode 100644 index be15bca52..000000000 --- a/grails-documentation-rest-client/src/docs/guide/3. Making REST Calls.gdoc +++ /dev/null @@ -1,38 +0,0 @@ -Currently GORM for REST supports only basic CRUD operations. - -The following will issue a POST request to create a resource: - -{code} -def book = new Book(title:"The Stand", author:"Stephen King", pages:1200) -book.save(flush:true) -{code} - -The issue a GET request to retrieve the resource you can use the @get(id)@ method: - -{code} -def book = Book.get(1) -{code} - -To issue a GET request for all resources you can use the @list()@ method: - -{code} -Book.list() -Book.list(offset:10, max:20) // with pagination -{code} - -If you pass pagination argument as per the above then the @offset@ and @max@ parameters are sent as part of the request. - -To update a resource with a PUT request you can use the @save()@ method on an existing resource: - -{code} -def book = Book.get(1) -book.title = "The Shining" -book.save() -{code} - -Finally, to issue DELETE request to delete a resource simply call the @delete()@ method: - -{code} -def book = Book.get(1) -book.delete() -{code} \ No newline at end of file diff --git a/grails-documentation-rest-client/src/docs/guide/4. Making Async REST Calls.gdoc b/grails-documentation-rest-client/src/docs/guide/4. Making Async REST Calls.gdoc deleted file mode 100644 index cab1ccb5e..000000000 --- a/grails-documentation-rest-client/src/docs/guide/4. Making Async REST Calls.gdoc +++ /dev/null @@ -1,25 +0,0 @@ -By default GORM for REST makes all REST calls asynchronously, however it is advisable to configure a default timeout. This can be done per entity using: - -{code} -static mapping = { - readTimeout 2000 - connectTimeout 2000 -} -{code} - -However, you may want to take control of the asynchronous calls yourself. To do this you can disable internal Async processing: - -{code} -static mapping = { - async false -} -{code} - -And then simply use [Asynchronous GORM|http://grails.org/doc/2.3.x/guide/async.html#asyncGorm] to make the calls in a non-blocking fashion: - -{code} -Book.async.get(1).onComplete { Book book -> - // do stuff with the book -} -{code} - diff --git a/grails-documentation-rest-client/src/docs/guide/5. Configuration.gdoc b/grails-documentation-rest-client/src/docs/guide/5. Configuration.gdoc deleted file mode 100644 index d1612f1f1..000000000 --- a/grails-documentation-rest-client/src/docs/guide/5. Configuration.gdoc +++ /dev/null @@ -1,23 +0,0 @@ -The following configuration properties are available inside the @mapping@ block of each entity: - -* @httpRequestFactory@ - The [SimpleClientHttpRequestFactory|http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/http/client/SimpleClientHttpRequestFactory.html] to use to make REST calls -* @url@ - The full URL of the endpoint -* @uri@ - The URI of the endpoint relative to the configured base URL (Set using the @grails.gorm.restClient.baseUrl@ setting in Config.groovy) -* @contentType@ - The content type of the end point to pass to the Content-Type header when sending requests -* @connectTimeout@ - The timeout for connecting to the REST resource. Defaults to none. -* @readTimeout@ - The timeout for reading the REST resource. Defaults to none. -* @accept@ - The accept type of the end point to pass to the Accept header when sending requests -* @headers@ - A map of any additional headers to send -* @async@ - Whether to perform requests asynchronously or not (defaults to true) - -All of these can be configured by default for all domain classes using the @grails.gorm.restClient.default.mapping@ setting in @Config.groovy@. Example: - -{code} -grails.gorm.restClient.baseUrl = "http://mycompany/api" -grails.gorm.restClient.default.mapping = { - connectTimeout 2000 - readTimeout 2000 - accept "application/json" - -} -{code} \ No newline at end of file diff --git a/grails-documentation-rest-client/src/docs/guide/6. Testing.gdoc b/grails-documentation-rest-client/src/docs/guide/6. Testing.gdoc deleted file mode 100644 index 8164fa44d..000000000 --- a/grails-documentation-rest-client/src/docs/guide/6. Testing.gdoc +++ /dev/null @@ -1,12 +0,0 @@ -GORM for REST uses Spring's RestTemplate under the covers, so testing can be done with Spring's [MockRestServiceServer|http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/test/web/client/MockRestServiceServer.html] API. Example: - -{code} - RestTemplate rt = Book.getRestBuilder().restTemplate - final mockServer = MockRestServiceServer.createServer(rt) - mockServer.expect(requestTo("http://localhost:8080/book")) - .andExpect(method(HttpMethod.GET)) - .andExpect(header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON.toString())) - .andRespond(withSuccess('[{"id":1, "title":"The Stand", "pages":200}]', MediaType.APPLICATION_JSON)) - - List results = Book.list() -{code} \ No newline at end of file diff --git a/grails-documentation-riak/build.gradle b/grails-documentation-riak/build.gradle deleted file mode 100644 index 27d21832e..000000000 --- a/grails-documentation-riak/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -task assemble(dependsOn:docs) << { - group = "docs" -} \ No newline at end of file diff --git a/grails-documentation-riak/src/docs/doc.properties b/grails-documentation-riak/src/docs/doc.properties deleted file mode 100644 index 12e9ba8e0..000000000 --- a/grails-documentation-riak/src/docs/doc.properties +++ /dev/null @@ -1,3 +0,0 @@ -title=Riak GORM -version=1.0.0.M4 -authors=Jon Brisbin, Graeme Rocher \ No newline at end of file diff --git a/grails-documentation-riak/src/docs/guide/1. Introduction.gdoc b/grails-documentation-riak/src/docs/guide/1. Introduction.gdoc deleted file mode 100644 index 04d3ac5b5..000000000 --- a/grails-documentation-riak/src/docs/guide/1. Introduction.gdoc +++ /dev/null @@ -1,32 +0,0 @@ -Riak is an Internet-scale Key/Value datastore that stores arbitrary data based on Content-Type, has an [efficient HTTP REST API|https://wiki.basho.com/display/RIAK/REST+API], and supports queries and data filtering via [Map/Reduce operations|https://wiki.basho.com/display/RIAK/MapReduce] written in either Javascript or Erlang. - -This project aims to provide an object-mapping framework on top of Riak to ease common activities like: - -* Converting objects to/from JSON for storage in Riak -* Easy access to custom Map/Reduce queries -* Validating domain instances backed by the Riak datastore - -The following key features are supported by GORM for Riak: - -* Simple persistence methods -* Dynamic finders -* Criteria queries -* Named queries -* Inheritance -* Embedded types -* Query by example - -However, some features are not supported: - -* Pagination (yes Riak doesn't allow you to paginate records) -* Queries that compare properties -* Queries that operate on the size() of a collection association -* Join queries -* HQL queries -* Dirty checking methods -* Composite primary keys -* Many-to-many associations (these can be modelled with a mapping class) -* Any direct interaction with the Hibernate API -* Custom Hibernate user types - -There may be other limitations not mentioned here so in general it shouldn't be expected that an application based on GORM for Hibernate will "just work" without some tweaking involved. Having said that, the large majority of common GORM functionality is supported. diff --git a/grails-documentation-riak/src/docs/guide/2. Getting Started.gdoc b/grails-documentation-riak/src/docs/guide/2. Getting Started.gdoc deleted file mode 100644 index baa406636..000000000 --- a/grails-documentation-riak/src/docs/guide/2. Getting Started.gdoc +++ /dev/null @@ -1,40 +0,0 @@ -To get started with GORM for Riak, you need to install the plugin into a Grails application: - -{code} -grails install-plugin riak -{code} - -Now you need to install and configure a Riak server for your architecture. To install Riak, you have several options: - -* Use a pre-compiled binary downloaded from the official download page: [http://downloads.basho.com/riak/|http://downloads.basho.com/riak/] -* Install from a package manager like @apt@ or [Homebrew|http://mxcl.github.com/homebrew/] -* Install the source distribution - -Once installed, you can run a Riak server in a terminal and gain access to an Erlang shell by doing the following (assuming Riak is installed to @/opt/riak-0.13.0@): - -{code} -cd /opt/riak-0.13.0 -bin/riak console -{code} - -When run, you should see something like the following: - -{code} -Exec: /opt/riak-0.13.0/erts-5.8.1/bin/erlexec -boot /opt/riak-0.13.0/releases/0.13.0/riak -embedded -config /opt/riak-0.13.0/etc/app.config -args_file /opt/riak-0.13.0/etc/vm.args -- console -Root: /opt/riak-0.13.0 -Erlang R14B (erts-5.8.1) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:64] [hipe] [kernel-poll:true] -... -=INFO REPORT==== 13-Dec-2010::16:30:51 === -Spidermonkey VM (thread stack: 32MB, max heap: 12MB) host starting (<0.147.0>) -Eshell V5.8.1 (abort with ^G) -(riak\@127.0.0.1)1> -{code} - -The default port for Riak's REST interface is 8098. So the default URI built into the Riak GORM support will work. The default is @http://localhost:8098/riak/{bucket}/{key}@. - -If you need to configure the URLs for the @RiakTemplate@, do so by adding configuration elements to @grails-app/conf/Config.groovy@: - -{code} -grails.riak.defaultUri = "http://localhost:8098/riak/\{bucket\}/\{key\}" -grails.riak.mapReduceUri = "http://localhost:8098/mapred" -{code} diff --git a/grails-documentation-riak/src/docs/guide/3. Object Mapping.gdoc b/grails-documentation-riak/src/docs/guide/3. Object Mapping.gdoc deleted file mode 100644 index a15ca455f..000000000 --- a/grails-documentation-riak/src/docs/guide/3. Object Mapping.gdoc +++ /dev/null @@ -1,24 +0,0 @@ -Object mapping works largely as described in the [documentation on GORM|http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html]. In general you can continue to model your associations using typical GORM notation such as @hasMany@, @belongsTo@ and so on. - -Here is an example of a domain class that can be persisted to Riak: - -{code} -class Person { - - String firstName - String lastName - - static constraints = { - firstName blank:false - lastName blank:false - } -} -{code} - -Since Riak doesn't support the notion of saved indexes, there are no options to specify what columns to index for faster searches. The GORM support for Riak relies on Riak's Map/Reduce implementation for queries, criteria, dynamic finder methods, and so on. As such, searching for data in Riak using finder methods can be slower than on other NoSQL datastores given a very large dataset. Caveat emptor. - -That said, finder methods are fully supported in Riak for GORM: - -{code} -Person.findByLastName("Simpson") -{code} diff --git a/grails-documentation-riak/src/docs/guide/3.1 Dealing with Eventual Consistency.gdoc b/grails-documentation-riak/src/docs/guide/3.1 Dealing with Eventual Consistency.gdoc deleted file mode 100644 index efe8e91e0..000000000 --- a/grails-documentation-riak/src/docs/guide/3.1 Dealing with Eventual Consistency.gdoc +++ /dev/null @@ -1,11 +0,0 @@ -One of the important features of Riak is that, by default, Riak promises to be ["eventually consistent" rather than synchronously up-to-date|http://blog.basho.com/category/eventual-consistency/]. This means that when an update to data in Riak is issued, the update method might return before the data has been fully written to disk. This increases performance of writes but means operations that depend on just-inserted data being available (for queries, for example) need to be careful about when they are run. - -If you want a @save()@ call to be guaranteed to have persisted the object to disk before returning to your application, then you need to pass a QOS (Quality of Service) parameter to the entity's @save@ method. You use the same names for the parameters as you would if you were specifying them on an HTTP URL: @w@ for write, @dw@ for durable write, and @r@ for read. - -For example, to ensure that an object has been completely flushed to disk before returning, use the "durable write" parameter: - -{code} -def p = new Person(firstName: "Bob") -p.save([dw: "all"]) -{code} - diff --git a/grails-documentation-riak/src/docs/guide/4. Querying.gdoc b/grails-documentation-riak/src/docs/guide/4. Querying.gdoc deleted file mode 100644 index fc7cc122f..000000000 --- a/grails-documentation-riak/src/docs/guide/4. Querying.gdoc +++ /dev/null @@ -1,7 +0,0 @@ -The Riak GORM module provides several ways to query data that is stored in Riak: - -* [Dynamic Finders|http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html#5.4.1%20Dynamic%20Finders] -* [Criteria|http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html#5.4.2%20Criteria] -* [Named Queries|http://grails.org/doc/latest/ref/Domain%20Classes/namedQueries.html] - -These queries operate in largely the same way as they do with GORM for Hibernate. \ No newline at end of file diff --git a/grails-documentation-riak/src/docs/guide/5. Spring Data Support.gdoc b/grails-documentation-riak/src/docs/guide/5. Spring Data Support.gdoc deleted file mode 100644 index 22480a6dd..000000000 --- a/grails-documentation-riak/src/docs/guide/5. Spring Data Support.gdoc +++ /dev/null @@ -1,40 +0,0 @@ -The Riak support for GORM is actually built on top of the Riak support for [Spring Data|http://www.springsource.org/spring-data]. As such, the Riak plugin provides full access to a @org.springframework.data.keyvalue.riak.core.RiakTemplate@ or @org.springframework.data.keyvalue.riak.core.AsyncRiakTemplate@ object you can inject into your own components. The former is for synchronous access to Riak, the latter is for asynchronous access. - -For example, in a controller: - -{code} -class MyController { - def riakTemplate - - def foo = { - def notifs = riak.get("notifications", "myuser") - render "Notifications: \$notifs" - } -} -{code} - -Or, for asynchronous access: - -{code} -class MyController { - def asyncRiakTemplate - - def foo = { - def callback = [ - completed: { metadata, val -> - // Since this is run asynchronously, - // put the data somewhere else... - }, - failed: { err -> - log.error(err.message, err) - } - ] as AsyncKeyValueStoreOperation - riak.get("notifications", "myuser", callback) - - // The previous call doesn't block, so we continue on... - render "Notifications: \$notifs" - } -} -{code} - -See the Spring Data reference for more information on the methods available and on examples of using the @RiakTemplate@ in your own code. diff --git a/grails-documentation-riak/src/docs/guide/5.1 RiakBuilder Support.gdoc b/grails-documentation-riak/src/docs/guide/5.1 RiakBuilder Support.gdoc deleted file mode 100644 index ef4879217..000000000 --- a/grails-documentation-riak/src/docs/guide/5.1 RiakBuilder Support.gdoc +++ /dev/null @@ -1,21 +0,0 @@ -Besides direct access to the Java-language template objects, the Riak plugin for Grails exposes a Groovy Builder object call RiakBuilder for use in your controllers and services. The builder uses a declarative, DSL-style syntax for working with Riak. - -For example, to delete all entries in a bucket using the RiakBuilder DSL (which is a dynamic method the plugin adds to any controller or service class): - -{code} -riak { - test { - foreach { - completed { v, meta -> delete(key: meta.key) } - failed { it.printStackTrace() } - } - } -} -{code} - -* The top-level node should always be "riak". -* The next level is optional. In this case, it sets the default bucket name to "test", so it's not necessary to specify it on operations contained within this block. -* When an operation is complete, if a "completed" closure is defined, the builder will call that closure, passing the results of the operation as the first parameter and optionally passing the metadata associated with that entry as the second (this might be null, depending on the context in which the completed closure is called). If no parameters are defined, the result of the operation is still available as the implicit variable "it". -* To handle errors, a "failed" closure should be defined, which should accept the exception just generated (the exception is also available as "it"). - -See the Spring Data reference for more information on the methods available and on examples of using the @RiakBuilder@ in your own code. \ No newline at end of file diff --git a/grails-documentation-riak/src/docs/guide/6. Map Reduce Support.gdoc b/grails-documentation-riak/src/docs/guide/6. Map Reduce Support.gdoc deleted file mode 100644 index 5f3c7df46..000000000 --- a/grails-documentation-riak/src/docs/guide/6. Map Reduce Support.gdoc +++ /dev/null @@ -1,16 +0,0 @@ -Since Map/Reduce is such an integral part of working with the Riak datastore, GORM for Riak provides access to this functionality both through the Map/Reduce operations exposed on the @RiakTemplate@ and through a special static helper called "mapreduce". - -To execute a Map/Reduce against all instances of a particular entity, you can do the following: - -{code} -def result = Person.mapreduce.execute([ - map: [ - source: "function(v){ ...perform map operations... return [result]; }" - ], - reduce: [ - source: "function(v){ ...perform reduce operations... return [result]; }" - ] -]) -{code} - -This is an easy way to execute ad hoc queries in a way that is more optimized for your application than what the @Query@ implementation will generate if you use criteria projections or a finder method. \ No newline at end of file diff --git a/grails-documentation-riak/src/docs/guide/7. Testing.gdoc b/grails-documentation-riak/src/docs/guide/7. Testing.gdoc deleted file mode 100644 index e894bc041..000000000 --- a/grails-documentation-riak/src/docs/guide/7. Testing.gdoc +++ /dev/null @@ -1,34 +0,0 @@ -The Riak plugin provides a Groovy mixin called [DatastoreUnitTestMixin|testing] for testing purposes. This mixin sets up a datastore implementation that operates against an in-memory @ConcurrentHashMap@. The datastore implementation that operates against an in-memory map is as complete as the one for Riak and provides support for: - -* Simple persistence methods -* Dynamic finders -* Criteria -* Named queries -* Inheritance - -You can easily write tests that use the mixin using Groovy's @Mixin@ annotation on any existing unit test: - -{code} -import grails.datastore.test.DatastoreUnitTestMixin - -@Mixin(DatastoreUnitTestMixin) -class PersonTests extends GroovyTestCase { - void testPersist() { - mockDomain(Person) - def s = new Simple(name:"Bob") - s.save() - - assert s.id != null - - s = Simple.get(s.id) - - assert s != null - } - - void tearDown() { - disconnect() - } -} -{code} - -You should call the @mockDomain()@ method to mock a domain instance and then the remainder of the API is the same. Note that you should call @disconnect()@ in @tearDown()@ otherwise your tests will share data. diff --git a/grails-documentation-riak/src/docs/ref/Beans/asyncRiakTemplate.gdoc b/grails-documentation-riak/src/docs/ref/Beans/asyncRiakTemplate.gdoc deleted file mode 100644 index 941cd148a..000000000 --- a/grails-documentation-riak/src/docs/ref/Beans/asyncRiakTemplate.gdoc +++ /dev/null @@ -1,24 +0,0 @@ -h1. riakTemplate - -h2. Purpose - -A Spring bean that provides access to the Spring Data @AsyncRiakTemplate@ API. - -h2. Examples - -{code} -def riak - -def foo = { - def callback = [ - completed: { v, meta -> ...do something with result... }, - failed: { err -> ...do something with error... } - ] as AsyncKeyValueStoreOperation - def future = riak.get("notifications", "mykey", callback) - render "Notifications: ${future.get()}" -} -{code} - -h2. Description - -The @asyncRiakTemplate@ bean is a singleton instance of the asynchronous @AsyncRiakTemplate@. Check the Spring Data Key/Value documentation for more information on the available methods and detailed usage instructions. \ No newline at end of file diff --git a/grails-documentation-riak/src/docs/ref/Beans/riak.gdoc b/grails-documentation-riak/src/docs/ref/Beans/riak.gdoc deleted file mode 100644 index 63de28cdf..000000000 --- a/grails-documentation-riak/src/docs/ref/Beans/riak.gdoc +++ /dev/null @@ -1,20 +0,0 @@ -h1. riakTemplate - -h2. Purpose - -A Spring bean that provides access to the Spring Data @RiakTemplate@ API using a @RiakBuilder@ instance. - -h2. Examples - -{code} -def riak - -def foo = { - def notifs = riak.foreach(bucket: "notifications") - render "Notifications: \$notifs" -} -{code} - -h2. Description - -If you want to use the @RiakBuilder@ to access the datastore using a dot notation, then inject it using the @riak@ bean. diff --git a/grails-documentation-riak/src/docs/ref/Beans/riakTemplate.gdoc b/grails-documentation-riak/src/docs/ref/Beans/riakTemplate.gdoc deleted file mode 100644 index fa78b7b7b..000000000 --- a/grails-documentation-riak/src/docs/ref/Beans/riakTemplate.gdoc +++ /dev/null @@ -1,20 +0,0 @@ -h1. riakTemplate - -h2. Purpose - -A Spring bean that provides access to the Spring Data @RiakTemplate@ API. - -h2. Examples - -{code} -def riak - -def foo = { - def notifs = riak.getAsType("notifications", "mykey", List) - render "Notifications: \$notifs" -} -{code} - -h2. Description - -The @riakTemplate@ bean is a singleton instance of the synchronous @RiakTemplate@. Check the Spring Data Key/Value documentation for more information on the available methods and detailed usage instructions. diff --git a/grails-documentation-riak/src/docs/ref/Domain Classes/mapreduce.gdoc b/grails-documentation-riak/src/docs/ref/Domain Classes/mapreduce.gdoc deleted file mode 100644 index 8a80b4af3..000000000 --- a/grails-documentation-riak/src/docs/ref/Domain Classes/mapreduce.gdoc +++ /dev/null @@ -1,24 +0,0 @@ -h1. mapreduce - -h2. Purpose - -Provides ad hoc access to Riak's Map/Reduce functionality for a given entity. - -h2. Examples - -Static method: - -{code} -def result = Person.mapreduce.execute([ - map: [ - source: "function(v){ ...perform map operations... return [result]; }" - ], - reduce: [ - source: "function(v){ ...perform reduce operations... return [result]; }" - ] -]) -{code} - -h2. Description - -Allows application code to execute arbitrary Map/Reduce operations for writing custom queries, doing reduce calculations not implemented by criteria projections, or for low-level access to Map/Reduce built-ins. \ No newline at end of file diff --git a/grails-documentation-riak/src/docs/ref/Testing/DatastoreUnitTestMixin.gdoc b/grails-documentation-riak/src/docs/ref/Testing/DatastoreUnitTestMixin.gdoc deleted file mode 100644 index 00542216d..000000000 --- a/grails-documentation-riak/src/docs/ref/Testing/DatastoreUnitTestMixin.gdoc +++ /dev/null @@ -1,36 +0,0 @@ -h1. DatastoreUnitTestMixin - -h2. Purpose - -A mixin for setting up unit testing of datastores such as the Riak datastore. - -h2. Examples - -{code} -import grails.datastore.test.DatastoreUnitTestMixin - -@Mixin(DatastoreUnitTestMixin) -class PersonTests extends GroovyTestCase { - void testPersist() { - mockDomain(Person) - def s = new Simple(name:"Bob") - s.save() - - assert s.id != null - - s = Simple.get(s.id) - - assert s != null - } - - void tearDown() { - disconnect() - } -} -{code} - -h2. Description - -@DatastoreUnitTestMixin@ allows you to test datastore interactions by mocking the complete GORM API including simple persistence methods, dynamic finders, criteria queries and named queries. - -If you want to make sure that tests do not share data, add an implementation of @tearDown()@ (or the equivalent in your test framework) that calls the @disconnect()@ method. Also make sure to call the super class method if necessary! diff --git a/grails-documentation-simpledb/build.gradle b/grails-documentation-simpledb/build.gradle deleted file mode 100644 index 27d21832e..000000000 --- a/grails-documentation-simpledb/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -task assemble(dependsOn:docs) << { - group = "docs" -} \ No newline at end of file diff --git a/grails-documentation-simpledb/src/docs/doc.properties b/grails-documentation-simpledb/src/docs/doc.properties deleted file mode 100644 index b11116403..000000000 --- a/grails-documentation-simpledb/src/docs/doc.properties +++ /dev/null @@ -1,4 +0,0 @@ -title=GORM for AWS SimpleDB -version=0.3 -authors=Roman Stepanenko -footer=Official production and development support for plugin is available via OSMoss: http://www.osmoss.com/project/grails-gorm-simpledb \ No newline at end of file diff --git a/grails-documentation-simpledb/src/docs/guide/gettingStarted.gdoc b/grails-documentation-simpledb/src/docs/guide/gettingStarted.gdoc deleted file mode 100644 index 377e41bd2..000000000 --- a/grails-documentation-simpledb/src/docs/guide/gettingStarted.gdoc +++ /dev/null @@ -1,6 +0,0 @@ -To get started with GORM for SimpleDB you need to install the plugin into a Grails application: - -{code} -grails install-plugin simpledb -{code} - diff --git a/grails-documentation-simpledb/src/docs/guide/gettingStarted/configurationOptions.gdoc b/grails-documentation-simpledb/src/docs/guide/gettingStarted/configurationOptions.gdoc deleted file mode 100644 index 8432bc593..000000000 --- a/grails-documentation-simpledb/src/docs/guide/gettingStarted/configurationOptions.gdoc +++ /dev/null @@ -1,81 +0,0 @@ -h3. Configuration options for simpledb plugin. - -simpledb plugin supports the following configuration options: -{table} -*Name* | *Required* | *Description* -accessKey | Y | AWS access key value. IMPORTANT: *You have to properly guard this value. Do not keep it in version control system if anyone except authorized persons has access to your VCS* -secretKey | Y | AWS secret key value. IMPORTANT: *You have to properly guard this value. Do not keep it in version control system if anyone except authorized persons has access to your VCS* -domainNamePrefix | N | if this property is specified, the value will be prefixed to all AWS domain names. It is handy when the same AWS account is shared between more than one environment. -dbCreate | N | similar to GORM for hibernate. Currently supports *'drop'* (will drop the domains for domain classes at startup), *'create'* (will create domains for domain classes at startup if they do not exist), *'drop-create'* (at startup will ensure that all domains are present and are *empty* - do not use in PROD environment!) -disableDrop | N | boolean property used as an extra protection against accidentally dropping data by setting dbCreate flag to 'drop' or 'drop-create'. Typically, this property would be set to true in PROD configuration after initial release of the application. Since AWS SimpleDB does not provide backup, accidentally dropping PROD domains can have a devastating effect. If the value of this property is true, the plugin will throw an exception if dbCreate is 'drop' or 'create-drop'. -{table} - -To configure, provide the following in the Config.groovy or your custom MyApp.groovy config file: -{code} -grails { - simpledb { - accessKey = '...' - secretKey = '...' - domainNamePrefix = 'DEV_' //optional, used when the same AWS account is shared between more than one environment - dbCreate = 'drop-create' // optional, one of 'drop', 'create', 'drop-create' - } -} -{code} - -Per-environment configuration works as well. For example: -{code} -grails { - simpledb { - accessKey = '...' - secretKey = '...' - } -} - -environments { - production { - grails { - simpledb { - disableDrop = true //extra protection against accidental misconfiguration of the 'dbCreate' flag - domainNamePrefix = 'PROD_' //this setting is optional, used when the same AWS account is shared between more than one environment - dbCreate = 'create' // one of 'drop, 'create', 'drop-create' - } - } - } - development { - grails { - simpledb { - domainNamePrefix = 'DEV_' //this setting is optional, used when the same AWS account is shared between more than one environment - dbCreate = 'drop-create' // one of 'drop, 'create', 'drop-create' - } - } - } -} -{code} - -Or, if you use separate AWS accounts for PROD and dev: -{code} -environments { - production { - grails { - simpledb { - accessKey = '... production account ...' - secretKey = '... production account ...' - dbCreate = 'create' // one of 'drop, 'create', 'drop-create' - } - } - } - development { - grails { - simpledb { - accessKey = '... dev account ...' - secretKey = '... dev account ...' - domainNamePrefix = 'DEV_' //this setting is optional, used when the same AWS account is shared between more than one environment - dbCreate = 'drop-create' // one of 'drop, 'create', 'drop-create' - } - } - } -} -{code} - - - diff --git a/grails-documentation-simpledb/src/docs/guide/introduction.gdoc b/grails-documentation-simpledb/src/docs/guide/introduction.gdoc deleted file mode 100644 index 707a65c49..000000000 --- a/grails-documentation-simpledb/src/docs/guide/introduction.gdoc +++ /dev/null @@ -1,21 +0,0 @@ -SimpleDB is a web service providing structured data storage in the cloud and backed by clusters -of Amazon-managed database servers. - -The simpledb plugin aims to provide an object-mapping layer on top of SimpleDB to ease common activities such as: - -* Marshalling from SimpleDB to Groovy/Java types and back again -* Support for GORM dynamic finders, criteria and named queries -* Session-managed transactions -* Validating domain instances backed by the SimpleDB datastore - -For example, this is all that is needed to persist a domain class in SimpleDB: - -{code} -class Book { - String id - String title - int pages - - static mapWith = "simpledb" -} -{code} diff --git a/grails-documentation-simpledb/src/docs/guide/introduction/currentFeatureSet.gdoc b/grails-documentation-simpledb/src/docs/guide/introduction/currentFeatureSet.gdoc deleted file mode 100644 index 4d8d75e98..000000000 --- a/grails-documentation-simpledb/src/docs/guide/introduction/currentFeatureSet.gdoc +++ /dev/null @@ -1,49 +0,0 @@ -This implementation tries to be as compatible as possible with GORM for Hibernate. -In general you can refer to the [GORM documentation|http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html] -for usage information. - -The following key features are supported by the current version simpledb plugin: - -* Simple persistence methods -* Dynamic finders -* Criteria queries -* Named queries -* Inheritance of domain classes (parent properties are stored in the child) -* Query by example -* Customizable AWS SimpleDB domain name per domain object -* Customizable AWS SimpleDB attribute name per attribute in domain object -* Customizable (optional) prefix for all AWS SimpleDB domain - useful when same AWS account is used for more than one environment (DEV and QA) -* hilo numeric id generator to use as alternative to default UUID -* Enum fields are supported -* Sorting and lexicographical comparison -friendly persistence of the following data types (including negative values for numeric types): -** byte -** short -** int -** long -** Date - -The current version of simpledb plugin has the following limitations: - -* Does not support Embedded types -* Does not support HQL queries -* Does not support Dirty checking methods -* Does not support Composite primary keys -* Does not support Many-to-many associations (these can be modelled with a mapping class) -* Does not support Any direct interaction with the Hibernate API -* Does not support Custom Hibernate user types -* Maximum size of String attribute or toString representation is 1024 bytes (will be solved in the next version) -* Sorting and lexicographical comparison -friendly persistence is not implemented for the following data types: -** float -** double -** BigDecimal -** BigInteger - -There may be other limitations not mentioned here so in general it shouldn't be -expected that an application based on GORM for Hibernate will work without some tweaking involved. -Furthermore, migration from SQL to NoSQL storage with eventual consistency (such as SimpleDB) -will require a re-design of the application -at the fundamental level (see 'eventual consistency' in the next chapter). -Having said that, the large majority of common GORM functionality is supported, and this simpledb plugin is a good option -(in author's eyes) for a from-scratch rapid project development. In this scenario AWS SimpleDB allows developer to -focus purely on the grails application without setting up and managing a dev/production cluster of database server instances. - diff --git a/grails-documentation-simpledb/src/docs/guide/introduction/simpleDBSpecifics.gdoc b/grails-documentation-simpledb/src/docs/guide/introduction/simpleDBSpecifics.gdoc deleted file mode 100644 index 313fc8a3f..000000000 --- a/grails-documentation-simpledb/src/docs/guide/introduction/simpleDBSpecifics.gdoc +++ /dev/null @@ -1,104 +0,0 @@ -AWS SimpleDB imposes several critical restrictions. - -h3. Eventual consistency model - -SimpleDB is based on the premise of eventual consistency model. -With eventual consistency, when you submit an update to SimpleDB, the database server handling your -request will forward the update to the other database servers where that domain -is replicated. The full update of all replicas does not happen before your update -request returns. The replication continues in the background while other requests are handled. -In other words, -if you update an object and do a query right after -updating it, you might get an old value back. There are ways to force strong consistency behavior but they go against the -whole premise of choosing SimpleDB in the first place - SimpleDB is best used by applications able to deal with -eventual consistency and benefit from the ability to remain available in the midst of a failure. Future -versions of the plugin might add support for strong consistency though. - -The best way to fight eventual consistency in the application is *not* to assume that the information is -available right after create/update/delete and store the objects you just modified or created in the cache. Generally, -information becomes visible within a couple of seconds, however it is a really bad idea to try to -implement artificial delay in the application layer because when AWS experiences some problems the -eventually consistency window might be -drastically increased. Design for failure and you will get fewer surprises when they happen. - -h3. Everything is a String -In AWS SimpleDB the only supported datatype is String, furthermore queries using LIKE keyword -string are compared in a _case-sensitive_ approach. - -The simpledb plugin automatically takes care of conversion to and from String for main data types. It must be noted -that proper implementation of the back-end of persistence layer must not only provide conversion to and from String -but provide conversion to and from String in format able to support comparison of resulting strings lexicographically (at least for -datatypes on which comparison is likely to be used). -Because everything is a string, -comparing naive toString representation of numbers will not work (89 is lexicographically greater than 321). - -Current implementation provides sorting and lexicographical comparison -friendly persistence of -the following data types (including negative values for numeric types): -* byte -* short -* int -* long -* Date - -The algorithm used to save numeric types is as follows (illustrated on the Byte example): -the goal is to move all negatives into the positives realms so that we can -compare strings lexicographically and it should be accurate for any mix of positives and negatives. - -Byte is -128..127. Let's say if the value is negative we shift it by adding 128 and pad with zeroes into 4 digits. -This way we can cover all negatives and turn them into positives. -* -128 -> 0000 -* -127 -> 0001 -* . . . -* -1 -> 0127 (this is the maximum a Byte can hold) - -so now we need to take care of how to convert remaining range of 0..127 values. -Lets say that for those values which are initially positive we just do toString and prepend them with '1' and pad -with zeroes into 4 digits. -* 0 -> 1000 -* 1 -> 1001 -* . . . -* 126 -> 1126 -* 127 -> 1127 - -With this logic initially positive values when converted will be greater than -converted negatives and yet conversion back/forth is faster than dealing with BigInteger (quick -note why BigIntegers are mentioned here. For byte, short, and int we can always step into 'next' storage bucket -when shifting negatives into positives: for example if when dealing with bytes we say that result value is of type -@short@ we can simply add the same 128 to *all* values byte values. -Unfortunately when we get to longs (which are used a lot, for example for versions), -there is no 'next' bucket to hold sum of two longs, and the only choice would be to deal with BigIntegers, -which is very slow. Also, it would lead to inconsistent representation of numbers among all numerics - one algorithm -for @byte@/@short@/@int@ and another for @long@) - -A helpful side effect is that initially positive values when converted would look pretty much the same -in the converted format (with leading 1), which is handy when looking at raw DB values. - -(Decoding is simple - we look at the first char to decide how to proceed because we know exactly how we got it) - -The short summary is that for this class - -{code} -class Book { - String id - String title - int pages - - static mapWith = "simpledb" -} -{code} - -You can fire standard dynamic finders and not worry about SimpleDB specifics. -{code} -Book.findAllByPagesGreaterThan(123) -{code} - -_In the current version, for numeric data types other than those listed above, dynamic finders with comparison will not produce correct results and should not be used._ - -h3. Transactions -AWS SimpleDB doesn't support explicit transactional boundaries or isolation levels. There is no notion of -a commit or a rollback. There is some implicit support for atomic writes, but it only applies within the -scope of each individual item being written. - -However, GORM for SimpleDB does batch up inserts -and updates until the session is flushed. This makes it possible to support some rollback options. See more details -in 'Transactions' chapter diff --git a/grails-documentation-simpledb/src/docs/guide/mapping.gdoc b/grails-documentation-simpledb/src/docs/guide/mapping.gdoc deleted file mode 100644 index 2d8da4d7a..000000000 --- a/grails-documentation-simpledb/src/docs/guide/mapping.gdoc +++ /dev/null @@ -1,83 +0,0 @@ -h3. Mapping to AWS Domains - -The way GORM for SimpleDB works is to map each domain class to a AWS SimpleDB domain. -For example, given a domain class such as: - -{code} -class Person { - String id - String firstName - String lastName - static hasMany = [pets:Pet] - - static mapWith = "simpledb" -} -{code} - -The plugin will map @Person@ class to a SimpleDB domain called "Person". -By default the domain name will be the class name, however it can be explicitly specified: - -{code} -class Person { - String id - String firstName - String lastName - static hasMany = [pets:Pet] - - static mapWith = "simpledb" - static mapping = { - domain 'PEOPLE' - } -} -{code} - -In this case @Person@ class will be mapped to 'PEOPLE' SimpleDB domain. - -Please note: _if you specified a domain name prefix in the configuration, all domain names will be prefixed_. For example, if you specified -{code} -grails { - simpledb { - accessKey = '...' - secretKey = '...' - domainNamePrefix = 'DEV_' //optional, used when the same AWS account is shared between more than one environment - } -} -{code} -then resulting domain name will be DEV_Person for first example and DEV_PEOPLE for second example. - -h3. Mapping to AWS Attributes - -By default, each java property will be mapped as an identically named AWS SimpleDB attribute. -For example, given a domain class such as: - -{code} -class Person { - String id - String firstName - String lastName - - static mapWith = "simpledb" -} -{code} - -will result in the following attribute names in 'Person' domain: -* firstName -* lastName - -@id@ field is always mapped to @itemName()@ for the record representing this domain class instance. - -It is possible to specify custom AWS attribute names for each java attribute: - -{code} -class Person { - String id - String firstName - String lastName - - static mapWith = "simpledb" - static mapping = { - firstName key:'FIRST_NAME' - lastName key:'LAST_NAME' - } -} -{code} diff --git a/grails-documentation-simpledb/src/docs/guide/mapping/automaticIndexing.gdoc b/grails-documentation-simpledb/src/docs/guide/mapping/automaticIndexing.gdoc deleted file mode 100644 index 9f95a8c42..000000000 --- a/grails-documentation-simpledb/src/docs/guide/mapping/automaticIndexing.gdoc +++ /dev/null @@ -1,11 +0,0 @@ -SimpleDB automatically creates indices for all attributes, thus there is no need to explicitly declare indexing in the mapping: - -{code} -class Person { - String id - String firstName //automatically indexed - String lastName //automatically indexed - - static mapWith = "simpledb" -} -{code} diff --git a/grails-documentation-simpledb/src/docs/guide/mapping/identityGeneration.gdoc b/grails-documentation-simpledb/src/docs/guide/mapping/identityGeneration.gdoc deleted file mode 100644 index 25f49a8e9..000000000 --- a/grails-documentation-simpledb/src/docs/guide/mapping/identityGeneration.gdoc +++ /dev/null @@ -1,29 +0,0 @@ -The plugin works only with String identifiers. Assignment and generation of ids is done automatically, however the String -id field must be currently explicitly declared in the domain class: - -{code} -class Person { - String id - String firstName - String lastName - - static mapWith = "simpledb" -} -{code} - -By default, generated ids are generated with @java.lang.UUID@. It is also possible to use hilo numeric value generator -(please note that the id field must still be declared as String): -{code} -class Person { - String id - String firstName - String lastName - - static mapWith = "simpledb" - - static mapping = { - id_generator type: 'hilo', maxLo: 500 - } -} -{code} - diff --git a/grails-documentation-simpledb/src/docs/guide/releaseNotes.gdoc b/grails-documentation-simpledb/src/docs/guide/releaseNotes.gdoc deleted file mode 100644 index 56c3fe6eb..000000000 --- a/grails-documentation-simpledb/src/docs/guide/releaseNotes.gdoc +++ /dev/null @@ -1,28 +0,0 @@ -Below are the details of the changes across releases: - -h4. Version 05. -* Upgraded to latest AWS version 1.3.23 - -h4. Version 0.4 -* Upgraded to latest AWS version -* Minor AWS internal improvements -* bugfix: for already existing object with non-null value of the property, setting that property to null was NOT propagating null to AWS, leaving AWS with the previous value - -h4. Version 0.3 -* Implemented hilo numeric id generator to use as alternative to default UUID -* Enum fields are supported -* Implemented automatic retry of load/save operations when AWS rejects request with 'ServiceUnavailable' error code -* Implemented behind-the-scenes working with nextToken when request takes more than 5 seconds or more than 2500 records returned - -h4. Version 0.1 - -Initial implementation of the SimpleDB support with -* Dynamic finders -* Criteria queries -* Named queries -* Lexicographical comparison -friendly persistence of the following data types (including negative values): -** byte -** short -** int -** long -** Date diff --git a/grails-documentation-simpledb/src/docs/guide/toc.yml b/grails-documentation-simpledb/src/docs/guide/toc.yml deleted file mode 100644 index 994e02f10..000000000 --- a/grails-documentation-simpledb/src/docs/guide/toc.yml +++ /dev/null @@ -1,13 +0,0 @@ -introduction: - title: Introduction - currentFeatureSet: Current Feature Set - simpleDBSpecifics: SimpleDB Specifics -gettingStarted: - title: Getting Started - configurationOptions: Configuration Options -mapping: - title: Mapping Domain Classes to SimpleDB - identityGeneration: IdentityGeneration - automaticIndexing: Automatic Indexing -transactions: Transactions -releaseNotes: Release Notes \ No newline at end of file diff --git a/grails-documentation-simpledb/src/docs/guide/transactions.gdoc b/grails-documentation-simpledb/src/docs/guide/transactions.gdoc deleted file mode 100644 index 0267a5153..000000000 --- a/grails-documentation-simpledb/src/docs/guide/transactions.gdoc +++ /dev/null @@ -1,29 +0,0 @@ -AWS SimpleDB doesn't support explicit transactional boundaries or isolation levels. There is no notion of -a commit or a rollback. There is some implicit support for atomic writes, but it only applies within the -scope of each individual item being written. - -However, simpledb plugin does batch up inserts -and updates until the session is flushed. This makes it possible to support some rollback options. - -You can use either transactional services or the static @withTransaction@ method. To mark a service as using the SimpleDB transaction manager, use the static @transactional@ property with the value @'simpledb'@: - -{code} -static transactional = 'simpledb' -{code} - -Alternately you can do ad-hoc transactions using the @withTransaction@ method: - -{code} -Person.withTransaction { status -> - new Person(firstName: "Bob").save() - throw new RuntimeException("bad") - new Person(firstName: "Fred").save() -} -{code} - -For example in this case neither @Person@ object will be persisted to the database, -because underneath the surface a persistence session is being used to batch up both insert -operations into a single insert. When the exception is thrown neither insert is ever -executed, hence we allow for some transactional semantics. - - diff --git a/grails-plugins/dynamodb/DynamodbGrailsPlugin.groovy b/grails-plugins/dynamodb/DynamodbGrailsPlugin.groovy deleted file mode 100644 index 9dbd49de0..000000000 --- a/grails-plugins/dynamodb/DynamodbGrailsPlugin.groovy +++ /dev/null @@ -1,63 +0,0 @@ -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty - -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBTableResolver -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBTableResolverFactory -import org.grails.datastore.mapping.dynamodb.engine.DynamoDBAssociationInfo -import org.grails.datastore.mapping.dynamodb.util.DynamoDBTemplate -import org.grails.datastore.mapping.dynamodb.util.DynamoDBConst -import org.grails.datastore.gorm.dynamodb.plugin.support.DynamoDBSpringConfigurer -import org.grails.datastore.gorm.dynamodb.plugin.support.DynamoDBMethodsConfigurer -import org.grails.datastore.gorm.dynamodb.plugin.support.DynamoDBOnChangeHandler -import org.grails.datastore.gorm.dynamodb.plugin.support.DynamoDBApplicationContextConfigurer - -class DynamodbGrailsPlugin { - def license = "Apache 2.0 License" - def scm = [ url: "https://github.com/SpringSource/grails-data-mapping" ] - def developers = [ - [ name: "Roman Stepanenko", email: "rs.opensource@gmail.com" ] ] - def version = "0.1.1" - def grailsVersion = "1.3.5 > *" - def observe = ['services', 'domainClass'] - def loadAfter = ['domainClass', 'hibernate', 'services', 'cloudFoundry'] - def dependsOn = [:] - def pluginExcludes = [ - "grails-app/views/error.gsp" - ] - - def author = "Roman Stepanenko" - def authorEmail = "rs.opensource@gmail.com" - def title = "DynamoDB GORM" - def description = 'A plugin that integrates the AWS DynamoDB datastore into Grails, providing a GORM API onto it' - - // URL to the plugin's documentation - def documentation = "http://grails.org/plugin/dynamodb" - def issueManagement = [system: "JIRA", url: "http://jira.grails.org/browse/GPDYNAMODB"] - - def doWithSpring = new DynamoDBSpringConfigurer().getConfiguration() - - def doWithDynamicMethods = { ctx -> - println 'dynamodb plugin: '+version - def datastore = ctx.dynamodbDatastore - def transactionManager = ctx.dynamodbTransactionManager - def methodsConfigurer = new DynamoDBMethodsConfigurer(datastore, transactionManager) - methodsConfigurer.hasExistingDatastore = manager.hasGrailsPlugin("hibernate") - def foe = application?.config?.grails?.gorm?.failOnError - methodsConfigurer.failOnError = foe instanceof Boolean ? foe : false - - methodsConfigurer.configure() - } - - def doWithApplicationContext = { ctx -> - new DynamoDBApplicationContextConfigurer().configure(ctx) - } - - - def onChange = { event -> - if(event.ctx) { - new DynamoDBOnChangeHandler(event.ctx.dynamodbDatastore, event.ctx.dynamodbTransactionManager).onChange(delegate, event) - } - } - -} diff --git a/grails-plugins/dynamodb/application.properties b/grails-plugins/dynamodb/application.properties deleted file mode 100644 index b72cdf4f9..000000000 --- a/grails-plugins/dynamodb/application.properties +++ /dev/null @@ -1,5 +0,0 @@ -#Grails Metadata file -#Thu Apr 19 09:37:42 EDT 2012 -app.grails.version=2.0.3 -app.name=dynamodb -plugins.release=2.0.0 diff --git a/grails-plugins/dynamodb/grails-app/conf/BuildConfig.groovy b/grails-plugins/dynamodb/grails-app/conf/BuildConfig.groovy deleted file mode 100644 index 5e831e12e..000000000 --- a/grails-plugins/dynamodb/grails-app/conf/BuildConfig.groovy +++ /dev/null @@ -1,49 +0,0 @@ -grails.project.class.dir = "target/classes" -grails.project.test.class.dir = "target/test-classes" -grails.project.test.reports.dir = "target/test-reports" - -grails.project.dependency.resolution = { - - inherits "global" - - log "warn" - - String dynamodbVersion = "0.1.1" - //for local development and testing of the plugin: - // 1) change version in grails-data-mapping/build.gradle to an appropriate snapshot - // 2) grails-data-mapping/gradle install - // 3) specify the same snapshot version here in the line below after the comments - // 4) in your grails app BuildConfig: grails.plugin.location.'dynamodb' = "C:/Source/grails-data-mapping/grails-plugins/dynamodb" - // 5) in your grails app BuildConfig: enable mavenLocal() in repositories AND put it first in the list of repos - - String datastoreVersion = "1.0.0.RELEASE" - - repositories { - mavenLocal() - grailsCentral() - mavenRepo "http://repo.grails.org/grails/core" - } - - dependencies { - - def excludes = { - transitive = false - } - compile("org.grails:grails-datastore-gorm-dynamodb:$dynamodbVersion", - "org.grails:grails-datastore-gorm-plugin-support:$datastoreVersion", - "org.grails:grails-datastore-gorm:$datastoreVersion", - "org.grails:grails-datastore-core:$datastoreVersion", - "org.grails:grails-datastore-dynamodb:$dynamodbVersion", - "org.grails:grails-datastore-web:$datastoreVersion") { - transitive = false - } - - runtime("stax:stax:1.2.0", excludes) - runtime('com.amazonaws:aws-java-sdk:1.3.3') - - test("org.grails:grails-datastore-gorm-test:$datastoreVersion", - "org.grails:grails-datastore-simple:$datastoreVersion") { - transitive = false - } - } -} diff --git a/grails-plugins/dynamodb/grails-app/conf/Config.groovy b/grails-plugins/dynamodb/grails-app/conf/Config.groovy deleted file mode 100644 index d53923251..000000000 --- a/grails-plugins/dynamodb/grails-app/conf/Config.groovy +++ /dev/null @@ -1,26 +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' -} -grails.views.default.codec="none" // none, html, base64 -grails.views.gsp.encoding="UTF-8" diff --git a/grails-plugins/dynamodb/grails-app/conf/DataSource.groovy b/grails-plugins/dynamodb/grails-app/conf/DataSource.groovy deleted file mode 100644 index 91143e70f..000000000 --- a/grails-plugins/dynamodb/grails-app/conf/DataSource.groovy +++ /dev/null @@ -1,32 +0,0 @@ -dataSource { - pooled = true - driverClassName = "org.hsqldb.jdbcDriver" - 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:hsqldb:mem:devDB" - } - } - test { - dataSource { - dbCreate = "update" - url = "jdbc:hsqldb:mem:testDb" - } - } - production { - dataSource { - dbCreate = "update" - url = "jdbc:hsqldb:file:prodDb;shutdown=true" - } - } -} diff --git a/grails-plugins/dynamodb/grails-app/i18n/messages.properties b/grails-plugins/dynamodb/grails-app/i18n/messages.properties deleted file mode 100644 index e69de29bb..000000000 diff --git a/grails-plugins/dynamodb/scripts/_Install.groovy b/grails-plugins/dynamodb/scripts/_Install.groovy deleted file mode 100644 index a21216087..000000000 --- a/grails-plugins/dynamodb/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/dynamodb/scripts/_Uninstall.groovy b/grails-plugins/dynamodb/scripts/_Uninstall.groovy deleted file mode 100644 index 7c5316914..000000000 --- a/grails-plugins/dynamodb/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/dynamodb/scripts/_Upgrade.groovy b/grails-plugins/dynamodb/scripts/_Upgrade.groovy deleted file mode 100644 index 6a1a4c925..000000000 --- a/grails-plugins/dynamodb/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/dynamodb/web-app/WEB-INF/applicationContext.xml b/grails-plugins/dynamodb/web-app/WEB-INF/applicationContext.xml deleted file mode 100644 index 69fbef3f7..000000000 --- a/grails-plugins/dynamodb/web-app/WEB-INF/applicationContext.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - Grails application factory bean - - - - - - A bean that manages Grails plugins - - - - - - - - - - - - - - - - utf-8 - - - \ No newline at end of file diff --git a/grails-plugins/dynamodb/web-app/WEB-INF/sitemesh.xml b/grails-plugins/dynamodb/web-app/WEB-INF/sitemesh.xml deleted file mode 100644 index 72399ceca..000000000 --- a/grails-plugins/dynamodb/web-app/WEB-INF/sitemesh.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/grails-plugins/dynamodb/web-app/WEB-INF/tld/c.tld b/grails-plugins/dynamodb/web-app/WEB-INF/tld/c.tld deleted file mode 100644 index 5e18236fe..000000000 --- a/grails-plugins/dynamodb/web-app/WEB-INF/tld/c.tld +++ /dev/null @@ -1,572 +0,0 @@ - - - - - JSTL 1.2 core library - JSTL core - 1.2 - c - http://java.sun.com/jsp/jstl/core - - - - Provides core validation features for JSTL tags. - - - org.apache.taglibs.standard.tlv.JstlCoreTLV - - - - - - Catches any Throwable that occurs in its body and optionally - exposes it. - - catch - org.apache.taglibs.standard.tag.common.core.CatchTag - JSP - - -Name of the exported scoped variable for the -exception thrown from a nested action. The type of the -scoped variable is the type of the exception thrown. - - var - false - false - - - - - - Simple conditional tag that establishes a context for - mutually exclusive conditional operations, marked by - <when> and <otherwise> - - choose - org.apache.taglibs.standard.tag.common.core.ChooseTag - JSP - - - - - Simple conditional tag, which evalutes its body if the - supplied condition is true and optionally exposes a Boolean - scripting variable representing the evaluation of this condition - - if - org.apache.taglibs.standard.tag.rt.core.IfTag - JSP - - -The test condition that determines whether or -not the body content should be processed. - - test - true - true - boolean - - - -Name of the exported scoped variable for the -resulting value of the test condition. The type -of the scoped variable is Boolean. - - var - false - false - - - -Scope for var. - - scope - false - false - - - - - - Retrieves an absolute or relative URL and exposes its contents - to either the page, a String in 'var', or a Reader in 'varReader'. - - import - org.apache.taglibs.standard.tag.rt.core.ImportTag - org.apache.taglibs.standard.tei.ImportTEI - JSP - - -The URL of the resource to import. - - url - true - true - - - -Name of the exported scoped variable for the -resource's content. The type of the scoped -variable is String. - - var - false - false - - - -Scope for var. - - scope - false - false - - - -Name of the exported scoped variable for the -resource's content. The type of the scoped -variable is Reader. - - varReader - false - false - - - -Name of the context when accessing a relative -URL resource that belongs to a foreign -context. - - context - false - true - - - -Character encoding of the content at the input -resource. - - charEncoding - false - true - - - - - - The basic iteration tag, accepting many different - collection types and supporting subsetting and other - functionality - - forEach - org.apache.taglibs.standard.tag.rt.core.ForEachTag - org.apache.taglibs.standard.tei.ForEachTEI - JSP - - -Collection of items to iterate over. - - items - false - true - java.lang.Object - - java.lang.Object - - - - -If items specified: -Iteration begins at the item located at the -specified index. First item of the collection has -index 0. -If items not specified: -Iteration begins with index set at the value -specified. - - begin - false - true - int - - - -If items specified: -Iteration ends at the item located at the -specified index (inclusive). -If items not specified: -Iteration ends when index reaches the value -specified. - - end - false - true - int - - - -Iteration will only process every step items of -the collection, starting with the first one. - - step - false - true - int - - - -Name of the exported scoped variable for the -current item of the iteration. This scoped -variable has nested visibility. Its type depends -on the object of the underlying collection. - - var - false - false - - - -Name of the exported scoped variable for the -status of the iteration. Object exported is of type -javax.servlet.jsp.jstl.core.LoopTagStatus. This scoped variable has nested -visibility. - - varStatus - false - false - - - - - - Iterates over tokens, separated by the supplied delimeters - - forTokens - org.apache.taglibs.standard.tag.rt.core.ForTokensTag - JSP - - -String of tokens to iterate over. - - items - true - true - java.lang.String - - java.lang.String - - - - -The set of delimiters (the characters that -separate the tokens in the string). - - delims - true - true - java.lang.String - - - -Iteration begins at the token located at the -specified index. First token has index 0. - - begin - false - true - int - - - -Iteration ends at the token located at the -specified index (inclusive). - - end - false - true - int - - - -Iteration will only process every step tokens -of the string, starting with the first one. - - step - false - true - int - - - -Name of the exported scoped variable for the -current item of the iteration. This scoped -variable has nested visibility. - - var - false - false - - - -Name of the exported scoped variable for the -status of the iteration. Object exported is of -type -javax.servlet.jsp.jstl.core.LoopTag -Status. This scoped variable has nested -visibility. - - varStatus - false - false - - - - - - Like <%= ... >, but for expressions. - - out - org.apache.taglibs.standard.tag.rt.core.OutTag - JSP - - -Expression to be evaluated. - - value - true - true - - - -Default value if the resulting value is null. - - default - false - true - - - -Determines whether characters <,>,&,'," in the -resulting string should be converted to their -corresponding character entity codes. Default value is -true. - - escapeXml - false - true - - - - - - - Subtag of <choose> that follows <when> tags - and runs only if all of the prior conditions evaluated to - 'false' - - otherwise - org.apache.taglibs.standard.tag.common.core.OtherwiseTag - JSP - - - - - Adds a parameter to a containing 'import' tag's URL. - - param - org.apache.taglibs.standard.tag.rt.core.ParamTag - JSP - - -Name of the query string parameter. - - name - true - true - - - -Value of the parameter. - - value - false - true - - - - - - Redirects to a new URL. - - redirect - org.apache.taglibs.standard.tag.rt.core.RedirectTag - JSP - - -The URL of the resource to redirect to. - - url - false - true - - - -Name of the context when redirecting to a relative URL -resource that belongs to a foreign context. - - context - false - true - - - - - - Removes a scoped variable (from a particular scope, if specified). - - remove - org.apache.taglibs.standard.tag.common.core.RemoveTag - empty - - -Name of the scoped variable to be removed. - - var - true - false - - - -Scope for var. - - scope - false - false - - - - - - Sets the result of an expression evaluation in a 'scope' - - set - org.apache.taglibs.standard.tag.rt.core.SetTag - JSP - - -Name of the exported scoped variable to hold the value -specified in the action. The type of the scoped variable is -whatever type the value expression evaluates to. - - var - false - false - - - -Expression to be evaluated. - - value - false - true - - java.lang.Object - - - - -Target object whose property will be set. Must evaluate to -a JavaBeans object with setter property property, or to a -java.util.Map object. - - target - false - true - - - -Name of the property to be set in the target object. - - property - false - true - - - -Scope for var. - - scope - false - false - - - - - - Creates a URL with optional query parameters. - - url - org.apache.taglibs.standard.tag.rt.core.UrlTag - JSP - - -Name of the exported scoped variable for the -processed url. The type of the scoped variable is -String. - - var - false - false - - - -Scope for var. - - scope - false - false - - - -URL to be processed. - - value - false - true - - - -Name of the context when specifying a relative URL -resource that belongs to a foreign context. - - context - false - true - - - - - - Subtag of <choose> that includes its body if its - condition evalutes to 'true' - - when - org.apache.taglibs.standard.tag.rt.core.WhenTag - JSP - - -The test condition that determines whether or not the -body content should be processed. - - test - true - true - boolean - - - - diff --git a/grails-plugins/dynamodb/web-app/WEB-INF/tld/fmt.tld b/grails-plugins/dynamodb/web-app/WEB-INF/tld/fmt.tld deleted file mode 100644 index 2ae47762d..000000000 --- a/grails-plugins/dynamodb/web-app/WEB-INF/tld/fmt.tld +++ /dev/null @@ -1,671 +0,0 @@ - - - - - JSTL 1.2 i18n-capable formatting library - JSTL fmt - 1.2 - fmt - http://java.sun.com/jsp/jstl/fmt - - - - Provides core validation features for JSTL tags. - - - org.apache.taglibs.standard.tlv.JstlFmtTLV - - - - - - Sets the request character encoding - - requestEncoding - org.apache.taglibs.standard.tag.rt.fmt.RequestEncodingTag - empty - - -Name of character encoding to be applied when -decoding request parameters. - - value - false - true - - - - - - Stores the given locale in the locale configuration variable - - setLocale - org.apache.taglibs.standard.tag.rt.fmt.SetLocaleTag - empty - - -A String value is interpreted as the -printable representation of a locale, which -must contain a two-letter (lower-case) -language code (as defined by ISO-639), -and may contain a two-letter (upper-case) -country code (as defined by ISO-3166). -Language and country codes must be -separated by hyphen (-) or underscore -(_). - - value - true - true - - - -Vendor- or browser-specific variant. -See the java.util.Locale javadocs for -more information on variants. - - variant - false - true - - - -Scope of the locale configuration variable. - - scope - false - false - - - - - - Specifies the time zone for any time formatting or parsing actions - nested in its body - - timeZone - org.apache.taglibs.standard.tag.rt.fmt.TimeZoneTag - JSP - - -The time zone. A String value is interpreted as -a time zone ID. This may be one of the time zone -IDs supported by the Java platform (such as -"America/Los_Angeles") or a custom time zone -ID (such as "GMT-8"). See -java.util.TimeZone for more information on -supported time zone formats. - - value - true - true - - - - - - Stores the given time zone in the time zone configuration variable - - setTimeZone - org.apache.taglibs.standard.tag.rt.fmt.SetTimeZoneTag - empty - - -The time zone. A String value is interpreted as -a time zone ID. This may be one of the time zone -IDs supported by the Java platform (such as -"America/Los_Angeles") or a custom time zone -ID (such as "GMT-8"). See java.util.TimeZone for -more information on supported time zone -formats. - - value - true - true - - - -Name of the exported scoped variable which -stores the time zone of type -java.util.TimeZone. - - var - false - false - - - -Scope of var or the time zone configuration -variable. - - scope - false - false - - - - - - Loads a resource bundle to be used by its tag body - - bundle - org.apache.taglibs.standard.tag.rt.fmt.BundleTag - JSP - - -Resource bundle base name. This is the bundle's -fully-qualified resource name, which has the same -form as a fully-qualified class name, that is, it uses -"." as the package component separator and does not -have any file type (such as ".class" or ".properties") -suffix. - - basename - true - true - - - -Prefix to be prepended to the value of the message -key of any nested <fmt:message> action. - - prefix - false - true - - - - - - Loads a resource bundle and stores it in the named scoped variable or - the bundle configuration variable - - setBundle - org.apache.taglibs.standard.tag.rt.fmt.SetBundleTag - empty - - -Resource bundle base name. This is the bundle's -fully-qualified resource name, which has the same -form as a fully-qualified class name, that is, it uses -"." as the package component separator and does not -have any file type (such as ".class" or ".properties") -suffix. - - basename - true - true - - - -Name of the exported scoped variable which stores -the i18n localization context of type -javax.servlet.jsp.jstl.fmt.LocalizationC -ontext. - - var - false - false - - - -Scope of var or the localization context -configuration variable. - - scope - false - false - - - - - - Maps key to localized message and performs parametric replacement - - message - org.apache.taglibs.standard.tag.rt.fmt.MessageTag - JSP - - -Message key to be looked up. - - key - false - true - - - -Localization context in whose resource -bundle the message key is looked up. - - bundle - false - true - - - -Name of the exported scoped variable -which stores the localized message. - - var - false - false - - - -Scope of var. - - scope - false - false - - - - - - Supplies an argument for parametric replacement to a containing - <message> tag - - param - org.apache.taglibs.standard.tag.rt.fmt.ParamTag - JSP - - -Argument used for parametric replacement. - - value - false - true - - - - - - Formats a numeric value as a number, currency, or percentage - - formatNumber - org.apache.taglibs.standard.tag.rt.fmt.FormatNumberTag - JSP - - -Numeric value to be formatted. - - value - false - true - - - -Specifies whether the value is to be -formatted as number, currency, or -percentage. - - type - false - true - - - -Custom formatting pattern. - - pattern - false - true - - - -ISO 4217 currency code. Applied only -when formatting currencies (i.e. if type is -equal to "currency"); ignored otherwise. - - currencyCode - false - true - - - -Currency symbol. Applied only when -formatting currencies (i.e. if type is equal -to "currency"); ignored otherwise. - - currencySymbol - false - true - - - -Specifies whether the formatted output -will contain any grouping separators. - - groupingUsed - false - true - - - -Maximum number of digits in the integer -portion of the formatted output. - - maxIntegerDigits - false - true - - - -Minimum number of digits in the integer -portion of the formatted output. - - minIntegerDigits - false - true - - - -Maximum number of digits in the -fractional portion of the formatted output. - - maxFractionDigits - false - true - - - -Minimum number of digits in the -fractional portion of the formatted output. - - minFractionDigits - false - true - - - -Name of the exported scoped variable -which stores the formatted result as a -String. - - var - false - false - - - -Scope of var. - - scope - false - false - - - - - - Parses the string representation of a number, currency, or percentage - - parseNumber - org.apache.taglibs.standard.tag.rt.fmt.ParseNumberTag - JSP - - -String to be parsed. - - value - false - true - - - -Specifies whether the string in the value -attribute should be parsed as a number, -currency, or percentage. - - type - false - true - - - -Custom formatting pattern that determines -how the string in the value attribute is to be -parsed. - - pattern - false - true - - - -Locale whose default formatting pattern (for -numbers, currencies, or percentages, -respectively) is to be used during the parse -operation, or to which the pattern specified -via the pattern attribute (if present) is -applied. - - parseLocale - false - true - - - -Specifies whether just the integer portion of -the given value should be parsed. - - integerOnly - false - true - - - -Name of the exported scoped variable which -stores the parsed result (of type -java.lang.Number). - - var - false - false - - - -Scope of var. - - scope - false - false - - - - - - Formats a date and/or time using the supplied styles and pattern - - formatDate - org.apache.taglibs.standard.tag.rt.fmt.FormatDateTag - empty - - -Date and/or time to be formatted. - - value - true - true - - - -Specifies whether the time, the date, or both -the time and date components of the given -date are to be formatted. - - type - false - true - - - -Predefined formatting style for dates. Follows -the semantics defined in class -java.text.DateFormat. Applied only -when formatting a date or both a date and -time (i.e. if type is missing or is equal to -"date" or "both"); ignored otherwise. - - dateStyle - false - true - - - -Predefined formatting style for times. Follows -the semantics defined in class -java.text.DateFormat. Applied only -when formatting a time or both a date and -time (i.e. if type is equal to "time" or "both"); -ignored otherwise. - - timeStyle - false - true - - - -Custom formatting style for dates and times. - - pattern - false - true - - - -Time zone in which to represent the formatted -time. - - timeZone - false - true - - - -Name of the exported scoped variable which -stores the formatted result as a String. - - var - false - false - - - -Scope of var. - - scope - false - false - - - - - - Parses the string representation of a date and/or time - - parseDate - org.apache.taglibs.standard.tag.rt.fmt.ParseDateTag - JSP - - -Date string to be parsed. - - value - false - true - - - -Specifies whether the date string in the -value attribute is supposed to contain a -time, a date, or both. - - type - false - true - - - -Predefined formatting style for days -which determines how the date -component of the date string is to be -parsed. Applied only when formatting a -date or both a date and time (i.e. if type -is missing or is equal to "date" or "both"); -ignored otherwise. - - dateStyle - false - true - - - -Predefined formatting styles for times -which determines how the time -component in the date string is to be -parsed. Applied only when formatting a -time or both a date and time (i.e. if type -is equal to "time" or "both"); ignored -otherwise. - - timeStyle - false - true - - - -Custom formatting pattern which -determines how the date string is to be -parsed. - - pattern - false - true - - - -Time zone in which to interpret any time -information in the date string. - - timeZone - false - true - - - -Locale whose predefined formatting styles -for dates and times are to be used during -the parse operation, or to which the -pattern specified via the pattern -attribute (if present) is applied. - - parseLocale - false - true - - - -Name of the exported scoped variable in -which the parsing result (of type -java.util.Date) is stored. - - var - false - false - - - -Scope of var. - - scope - false - false - - - - diff --git a/grails-plugins/dynamodb/web-app/WEB-INF/tld/grails.tld b/grails-plugins/dynamodb/web-app/WEB-INF/tld/grails.tld deleted file mode 100644 index 9bd036b8c..000000000 --- a/grails-plugins/dynamodb/web-app/WEB-INF/tld/grails.tld +++ /dev/null @@ -1,550 +0,0 @@ - - - The Grails custom tag library - 0.2 - grails - http://grails.codehaus.org/tags - - - link - org.codehaus.groovy.grails.web.taglib.jsp.JspLinkTag - JSP - - action - false - true - - - controller - false - true - - - id - false - true - - - url - false - true - - - params - false - true - - true - - - form - org.codehaus.groovy.grails.web.taglib.jsp.JspFormTag - JSP - - action - false - true - - - controller - false - true - - - id - false - true - - - url - false - true - - - method - true - true - - true - - - select - org.codehaus.groovy.grails.web.taglib.jsp.JspSelectTag - JSP - - name - true - true - - - value - false - true - - - optionKey - false - true - - - optionValue - false - true - - true - - - datePicker - org.codehaus.groovy.grails.web.taglib.jsp.JspDatePickerTag - empty - - name - true - true - - - value - false - true - - - precision - false - true - - false - - - currencySelect - org.codehaus.groovy.grails.web.taglib.jsp.JspCurrencySelectTag - empty - - name - true - true - - - value - false - true - - true - - - localeSelect - org.codehaus.groovy.grails.web.taglib.jsp.JspLocaleSelectTag - empty - - name - true - true - - - value - false - true - - true - - - timeZoneSelect - org.codehaus.groovy.grails.web.taglib.jsp.JspTimeZoneSelectTag - empty - - name - true - true - - - value - false - true - - true - - - checkBox - org.codehaus.groovy.grails.web.taglib.jsp.JspCheckboxTag - empty - - name - true - true - - - value - true - true - - true - - - hasErrors - org.codehaus.groovy.grails.web.taglib.jsp.JspHasErrorsTag - JSP - - model - false - true - - - bean - false - true - - - field - false - true - - false - - - eachError - org.codehaus.groovy.grails.web.taglib.jsp.JspEachErrorTag - JSP - - model - false - true - - - bean - false - true - - - field - false - true - - false - - - renderErrors - org.codehaus.groovy.grails.web.taglib.jsp.JspEachErrorTag - JSP - - model - false - true - - - bean - false - true - - - field - false - true - - - as - true - true - - false - - - message - org.codehaus.groovy.grails.web.taglib.jsp.JspMessageTag - JSP - - code - false - true - - - error - false - true - - - default - false - true - - false - - - remoteFunction - org.codehaus.groovy.grails.web.taglib.jsp.JspRemoteFunctionTag - empty - - before - false - true - - - after - false - true - - - action - false - true - - - controller - false - true - - - id - false - true - - - url - false - true - - - params - false - true - - - asynchronous - false - true - - - method - false - true - - - update - false - true - - - onSuccess - false - true - - - onFailure - false - true - - - onComplete - false - true - - - onLoading - false - true - - - onLoaded - false - true - - - onInteractive - false - true - - true - - - remoteLink - org.codehaus.groovy.grails.web.taglib.jsp.JspRemoteLinkTag - JSP - - before - false - true - - - after - false - true - - - action - false - true - - - controller - false - true - - - id - false - true - - - url - false - true - - - params - false - true - - - asynchronous - false - true - - - method - false - true - - - update - false - true - - - onSuccess - false - true - - - onFailure - false - true - - - onComplete - false - true - - - onLoading - false - true - - - onLoaded - false - true - - - onInteractive - false - true - - true - - - formRemote - org.codehaus.groovy.grails.web.taglib.jsp.JspFormRemoteTag - JSP - - before - false - true - - - after - false - true - - - action - false - true - - - controller - false - true - - - id - false - true - - - url - false - true - - - params - false - true - - - asynchronous - false - true - - - method - false - true - - - update - false - true - - - onSuccess - false - true - - - onFailure - false - true - - - onComplete - false - true - - - onLoading - false - true - - - onLoaded - false - true - - - onInteractive - false - true - - true - - - invokeTag - org.codehaus.groovy.grails.web.taglib.jsp.JspInvokeGrailsTagLibTag - JSP - - it - java.lang.Object - true - NESTED - - - tagName - true - true - - true - - - diff --git a/grails-plugins/dynamodb/web-app/WEB-INF/tld/spring.tld b/grails-plugins/dynamodb/web-app/WEB-INF/tld/spring.tld deleted file mode 100644 index 1bc7091f0..000000000 --- a/grails-plugins/dynamodb/web-app/WEB-INF/tld/spring.tld +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - 1.1.1 - - 1.2 - - Spring - - http://www.springframework.org/tags - - Spring Framework JSP Tag Library. Authors: Rod Johnson, Juergen Hoeller - - - - - htmlEscape - org.springframework.web.servlet.tags.HtmlEscapeTag - JSP - - - Sets default HTML escape value for the current page. - Overrides a "defaultHtmlEscape" context-param in web.xml, if any. - - - - defaultHtmlEscape - true - true - - - - - - - - escapeBody - org.springframework.web.servlet.tags.EscapeBodyTag - JSP - - - Escapes its enclosed body content, applying HTML escaping and/or JavaScript escaping. - The HTML escaping flag participates in a page-wide or application-wide setting - (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). - - - - htmlEscape - false - true - - - - javaScriptEscape - false - true - - - - - - - - message - org.springframework.web.servlet.tags.MessageTag - JSP - - - Retrieves the message with the given code, or text if code isn't resolvable. - The HTML escaping flag participates in a page-wide or application-wide setting - (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). - - - - code - false - true - - - - arguments - false - true - - - - text - false - true - - - - var - false - true - - - - scope - false - true - - - - htmlEscape - false - true - - - - javaScriptEscape - false - true - - - - - - - - theme - org.springframework.web.servlet.tags.ThemeTag - JSP - - - Retrieves the theme message with the given code, or text if code isn't resolvable. - The HTML escaping flag participates in a page-wide or application-wide setting - (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). - - - - code - false - true - - - - arguments - false - true - - - - text - false - true - - - - var - false - true - - - - scope - false - true - - - - htmlEscape - false - true - - - - javaScriptEscape - false - true - - - - - - - - hasBindErrors - org.springframework.web.servlet.tags.BindErrorsTag - JSP - - - Provides Errors instance in case of bind errors. - The HTML escaping flag participates in a page-wide or application-wide setting - (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). - - - - errors - org.springframework.validation.Errors - - - - name - true - true - - - - htmlEscape - false - true - - - - - - - - nestedPath - org.springframework.web.servlet.tags.NestedPathTag - JSP - - - Sets a nested path to be used by the bind tag's path. - - - - nestedPath - java.lang.String - - - - path - true - true - - - - - - - - bind - org.springframework.web.servlet.tags.BindTag - JSP - - - Provides BindStatus object for the given bind path. - The HTML escaping flag participates in a page-wide or application-wide setting - (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). - - - - status - org.springframework.web.servlet.support.BindStatus - - - - path - true - true - - - - ignoreNestedPath - false - true - - - - htmlEscape - false - true - - - - - - - - transform - org.springframework.web.servlet.tags.TransformTag - JSP - - - Provides transformation of variables to Strings, using an appropriate - custom PropertyEditor from BindTag (can only be used inside BindTag). - The HTML escaping flag participates in a page-wide or application-wide setting - (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). - - - - value - true - true - - - - var - false - true - - - - scope - false - true - - - - htmlEscape - false - true - - - - - diff --git a/grails-plugins/dynamodb/web-app/css/errors.css b/grails-plugins/dynamodb/web-app/css/errors.css deleted file mode 100644 index bdb58bcca..000000000 --- a/grails-plugins/dynamodb/web-app/css/errors.css +++ /dev/null @@ -1,109 +0,0 @@ -h1, h2 { - margin: 10px 25px 5px; -} - -h2 { - font-size: 1.1em; -} - -.filename { - font-style: italic; -} - -.exceptionMessage { - margin: 10px; - border: 1px solid #000; - padding: 5px; - background-color: #E9E9E9; -} - -.stack, -.snippet { - margin: 0 25px 10px; -} - -.stack, -.snippet { - border: 1px solid #ccc; - -mox-box-shadow: 0 0 2px rgba(0,0,0,0.2); - -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.2); - box-shadow: 0 0 2px rgba(0,0,0,0.2); -} - -/* error details */ -.error-details { - border-top: 1px solid #FFAAAA; - -mox-box-shadow: 0 0 2px rgba(0,0,0,0.2); - -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.2); - box-shadow: 0 0 2px rgba(0,0,0,0.2); - border-bottom: 1px solid #FFAAAA; - -mox-box-shadow: 0 0 2px rgba(0,0,0,0.2); - -webkit-box-shadow: 0 0 2px rgba(0,0,0,0.2); - box-shadow: 0 0 2px rgba(0,0,0,0.2); - background-color:#FFF3F3; - line-height: 1.5; - overflow: hidden; - padding: 5px; - padding-left:25px; -} - -.error-details dt { - clear: left; - float: left; - font-weight: bold; - margin-right: 5px; -} - -.error-details dt:after { - content: ":"; -} - -.error-details dd { - display: block; -} - -/* stack trace */ -.stack { - padding: 5px; - overflow: auto; - height: 150px; -} - -/* code snippet */ -.snippet { - background-color: #fff; - font-family: monospace; -} - -.snippet .line { - display: block; -} - -.snippet .lineNumber { - background-color: #ddd; - color: #999; - display: inline-block; - margin-right: 5px; - padding: 0 3px; - text-align: right; - width: 3em; -} - -.snippet .error { - background-color: #fff3f3; - font-weight: bold; -} - -.snippet .error .lineNumber { - background-color: #faa; - color: #333; - font-weight: bold; -} - -.snippet .line:first-child .lineNumber { - padding-top: 5px; -} - -.snippet .line:last-child .lineNumber { - padding-bottom: 5px; -} \ No newline at end of file diff --git a/grails-plugins/dynamodb/web-app/css/main.css b/grails-plugins/dynamodb/web-app/css/main.css deleted file mode 100644 index ed551d68e..000000000 --- a/grails-plugins/dynamodb/web-app/css/main.css +++ /dev/null @@ -1,585 +0,0 @@ -/* FONT STACK */ -body, -input, select, textarea { - font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; -} - -/* BASE LAYOUT */ - -html { - background-color: #ddd; - background-image: -moz-linear-gradient(center top, #aaa, #ddd); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #aaa), color-stop(1, #ddd)); - background-image: linear-gradient(top, #aaa, #ddd); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr = '#aaaaaa', EndColorStr = '#dddddd'); - background-repeat: no-repeat; - height: 100%; - /* change the box model to exclude the padding from the calculation of 100% height (IE8+) */ - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -html.no-cssgradients { - background-color: #aaa; -} - -.ie6 html { - height: 100%; -} - -html * { - margin: 0; -} - -body { - background: #ffffff; - color: #333333; - margin: 0 auto; - max-width: 960px; - overflow-x: hidden; /* prevents box-shadow causing a horizontal scrollbar in firefox when viewport < 960px wide */ - -moz-box-shadow: 0 0 0.3em #255b17; - -webkit-box-shadow: 0 0 0.3em #255b17; - box-shadow: 0 0 0.3em #255b17; -} - -#grailsLogo { - background-color: #abbf78; -} - -/* replace with .no-boxshadow body if you have modernizr available */ -.ie6 body, -.ie7 body, -.ie8 body { - border-color: #255b17; - border-style: solid; - border-width: 0 1px; -} - -.ie6 body { - height: 100%; -} - -a:link, a:visited, a:hover { - color: #48802c; -} - -a:hover, a:active { - outline: none; /* prevents outline in webkit on active links but retains it for tab focus */ -} - -h1 { - color: #48802c; - font-weight: normal; - font-size: 1.25em; - margin: 0.8em 0 0.3em 0; -} - -ul { - padding: 0; -} - -img { - border: 0; -} - -/* GENERAL */ - -#grailsLogo a { - display: inline-block; - margin: 1em; -} - -.content { -} - -.content h1 { - border-bottom: 1px solid #CCCCCC; - margin: 0.8em 1em 0.3em; - padding: 0 0.25em; -} - -.scaffold-list h1 { - border: none; -} - -.footer { - background: #abbf78; - color: #000; - clear: both; - font-size: 0.8em; - margin-top: 1.5em; - padding: 1em; - min-height: 1em; -} - -.footer a { - color: #255b17; -} - -.spinner { - background: url(../images/spinner.gif) 50% 50% no-repeat transparent; - height: 16px; - width: 16px; - padding: 0.5em; - position: absolute; - right: 0; - top: 0; - text-indent: -9999px; -} - -/* NAVIGATION MENU */ - -.nav { - background-color: #efefef; - padding: 0.5em 0.75em; - -moz-box-shadow: 0 0 3px 1px #aaaaaa; - -webkit-box-shadow: 0 0 3px 1px #aaaaaa; - box-shadow: 0 0 3px 1px #aaaaaa; - zoom: 1; -} - -.nav ul { - overflow: hidden; - padding-left: 0; - zoom: 1; -} - -.nav li { - display: block; - float: left; - list-style-type: none; - margin-right: 0.5em; - padding: 0; -} - -.nav a { - color: #666666; - display: block; - padding: 0.25em 0.7em; - text-decoration: none; - -moz-border-radius: 0.3em; - -webkit-border-radius: 0.3em; - border-radius: 0.3em; -} - -.nav a:active, .nav a:visited { - color: #666666; -} - -.nav a:focus, .nav a:hover { - background-color: #999999; - color: #ffffff; - outline: none; - text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8); -} - -.no-borderradius .nav a:focus, .no-borderradius .nav a:hover { - background-color: transparent; - color: #444444; - text-decoration: underline; -} - -.nav a.home, .nav a.list, .nav a.create { - background-position: 0.7em center; - background-repeat: no-repeat; - text-indent: 25px; -} - -.nav a.home { - background-image: url(../images/skin/house.png); -} - -.nav a.list { - background-image: url(../images/skin/database_table.png); -} - -.nav a.create { - background-image: url(../images/skin/database_add.png); -} - -/* CREATE/EDIT FORMS AND SHOW PAGES */ - -fieldset, -.property-list { - margin: 0.6em 1.25em 0 1.25em; - padding: 0.3em 1.8em 1.25em; - position: relative; - zoom: 1; - border: none; -} - -.property-list .fieldcontain { - list-style: none; - overflow: hidden; - zoom: 1; -} - -.fieldcontain { - margin-top: 1em; -} - -.fieldcontain label, -.fieldcontain .property-label { - color: #666666; - text-align: right; - width: 25%; -} - -.fieldcontain .property-label { - float: left; -} - -.fieldcontain .property-value { - display: block; - margin-left: 27%; -} - -label { - cursor: pointer; - display: inline-block; - margin: 0 0.25em 0 0; -} - -input, select, textarea { - background-color: #fcfcfc; - border: 1px solid #cccccc; - font-size: 1em; - padding: 0.2em 0.4em; -} - -select { - padding: 0.2em 0.2em 0.2em 0; -} - -select[multiple] { - vertical-align: top; -} - -textarea { - width: 250px; - height: 150px; - overflow: auto; /* IE always renders vertical scrollbar without this */ - vertical-align: top; -} - -input[type=checkbox], input[type=radio] { - background-color: transparent; - border: 0; - padding: 0; -} - -input:focus, select:focus, textarea:focus { - background-color: #ffffff; - border: 1px solid #eeeeee; - outline: 0; - -moz-box-shadow: 0 0 0.5em #ffffff; - -webkit-box-shadow: 0 0 0.5em #ffffff; - box-shadow: 0 0 0.5em #ffffff; -} - -.required-indicator { - color: #48802C; - display: inline-block; - font-weight: bold; - margin-left: 0.3em; - position: relative; - top: 0.1em; -} - -ul.one-to-many { - display: inline-block; - list-style-position: inside; - vertical-align: top; -} - -.ie6 ul.one-to-many, .ie7 ul.one-to-many { - display: inline; - zoom: 1; -} - -ul.one-to-many li.add { - list-style-type: none; -} - -/* EMBEDDED PROPERTIES */ - -fieldset.embedded { - background-color: transparent; - border: 1px solid #CCCCCC; - padding-left: 0; - padding-right: 0; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} - -fieldset.embedded legend { - margin: 0 1em; -} - -/* MESSAGES AND ERRORS */ - -.errors, -.message { - font-size: 0.8em; - line-height: 2; - margin: 1em 2em; - padding: 0.5em; -} - -.message { - background: #f3f3ff; - border: 1px solid #b2d1ff; - color: #006dba; - -moz-box-shadow: 0 0 0.25em #b2d1ff; - -webkit-box-shadow: 0 0 0.25em #b2d1ff; - box-shadow: 0 0 0.25em #b2d1ff; -} - -.errors { - background: #fff3f3; - border: 1px solid #ffaaaa; - color: #cc0000; - -moz-box-shadow: 0 0 0.25em #ff8888; - -webkit-box-shadow: 0 0 0.25em #ff8888; - box-shadow: 0 0 0.25em #ff8888; -} - -.errors ul, -.message { - padding: 0; -} - -.errors li { - list-style: none; - background: transparent url(../images/skin/exclamation.png) 0 50% no-repeat; - text-indent: 22px; -} - -.message { - background: transparent url(../images/skin/information.png) 0 50% no-repeat; - text-indent: 22px; -} - -/* form fields with errors */ - -.error input, .error select, .error textarea { - background: #fff3f3; - border-color: #ffaaaa; - color: #cc0000; -} - -.error input:focus, .error select:focus, .error textarea:focus { - -moz-box-shadow: 0 0 0.5em #ffaaaa; - -webkit-box-shadow: 0 0 0.5em #ffaaaa; - box-shadow: 0 0 0.5em #ffaaaa; -} - -/* same effects for browsers that support HTML5 client-side validation (these have to be specified separately or IE will ignore the entire rule) */ - -input:invalid, select:invalid, textarea:invalid { - background: #fff3f3; - border-color: #ffaaaa; - color: #cc0000; -} - -input:invalid:focus, select:invalid:focus, textarea:invalid:focus { - -moz-box-shadow: 0 0 0.5em #ffaaaa; - -webkit-box-shadow: 0 0 0.5em #ffaaaa; - box-shadow: 0 0 0.5em #ffaaaa; -} - -/* TABLES */ - -table { - border-top: 1px solid #DFDFDF; - border-collapse: collapse; - width: 100%; - margin-bottom: 1em; -} - -tr { - border: 0; -} - -tr>td:first-child, tr>th:first-child { - padding-left: 1.25em; -} - -tr>td:last-child, tr>th:last-child { - padding-right: 1.25em; -} - -td, th { - line-height: 1.5em; - padding: 0.5em 0.6em; - text-align: left; - vertical-align: top; -} - -th { - background-color: #efefef; - background-image: -moz-linear-gradient(top, #ffffff, #eaeaea); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #ffffff), color-stop(1, #eaeaea)); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr = '#ffffff', EndColorStr = '#eaeaea'); - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#eaeaea')"; - color: #666666; - font-weight: bold; - line-height: 1.7em; - padding: 0.2em 0.6em; -} - -thead th { - white-space: nowrap; -} - -th a { - display: block; - text-decoration: none; -} - -th a:link, th a:visited { - color: #666666; -} - -th a:hover, th a:focus { - color: #333333; -} - -th.sortable a { - background-position: right; - background-repeat: no-repeat; - padding-right: 1.1em; -} - -th.asc a { - background-image: url(../images/skin/sorted_asc.gif); -} - -th.desc a { - background-image: url(../images/skin/sorted_desc.gif); -} - -.odd { - background: #f7f7f7; -} - -.even { - background: #ffffff; -} - -th:hover, tr:hover { - background: #E1F2B6; -} - -/* PAGINATION */ - -.pagination { - border-top: 0; - margin: 0; - padding: 0.3em 0.2em; - text-align: center; - -moz-box-shadow: 0 0 3px 1px #AAAAAA; - -webkit-box-shadow: 0 0 3px 1px #AAAAAA; - box-shadow: 0 0 3px 1px #AAAAAA; - background-color: #EFEFEF; -} - -.pagination a, -.pagination .currentStep { - color: #666666; - display: inline-block; - margin: 0 0.1em; - padding: 0.25em 0.7em; - text-decoration: none; - -moz-border-radius: 0.3em; - -webkit-border-radius: 0.3em; - border-radius: 0.3em; -} - -.pagination a:hover, .pagination a:focus, -.pagination .currentStep { - background-color: #999999; - color: #ffffff; - outline: none; - text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8); -} - -.no-borderradius .pagination a:hover, .no-borderradius .pagination a:focus, -.no-borderradius .pagination .currentStep { - background-color: transparent; - color: #444444; - text-decoration: underline; -} - -/* ACTION BUTTONS */ - -.buttons { - background-color: #efefef; - overflow: hidden; - padding: 0.3em; - -moz-box-shadow: 0 0 3px 1px #aaaaaa; - -webkit-box-shadow: 0 0 3px 1px #aaaaaa; - box-shadow: 0 0 3px 1px #aaaaaa; - margin: 0.1em 0 0 0; - border: none; -} - -.buttons input, -.buttons a { - background-color: transparent; - border: 0; - color: #666666; - cursor: pointer; - display: inline-block; - margin: 0 0.25em 0; - overflow: visible; - padding: 0.25em 0.7em; - text-decoration: none; - - -moz-border-radius: 0.3em; - -webkit-border-radius: 0.3em; - border-radius: 0.3em; -} - -.buttons input:hover, .buttons input:focus, -.buttons a:hover, .buttons a:focus { - background-color: #999999; - color: #ffffff; - outline: none; - text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8); - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} - -.no-borderradius .buttons input:hover, .no-borderradius .buttons input:focus, -.no-borderradius .buttons a:hover, .no-borderradius .buttons a:focus { - background-color: transparent; - color: #444444; - text-decoration: underline; -} - -.buttons .delete, .buttons .edit, .buttons .save { - background-position: 0.7em center; - background-repeat: no-repeat; - text-indent: 25px; -} - -.buttons .delete { - background-image: url(../images/skin/database_delete.png); -} - -.buttons .edit { - background-image: url(../images/skin/database_edit.png); -} - -.buttons .save { - background-image: url(../images/skin/database_save.png); -} - -a.skip { - position: absolute; - left: -9999px; -} diff --git a/grails-plugins/dynamodb/web-app/css/mobile.css b/grails-plugins/dynamodb/web-app/css/mobile.css deleted file mode 100644 index 167f50221..000000000 --- a/grails-plugins/dynamodb/web-app/css/mobile.css +++ /dev/null @@ -1,82 +0,0 @@ -/* Styles for mobile devices */ - -@media screen and (max-width: 480px) { - .nav { - padding: 0.5em; - } - - .nav li { - margin: 0 0.5em 0 0; - padding: 0.25em; - } - - /* Hide individual steps in pagination, just have next & previous */ - .pagination .step, .pagination .currentStep { - display: none; - } - - .pagination .prevLink { - float: left; - } - - .pagination .nextLink { - float: right; - } - - /* pagination needs to wrap around floated buttons */ - .pagination { - overflow: hidden; - } - - /* slightly smaller margin around content body */ - fieldset, - .property-list { - padding: 0.3em 1em 1em; - } - - input, textarea { - width: 100%; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - } - - select, input[type=checkbox], input[type=radio], input[type=submit], input[type=button], input[type=reset] { - width: auto; - } - - /* hide all but the first column of list tables */ - .scaffold-list td:not(:first-child), - .scaffold-list th:not(:first-child) { - display: none; - } - - .scaffold-list thead th { - text-align: center; - } - - /* stack form elements */ - .fieldcontain { - margin-top: 0.6em; - } - - .fieldcontain label, - .fieldcontain .property-label, - .fieldcontain .property-value { - display: block; - float: none; - margin: 0 0 0.25em 0; - text-align: left; - width: auto; - } - - .errors ul, - .message p { - margin: 0.5em; - } - - .error ul { - margin-left: 0; - } -} diff --git a/grails-plugins/dynamodb/web-app/images/apple-touch-icon-retina.png b/grails-plugins/dynamodb/web-app/images/apple-touch-icon-retina.png deleted file mode 100644 index 5cc83edbe..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/apple-touch-icon-retina.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/apple-touch-icon.png b/grails-plugins/dynamodb/web-app/images/apple-touch-icon.png deleted file mode 100644 index aba337f61..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/apple-touch-icon.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/favicon.ico b/grails-plugins/dynamodb/web-app/images/favicon.ico deleted file mode 100644 index 3dfcb9279..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/favicon.ico and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/grails_logo.jpg b/grails-plugins/dynamodb/web-app/images/grails_logo.jpg deleted file mode 100644 index 8be657c07..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/grails_logo.jpg and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/grails_logo.png b/grails-plugins/dynamodb/web-app/images/grails_logo.png deleted file mode 100644 index 9836b93d2..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/grails_logo.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/leftnav_btm.png b/grails-plugins/dynamodb/web-app/images/leftnav_btm.png deleted file mode 100644 index 582e1eb92..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/leftnav_btm.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/leftnav_midstretch.png b/grails-plugins/dynamodb/web-app/images/leftnav_midstretch.png deleted file mode 100644 index 3cb8a5155..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/leftnav_midstretch.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/leftnav_top.png b/grails-plugins/dynamodb/web-app/images/leftnav_top.png deleted file mode 100644 index 6afec7d32..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/leftnav_top.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/skin/database_add.png b/grails-plugins/dynamodb/web-app/images/skin/database_add.png deleted file mode 100644 index 802bd6cde..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/skin/database_add.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/skin/database_delete.png b/grails-plugins/dynamodb/web-app/images/skin/database_delete.png deleted file mode 100644 index cce652e84..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/skin/database_delete.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/skin/database_edit.png b/grails-plugins/dynamodb/web-app/images/skin/database_edit.png deleted file mode 100644 index e501b668c..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/skin/database_edit.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/skin/database_save.png b/grails-plugins/dynamodb/web-app/images/skin/database_save.png deleted file mode 100644 index 44c06dddf..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/skin/database_save.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/skin/database_table.png b/grails-plugins/dynamodb/web-app/images/skin/database_table.png deleted file mode 100644 index 693709cbc..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/skin/database_table.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/skin/exclamation.png b/grails-plugins/dynamodb/web-app/images/skin/exclamation.png deleted file mode 100644 index c37bd062e..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/skin/exclamation.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/skin/house.png b/grails-plugins/dynamodb/web-app/images/skin/house.png deleted file mode 100644 index fed62219f..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/skin/house.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/skin/information.png b/grails-plugins/dynamodb/web-app/images/skin/information.png deleted file mode 100644 index 12cd1aef9..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/skin/information.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/skin/shadow.jpg b/grails-plugins/dynamodb/web-app/images/skin/shadow.jpg deleted file mode 100644 index b7ed44fad..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/skin/shadow.jpg and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/skin/sorted_asc.gif b/grails-plugins/dynamodb/web-app/images/skin/sorted_asc.gif deleted file mode 100644 index 6b179c11c..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/skin/sorted_asc.gif and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/skin/sorted_desc.gif b/grails-plugins/dynamodb/web-app/images/skin/sorted_desc.gif deleted file mode 100644 index 38b3a01d0..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/skin/sorted_desc.gif and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/spinner.gif b/grails-plugins/dynamodb/web-app/images/spinner.gif deleted file mode 100644 index 1ed786f2e..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/spinner.gif and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/images/springsource.png b/grails-plugins/dynamodb/web-app/images/springsource.png deleted file mode 100644 index e806d0011..000000000 Binary files a/grails-plugins/dynamodb/web-app/images/springsource.png and /dev/null differ diff --git a/grails-plugins/dynamodb/web-app/js/application.js b/grails-plugins/dynamodb/web-app/js/application.js deleted file mode 100644 index b2adb962e..000000000 --- a/grails-plugins/dynamodb/web-app/js/application.js +++ /dev/null @@ -1,9 +0,0 @@ -if (typeof jQuery !== 'undefined') { - (function($) { - $('#spinner').ajaxStart(function() { - $(this).fadeIn(); - }).ajaxStop(function() { - $(this).fadeOut(); - }); - })(jQuery); -} diff --git a/grails-plugins/jpa/GormJpaGrailsPlugin.groovy b/grails-plugins/jpa/GormJpaGrailsPlugin.groovy deleted file mode 100644 index 1e10d274d..000000000 --- a/grails-plugins/jpa/GormJpaGrailsPlugin.groovy +++ /dev/null @@ -1,60 +0,0 @@ -import org.grails.datastore.gorm.jpa.plugin.support.* - -class GormJpaGrailsPlugin { - // the plugin version - def version = "1.0.0.M1" - // the version or versions of Grails the plugin is designed for - def grailsVersion = "2.0.0 > *" - // the other plugins this plugin depends on - def dependsOn = [:] - // resources that are excluded from plugin packaging - def pluginExcludes = [ - "grails-app/views/error.gsp" - ] - - def title = "Gorm Jpa Plugin" // Headline display name of the plugin - def author = "Graeme Rocher" - def authorEmail = "grocher@vmware.com" - def description = '''\ -Implementation of GORM for JPA -''' - - // URL to the plugin's documentation - def documentation = "http://grails.org/plugin/gorm-jpa" - - // Extra (optional) plugin metadata - - // License: one of 'APACHE', 'GPL2', 'GPL3' - def license = "APACHE" - - // Details of company behind the plugin (if there is one) - def organization = [ name: "SpringSource", url: "http://www.springsource.com/" ] - - // Any additional developers beyond the author specified above. - def developers = [ [ name: "Graeme Rocher", email: "grocher@vmware.com" ]] - - // Location of the plugin's issue tracker. - def issueManagement = [ system: "JIRA", url: "http://jira.grails.org/browse/GPGORMJPA" ] - - // Online location of the plugin's browseable source code. - def scm = [ url: "https://github.com/SpringSource/grails-data-mapping/tree/master/grails-plugins" ] - - def observe = ['services', 'domainClass'] - - def doWithSpring = new JpaSpringConfigurer().getConfiguration() - - def doWithDynamicMethods = { ctx -> - def datastore = ctx.jpaDatastore - def transactionManager = ctx.getBean(org.springframework.orm.jpa.JpaTransactionManager) - def methodsConfigurer = new JpaMethodsConfigurer(datastore, transactionManager) - def foe = application?.config?.grails?.gorm?.failOnError - methodsConfigurer.failOnError = foe instanceof Boolean ? foe : false - methodsConfigurer.configure() - } - - def onChange = { event -> - if(event.ctx) { - new JpaOnChangeHandler(event.ctx.jpaDatastore, event.ctx.jpaTransactionManager).onChange(delegate, event) - } - } -} diff --git a/grails-plugins/jpa/application.properties b/grails-plugins/jpa/application.properties deleted file mode 100644 index a4b295c44..000000000 --- a/grails-plugins/jpa/application.properties +++ /dev/null @@ -1,5 +0,0 @@ -#Grails Metadata file -#Tue Jan 10 12:47:29 CET 2012 -app.grails.version=2.0.0 -app.name=gorm-jpa -plugins.svn=1.0.2 diff --git a/grails-plugins/jpa/grails-app/conf/BuildConfig.groovy b/grails-plugins/jpa/grails-app/conf/BuildConfig.groovy deleted file mode 100644 index f42a7c419..000000000 --- a/grails-plugins/jpa/grails-app/conf/BuildConfig.groovy +++ /dev/null @@ -1,60 +0,0 @@ -grails.project.class.dir = "target/classes" -grails.project.test.class.dir = "target/test-classes" -grails.project.test.reports.dir = "target/test-reports" -grails.project.target.level = 1.6 -//grails.project.war.file = "target/${appName}-${appVersion}.war" - -grails.project.dependency.resolution = { - // inherit Grails' default dependencies - inherits("global") { - // uncomment to disable ehcache - // excludes 'ehcache' - } - log "warn" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose' - repositories { - grailsCentral() - // uncomment the below to enable remote dependency resolution - // from public Maven repositories - //mavenCentral() - mavenRepo "http://repo.grails.org/grails/core" - //mavenRepo "http://snapshots.repository.codehaus.org" - //mavenRepo "http://repository.codehaus.org" - //mavenRepo "http://download.java.net/maven/2/" - //mavenRepo "http://repository.jboss.com/maven2/" - } - dependencies { - def excludes = { - excludes "slf4j-simple", "persistence-api", "commons-logging", "jcl-over-slf4j", "slf4j-api", "jta" - excludes "spring-core", "spring-beans", "spring-aop", "spring-asm","spring-webmvc","spring-tx", "spring-context", "spring-web", "log4j", "slf4j-log4j12" - excludes group:"org.grails", name:'grails-core' - excludes group:"org.grails", name:'grails-gorm' - excludes group:"org.grails", name:'grails-test' - excludes group:'xml-apis', name:'xml-apis' - excludes 'ehcache-core' - transitive = false - } - - - def datastoreVersion = "1.0.0.RELEASE" - def jpaDatastoreVersion = "1.0.0.RC3" - - compile ("org.grails:grails-datastore-jpa:$jpaDatastoreVersion", - "org.grails:grails-datastore-gorm-jpa:$jpaDatastoreVersion",excludes) - compile("org.grails:grails-datastore-gorm-plugin-support:$datastoreVersion", - "org.grails:grails-datastore-gorm:$datastoreVersion", - "org.grails:grails-datastore-core:$datastoreVersion", - "org.grails:grails-datastore-web:$datastoreVersion",excludes) - - runtime 'javassist:javassist:3.12.0.GA' - - test("org.grails:grails-datastore-gorm-test:$datastoreVersion", - "org.grails:grails-datastore-simple:$datastoreVersion", excludes) - } - - plugins { - build(":tomcat:$grailsVersion", - ":release:1.0.1") { - export = false - } - } -} diff --git a/grails-plugins/jpa/grails-app/conf/Config.groovy b/grails-plugins/jpa/grails-app/conf/Config.groovy deleted file mode 100644 index e448e67d2..000000000 --- a/grails-plugins/jpa/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/jpa/grails-app/views/error.gsp b/grails-plugins/jpa/grails-app/views/error.gsp deleted file mode 100644 index 64a0b08b5..000000000 --- a/grails-plugins/jpa/grails-app/views/error.gsp +++ /dev/null @@ -1,11 +0,0 @@ - - - - Grails Runtime Exception - - - - - - - \ No newline at end of file diff --git a/grails-plugins/mongodb/.classpath b/grails-plugins/mongodb/.classpath deleted file mode 100644 index 27107c2b7..000000000 --- a/grails-plugins/mongodb/.classpath +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/grails-plugins/mongodb/.gitignore b/grails-plugins/mongodb/.gitignore deleted file mode 100644 index a394f81aa..000000000 --- a/grails-plugins/mongodb/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/plugin.xml -/grails-mongodb*.zip diff --git a/grails-plugins/mongodb/.project b/grails-plugins/mongodb/.project deleted file mode 100644 index c173311c2..000000000 --- a/grails-plugins/mongodb/.project +++ /dev/null @@ -1,26 +0,0 @@ - - - mongodb - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.grails.ide.eclipse.core.nature - org.eclipse.jdt.groovy.core.groovyNature - org.eclipse.jdt.core.javanature - - - - .link_to_grails_plugins - 2 - /home/burt/workspace.nosql/grails-data-mapping/grails-plugins/mongodb/target/plugins - - - 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 bf339c77a..000000000 --- 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/LICENSE b/grails-plugins/mongodb/LICENSE deleted file mode 100644 index de401aa99..000000000 --- a/grails-plugins/mongodb/LICENSE +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (C) 2010 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. - */ diff --git a/grails-plugins/mongodb/MongodbGrailsPlugin.groovy b/grails-plugins/mongodb/MongodbGrailsPlugin.groovy deleted file mode 100644 index 3df9abbb9..000000000 --- a/grails-plugins/mongodb/MongodbGrailsPlugin.groovy +++ /dev/null @@ -1,42 +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 - -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/SpringSource/grails-data-mapping"] - - def version = "1.3.0.BUILD-SNAPSHOT" - def grailsVersion = "2.1.4 > *" - def observe = ['services', 'domainClass'] - def loadAfter = ['domainClass', 'hibernate', '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.org/plugin/mongodb" - - def doWithSpring = new MongoSpringConfigurer().getConfiguration() - - def doWithDynamicMethods = { ctx -> - def datastore = ctx.mongoDatastore - def transactionManager = ctx.mongoTransactionManager - def methodsConfigurer = new MongoMethodsConfigurer(datastore, transactionManager) - methodsConfigurer.hasExistingDatastore = manager.hasGrailsPlugin("hibernate") - 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 b6015f7b3..000000000 --- a/grails-plugins/mongodb/application.properties +++ /dev/null @@ -1 +0,0 @@ -app.grails.version=2.2.3 diff --git a/grails-plugins/mongodb/grails-app/conf/BuildConfig.groovy b/grails-plugins/mongodb/grails-app/conf/BuildConfig.groovy deleted file mode 100644 index 8f2621bc9..000000000 --- a/grails-plugins/mongodb/grails-app/conf/BuildConfig.groovy +++ /dev/null @@ -1,57 +0,0 @@ -grails.project.work.dir = 'target' -grails.project.source.level = 1.6 - -grails.project.dependency.resolution = { - - inherits( "global" ) { - excludes 'xml-apis', 'netty' - } - log 'warn' - - repositories { - mavenCentral() - grailsCentral() - mavenLocal() - - } - - dependencies { - def excludes = { - excludes "slf4j-simple", "persistence-api", "commons-logging", "jcl-over-slf4j", "slf4j-api", "jta" - excludes "spring-core", "spring-beans", "spring-aop", "spring-asm","spring-webmvc","spring-tx", "spring-context", "spring-web", "log4j", "slf4j-log4j12" - excludes group:"org.grails", name:'grails-core' - excludes group:"org.grails", name:'grails-gorm' - excludes group:"org.grails", name:'grails-test' - excludes group:'xml-apis', name:'xml-apis' - excludes 'ehcache-core' - transitive = false - } - - compile("org.mongodb:mongo-java-driver:2.11.1", excludes) - compile("org.springframework.data:spring-data-mongodb:1.2.1.RELEASE", excludes) - compile("org.springframework.data:spring-data-commons-core:1.4.1.RELEASE", excludes) - runtime 'org.springframework.data:spring-data-commons:1.5.1.RELEASE' - runtime("com.gmongo:gmongo:1.2", excludes) - - def datastoreVersion = "1.1.9.BUILD-SNAPSHOT" - def mongoDatastoreVersion = "1.3.0.BUILD-SNAPSHOT" - - compile ("org.grails:grails-datastore-mongo:$mongoDatastoreVersion", - "org.grails:grails-datastore-gorm-mongo:$mongoDatastoreVersion",excludes) - compile("org.grails:grails-datastore-gorm-plugin-support:$datastoreVersion", - "org.grails:grails-datastore-gorm:$datastoreVersion", - "org.grails:grails-datastore-core:$datastoreVersion", - "org.grails:grails-datastore-web:$datastoreVersion",excludes) - - runtime 'org.javassist:javassist:3.16.1-GA' - - test("org.grails:grails-datastore-gorm-test:$datastoreVersion", - "org.grails:grails-datastore-simple:$datastoreVersion", excludes) - } - - plugins { - build(':release:2.2.0', ':rest-client-builder:1.0.3') { - export = false - } - } -} 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 2e57c6d88..000000000 --- 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 76beddedf..000000000 --- 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 a21216087..000000000 --- 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 7c5316914..000000000 --- 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 6a1a4c925..000000000 --- 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/neo4j/.gitignore b/grails-plugins/neo4j/.gitignore deleted file mode 100644 index 6a2d9fcdb..000000000 --- a/grails-plugins/neo4j/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -target -*.log -*.zip -*.iws -data -plugin.xml diff --git a/grails-plugins/neo4j/LICENSE.txt b/grails-plugins/neo4j/LICENSE.txt deleted file mode 100644 index 023ad8200..000000000 --- a/grails-plugins/neo4j/LICENSE.txt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2004-2010 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. - */ \ No newline at end of file diff --git a/grails-plugins/neo4j/Neo4jGrailsPlugin.groovy b/grails-plugins/neo4j/Neo4jGrailsPlugin.groovy deleted file mode 100644 index 87b008c53..000000000 --- a/grails-plugins/neo4j/Neo4jGrailsPlugin.groovy +++ /dev/null @@ -1,128 +0,0 @@ -import org.codehaus.groovy.grails.validation.ConstrainedProperty -import org.grails.datastore.gorm.neo4j.constraints.UniqueConstraint -import org.grails.datastore.gorm.neo4j.plugin.support.Neo4jMethodsConfigurer -import org.grails.datastore.gorm.neo4j.plugin.support.Neo4jOnChangeHandler -import org.grails.datastore.gorm.neo4j.plugin.support.Neo4jSpringConfigurer -import org.neo4j.kernel.impl.core.NodeProxy -import org.neo4j.kernel.impl.core.RelationshipProxy -import grails.converters.JSON -import org.codehaus.groovy.grails.commons.metaclass.MetaClassEnhancer -import org.codehaus.groovy.grails.plugins.converters.api.ConvertersApi -import org.codehaus.groovy.grails.commons.GrailsMetaClassUtils -import org.springframework.context.ApplicationContext - -class Neo4jGrailsPlugin { - - def license = "Apache 2.0 License" - def organization = [ name: "Stefan Armbruster", url: "http://blog.armbruster-it.de/" ] - def developers = [ - [ name: "Stefan Armbruster", email: "stefan@armbruster-it.de" ] ] - def issueManagement = [ system: "JIRA", url: "https://github.com/SpringSource/grails-data-mapping/issues" ] - def scm = [ url: "https://github.com/sarmbruster/grails-data-mapping" ] - - //def version = "1.0.1" - def version = "1.0.1.SNAPSHOT" - def grailsVersion = "1.2 > *" - def loadAfter = ['domainClass', 'hibernate', 'services', 'cloudFoundry', 'converters'] - def observe = ['services', 'domainClass'] - - def author = "Stefan Armbruster" - def authorEmail = "stefan@armbruster-it.de" - def title = "Neo4j GORM" - def description = 'A plugin that integrates the Neo4j graph database into Grails, providing a GORM API onto it' - - def documentation = "http://grails.org/plugin/neo4j" - - def dependsOn = [:] - // resources that are excluded from plugin packaging - - def pluginExcludes = [ - "grails-app/views/error.gsp" - ] - - def doWithSpring = new Neo4jSpringConfigurer().getConfiguration() - - def doWithDynamicMethods = { ctx -> - def datastore = ctx.neo4jDatastore - def transactionManager = ctx.neo4jTransactionManager - def methodsConfigurer = new Neo4jMethodsConfigurer(datastore, transactionManager) - methodsConfigurer.hasExistingDatastore = manager.hasGrailsPlugin("hibernate") - def foe = application?.config?.grails?.gorm?.failOnError - methodsConfigurer.failOnError = foe instanceof Boolean ? foe : false - - methodsConfigurer.configure() - - setupGetOrSet() - - setupJsonMarshallers(ctx) - } - - private void setupJsonMarshallers(ApplicationContext ctx) { - MetaClassEnhancer enhancer = new MetaClassEnhancer() - enhancer.addApi(new ConvertersApi(applicationContext: ctx)) - - // Override GDK asType for some common Interfaces and Classes - enhancer.enhanceAll([NodeProxy, RelationshipProxy].collect { - GrailsMetaClassUtils.getExpandoMetaClass(it) - }) - - - JSON.registerObjectMarshaller(NodeProxy) { n -> - def m = [:] - m.id = n.id - n.propertyKeys.each { k -> - m[(k)] = n."$k" - } - m.relationships = n.relationships.collect {it} - m - } - - JSON.registerObjectMarshaller(RelationshipProxy) { r -> - def m = [:] - m.id = r.id - m.type = r.type.name() - m.startNode = r.startNode.id - m.endNode = r.endNode.id - r.propertyKeys.each { k -> - m[(k)] = r."$k" - } - m - } - } - - private void setupGetOrSet() { - def getOrSet = { name, value = null -> - if (value) { - delegate.setProperty(name, value instanceof Date ? value.time : value) - } else { - def val = delegate.getProperty(name, null) - (val instanceof Long && name.endsWith('Date')) ? new Date(val) : val - } - } - - def classLoader = Thread.currentThread().contextClassLoader - def classes = [NodeProxy, RelationshipProxy] - ['org.neo4j.rest.graphdb.entity.RestNode', 'org.neo4j.rest.graphdb.entity.RestRelationship'].each { - try { - classes << classLoader.loadClass(it) - } catch (ClassNotFoundException e) { - //pass - } - } - - classes.each { - it.metaClass.propertyMissing = getOrSet - } - } - - def doWithApplicationContext = { applicationContext -> - //ConstrainedProperty.registerNewConstraint(UniqueConstraint.UNIQUE_CONSTRAINT, UniqueConstraint.class ); - } - - def onChange = { event -> - if(event.ctx) { - new Neo4jOnChangeHandler(event.ctx.neo4jDatastore, event.ctx.neo4jTransactionManager).onChange(delegate, event) - } - } - -} diff --git a/grails-plugins/neo4j/application.properties b/grails-plugins/neo4j/application.properties deleted file mode 100644 index 2db7b2693..000000000 --- a/grails-plugins/neo4j/application.properties +++ /dev/null @@ -1,4 +0,0 @@ -#Grails Metadata file -#Tue Oct 23 23:32:27 PDT 2012 -app.grails.version=2.1.4 -app.name=neo4j diff --git a/grails-plugins/neo4j/grails-app/conf/BuildConfig.groovy b/grails-plugins/neo4j/grails-app/conf/BuildConfig.groovy deleted file mode 100644 index 3f9f66a6a..000000000 --- a/grails-plugins/neo4j/grails-app/conf/BuildConfig.groovy +++ /dev/null @@ -1,82 +0,0 @@ -grails.project.class.dir = "target/classes" -grails.project.test.class.dir = "target/test-classes" -grails.project.test.reports.dir = "target/test-reports" - -grails.project.dependency.resolution = { - - inherits("global") { - excludes 'xml-apis', 'netty'//, 'xercesImpl' - } - log "warn" - - repositories { - inherits true - - grailsPlugins() - grailsHome() - mavenLocal() // for picking up self-built snapshots before fetching from grailsCentral - grailsCentral() - mavenCentral() - - //mavenRepo 'http://m2.neo4j.org/releases' - mavenRepo "http://repo.grails.org/grails/repo" - } - - dependencies { - - def excludes = { - excludes "slf4j-simple", "persistence-api", "commons-logging", "jcl-over-slf4j", "slf4j-api", "jta" - excludes "spring-core", "spring-beans", "spring-aop", "spring-asm","spring-webmvc","spring-tx", "spring-context", "spring-web", "log4j", "slf4j-log4j12" - excludes group:"org.grails", name:'grails-core' - excludes group:"org.grails", name:'grails-gorm' - excludes group:"org.grails", name:'grails-test' - excludes group:'xml-apis', name:'xml-apis' - excludes 'ehcache-core' - transitive = false - } - - //def datastoreVersion = "1.1.4.BUILD-SNAPSHOT" - def datastoreVersion = "1.1.7.RELEASE" - def neo4jDatastoreVersion = "1.0.1.SNAPSHOT" - //def neo4jDatastoreVersion = "1.0.1" - def seleniumVersion = "2.31.0" - - compile("org.grails:grails-datastore-gorm-neo4j:$neo4jDatastoreVersion", - "org.grails:grails-datastore-gorm-plugin-support:$datastoreVersion", - "org.grails:grails-datastore-gorm:$datastoreVersion", - "org.grails:grails-datastore-core:$datastoreVersion", - "org.grails:grails-datastore-web:$datastoreVersion", excludes) - - test("org.grails:grails-datastore-gorm-test:$datastoreVersion", - "org.grails:grails-datastore-simple:$datastoreVersion", exlcudes) - - compile('org.neo4j:neo4j-community:1.8.2') - - test "org.gebish:geb-spock:0.9.0" - test "org.seleniumhq.selenium:selenium-support:$seleniumVersion" - test( "com.github.detro.ghostdriver:phantomjsdriver:1.0.3" ) { - transitive = false - } - test "org.seleniumhq.selenium:selenium-chrome-driver:$seleniumVersion" - test "org.seleniumhq.selenium:selenium-firefox-driver:$seleniumVersion" - - // htmlunit seems to be broken -/* test("org.seleniumhq.selenium:selenium-htmlunit-driver:$seleniumVersion") { - exclude 'xml-apis' - }*/ - } - - plugins { - runtime(":jquery:1.7.1", ":resources:1.1.6", ":tomcat:$grailsVersion") { - export = false - } - build ":release:2.2.1", { - export = false - } - //runtime ":svn:1.0.2" - test(":spock:0.7", ":geb:0.9.0") { - export = false - } - } - -} diff --git a/grails-plugins/neo4j/grails-app/conf/Config.groovy b/grails-plugins/neo4j/grails-app/conf/Config.groovy deleted file mode 100644 index 855707e61..000000000 --- a/grails-plugins/neo4j/grails-app/conf/Config.groovy +++ /dev/null @@ -1,28 +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' -} -grails.views.default.codec="none" // none, html, base64 -grails.views.gsp.encoding="UTF-8" - -grails.spring.bean.packages = [ "org.springframework.data.graph.neo4j.config" ] diff --git a/grails-plugins/neo4j/grails-app/conf/DataSource.groovy b/grails-plugins/neo4j/grails-app/conf/DataSource.groovy deleted file mode 100644 index a21da20d1..000000000 --- a/grails-plugins/neo4j/grails-app/conf/DataSource.groovy +++ /dev/null @@ -1,40 +0,0 @@ -grails { - neo4j { - // define a Neo4j datasource - // type is either "embedded", "rest", "ha", or any custom class implementing GraphDatabaseService - - // 1) embedded - // when using embedded, Neo4j runs inside the same JVM like the Grails application - // options: - // location: the path where Neo4j is stored, defaults to "data/neo4j" - // params: optional map passed to EmbeddedGraphDatabase - type = "embedded" - // location = "data/neo4j" - // params = [:] - - - // 2) rest - // when using a Neo4j server via rest REST uncomment the following line - // type = "rest" - // options: - // location: URL of rest server, defaults to http://localhost:7474/db/data/ - // NB: if heroku is used just omit location, the plugin tries to use env.NEO4J_URL in this case - // NB: params are not allowed when using REST - - // type="rest - // location = "http://localhost:7474/db/data/" - - // 3) HA embedded - // use a in-JVM Neo4j instance being part of a HA cluster - // options: - // location: directory where Neo4j stores the db - // options: parameters for HA setup, see http://docs.neo4j.org/chunked/stable/ha-configuration.html#_installation_notes - // type = "ha" - // location = "data/neo4j" - // params = [ - // ha.server_id = 1 - // ha.coordinators = " localhost:2181,localhost:2182,localhost:2183" - // ] - - } -} diff --git a/grails-plugins/neo4j/grails-app/conf/Neo4jBootStrap.groovy b/grails-plugins/neo4j/grails-app/conf/Neo4jBootStrap.groovy deleted file mode 100644 index bc49146ea..000000000 --- a/grails-plugins/neo4j/grails-app/conf/Neo4jBootStrap.groovy +++ /dev/null @@ -1,23 +0,0 @@ -import org.neo4j.kernel.AbstractGraphDatabase - -class Neo4jBootStrap { - - def graphDatabaseService - def neoServer - - def init = { servletContext -> - - if (graphDatabaseService instanceof AbstractGraphDatabase) { - try { - neoServer = Thread.currentThread().contextClassLoader.loadClass('org.neo4j.server.WrappingNeoServerBootstrapper').newInstance([graphDatabaseService] as Object[]) - neoServer.start() - } catch (ClassNotFoundException e) { - log.info("org.neo4j.server.WrappingNeoServerBootstrapper not started, class not found, consider adding neo4j-server-.jar to dependencies") - } - } - } - - def destroy = { - neoServer?.stop() - } -} diff --git a/grails-plugins/neo4j/grails-app/conf/UrlMappings.groovy b/grails-plugins/neo4j/grails-app/conf/UrlMappings.groovy deleted file mode 100644 index 8c597d6c2..000000000 --- a/grails-plugins/neo4j/grails-app/conf/UrlMappings.groovy +++ /dev/null @@ -1,13 +0,0 @@ -class UrlMappings { - - static mappings = { - "/$controller/$action?/$id?"{ - constraints { - // apply constraints here - } - } - - "/"(view:"/index") - "500"(view:'/error') - } -} diff --git a/grails-plugins/neo4j/grails-app/controllers/org/grails/datastore/gorm/neo4j/Neo4jController.groovy b/grails-plugins/neo4j/grails-app/controllers/org/grails/datastore/gorm/neo4j/Neo4jController.groovy deleted file mode 100644 index cad8d61e5..000000000 --- a/grails-plugins/neo4j/grails-app/controllers/org/grails/datastore/gorm/neo4j/Neo4jController.groovy +++ /dev/null @@ -1,169 +0,0 @@ -package org.grails.datastore.gorm.neo4j - -import org.neo4j.graphdb.GraphDatabaseService -import org.neo4j.graphdb.Node -import org.neo4j.graphdb.Relationship -import org.neo4j.graphdb.Direction -import org.codehaus.groovy.grails.commons.GrailsDomainClass -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty -import org.neo4j.graphdb.Traverser - -class Neo4jController { - - GraphDatabaseService graphDatabaseService - - static defaultAction = "node" - - def beforeInterceptor = { - if (!["127.0.0.1", "0:0:0:0:0:0:0:1"].contains(request.remoteAddr)) { - render(status: 503, text: 'Access limited to localhost') - return false - } - } - - def node = { - def node = params.id ? graphDatabaseService.getNodeById(params.long("id")) : graphDatabaseService.referenceNode; - assert node - [node: node] - } - - def relationship = { - def rel = graphDatabaseService.getRelationshipById(params.long("id")) - assert rel - [rel:rel] - } - - def traverse = { TraverseCommand cmd -> - - if (params.traverse ) { - log.error "cmd: $cmd" - if (!cmd.validate()) { - cmd.errors.each { - log.error it - } - } - //Node node = params.id ? neoService.getNodeById(params.id as long) : neoService.getReferenceNode(); - //node.traverse() - } else { - } - [command: cmd] - } - - def statistics = { - - def typeCounter = [:] - def reltypeCounter = [:] - - for (Node node in graphDatabaseService.allNodes) { - def type = node.getProperty("type", "n/a") - typeCounter[type] = typeCounter.get(type, 0)+1 - - for (Relationship rel in node.getRelationships(Direction.OUTGOING)) { - def reltype = rel.type.name() - reltypeCounter[reltype] = reltypeCounter.get(reltype, 0)+1 - - } - } - - [typeCounter:typeCounter, reltypeCounter:reltypeCounter] - } - - def fixDoubleRelationShips = { - - def counter = 0 - def removed = 0 - def intransaction = 0 - - def tx = graphDatabaseService.beginTx() - - for (Node node in graphDatabaseService.allNodes) { - counter++ - if (counter%10000==0) { - log.error "Processing $counter" - } - - if (intransaction > 5000) { - log.error "intransaction: $intransaction -> new transaction" - intransaction = 0 - tx.success() - tx.finish() - tx = graphDatabaseService.beginTx() - } - - def relationshipsMap = [:] - - for (Relationship rel in node.getRelationships(Direction.OUTGOING)) { - def reltype = rel.type.name() - //reltypeCounter[reltype] = reltypeCounter.get(reltype, 0)+1 - - def key = [ reltype, rel.startNode.id, rel.endNode.id] - //key.sort() - - if (relationshipsMap.containsKey(key)) { - relationshipsMap[key] << rel - } else { - relationshipsMap[key] = [rel] - } - - } - def doubledRelationships = relationshipsMap.findAll {k, v -> v.size() > 1} - - doubledRelationships.each { - log.debug "${it.key} -> ${it.value}" - removed += it.value.size()-1 - intransaction += it.value.size()-1 - it.value[1..-1].each { rel -> rel.delete() } - } - - } - - tx.success() - tx.finish() - - - [ removed: removed ] - } - - def domain = { - - def filter=["bidirectional", "oneToMany", "manyToOne", "manyToMany", "hasOne", "oneToOne", "owningSide"] - def filters = params.list("filter") - def domainProps = [] - def domainClassesNames = params.list("domainClasses") - - def allDomainClasses = grailsApplication.domainClasses.collect {it}. // use a clone - sort { it.name } - - def domainClasses = allDomainClasses.findAll { domainClassesNames.contains(it.name) } - - for (GrailsDomainClass dc in domainClasses) { - for (GrailsDomainClassProperty prop in dc.persistantProperties) { - - if (filters.any { prop."$it" } ) { - //if (!params.filter || params.filter=='all' || prop.association) { - domainProps << prop - } - } - } - - [ domainProps:domainProps, - domainClassesNames:domainClassesNames, - allDomainClasses: allDomainClasses, - filter:filter, - filters:filters - ] - } - - def doforward() { - forward action:"node" - } -} - -public class TraverseCommand { - - long id - Traverser.Order order - Closure stopEvaluator - Closure returnableEvaluator - -} \ No newline at end of file diff --git a/grails-plugins/neo4j/grails-app/i18n/messages.properties b/grails-plugins/neo4j/grails-app/i18n/messages.properties deleted file mode 100644 index e69de29bb..000000000 diff --git a/grails-plugins/neo4j/grails-app/views/error.gsp b/grails-plugins/neo4j/grails-app/views/error.gsp deleted file mode 100644 index cfc512a99..000000000 --- a/grails-plugins/neo4j/grails-app/views/error.gsp +++ /dev/null @@ -1,54 +0,0 @@ - - - Grails Runtime Exception - - - - -

    Grails Runtime Exception

    -

    Error Details

    - -
    - Error ${request.'javax.servlet.error.status_code'}: ${request.'javax.servlet.error.message'.encodeAsHTML()}
    - Servlet: ${request.'javax.servlet.error.servlet_name'}
    - URI: ${request.'javax.servlet.error.request_uri'}
    - - Exception Message: ${exception.message?.encodeAsHTML()}
    - Caused by: ${exception.cause?.message?.encodeAsHTML()}
    - Class: ${exception.className}
    - At Line: [${exception.lineNumber}]
    - Code Snippet:
    -
    - - ${cs?.encodeAsHTML()}
    -
    -
    -
    -
    - -

    Stack Trace

    -
    -
    ${it.encodeAsHTML()}
    -
    -
    - - \ No newline at end of file diff --git a/grails-plugins/neo4j/grails-app/views/neo4j/_nav.gsp b/grails-plugins/neo4j/grails-app/views/neo4j/_nav.gsp deleted file mode 100644 index 16a634595..000000000 --- a/grails-plugins/neo4j/grails-app/views/neo4j/_nav.gsp +++ /dev/null @@ -1,9 +0,0 @@ - diff --git a/grails-plugins/neo4j/grails-app/views/neo4j/domain.gsp b/grails-plugins/neo4j/grails-app/views/neo4j/domain.gsp deleted file mode 100644 index 2d73131f9..000000000 --- a/grails-plugins/neo4j/grails-app/views/neo4j/domain.gsp +++ /dev/null @@ -1,93 +0,0 @@ - - - domain structure - - - - function toogleCheckboxes(name, value) { - $("input[name=" + name + "]").each(function () { - this.checked = value; - }) - }; - - - - - - -
    - -

    Filtering

    - - - - - - - - - - -
    Property types (display any of these) - - ${it}
    -
    -
    - all
    - none -
    Domain classes - - ${dc.name}
    -
    -
    - all
    - none -
    - -
    -
    - -

    List of domain classes persisted via Neo4j

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    classnametypeassocbidihasOnemanyToManymanyToOneoneToManyoneToOneowningcircularrefNamerefTyperefDomCl
    ${p.domainClass.name}${p.name}${grails.util.GrailsNameUtils.getShortName(p.type.name)}${p.association}${p.bidirectional}${p.hasOne}${p.manyToMany}${p.manyToOne}${p.oneToMany}${p.oneToOne}${p.owningSide}${p.circular}${p.referencedPropertyName}${grails.util.GrailsNameUtils.getShortName(p.referencedPropertyType)}${p.referencedDomainClass}
    - -
    - - \ No newline at end of file diff --git a/grails-plugins/neo4j/grails-app/views/neo4j/fixDoubleRelationShips.gsp b/grails-plugins/neo4j/grails-app/views/neo4j/fixDoubleRelationShips.gsp deleted file mode 100644 index 39687bd52..000000000 --- a/grails-plugins/neo4j/grails-app/views/neo4j/fixDoubleRelationShips.gsp +++ /dev/null @@ -1,25 +0,0 @@ - - - Neo4j Statistics - - - - - - -
    -

    Counters

    - # removed relationships: ${removed} - - <%-- - - - - - - -
    ${item.key}${item.value}
    --%> - -
    - - \ No newline at end of file diff --git a/grails-plugins/neo4j/grails-app/views/neo4j/node.gsp b/grails-plugins/neo4j/grails-app/views/neo4j/node.gsp deleted file mode 100644 index 24fb4c3bb..000000000 --- a/grails-plugins/neo4j/grails-app/views/neo4j/node.gsp +++ /dev/null @@ -1,40 +0,0 @@ - - - explore node space - - - - - - -
    -

    Showing node (${node.id})

    -

    Node properties

    - - - - - - - - - -
    property nameproperty valuevalue type
    ${it}${node.getProperty(it)}${node.getProperty(it)?.getClass().name}
    -

    Relationships

    - - - - - - - - - - - - - -
    idtypepropertiesdirectiontarget
    ${rel.id}${rel.type.name()}${prop} = ${rel.getProperty(prop)}
    ${other}
    -
    - - diff --git a/grails-plugins/neo4j/grails-app/views/neo4j/relationship.gsp b/grails-plugins/neo4j/grails-app/views/neo4j/relationship.gsp deleted file mode 100644 index 79af475c8..000000000 --- a/grails-plugins/neo4j/grails-app/views/neo4j/relationship.gsp +++ /dev/null @@ -1,35 +0,0 @@ - - - explore node space - - - - - - -
    -

    Showing relationship (${rel.id})

    - - - - - - - - - -
    start node:${rel.startNode.id} (type: ${rel.startNode.getProperty("type","n/a")})
    end node:${rel.endNode.id} (type: ${rel.endNode.getProperty("type","n/a")})
    -

    properties

    - - - - - - - - - -
    property nameproperty valuevalue type
    ${it}${rel.getProperty(it)}${rel.getProperty(it)?.getClass().name}
    -
    - - diff --git a/grails-plugins/neo4j/grails-app/views/neo4j/statistics.gsp b/grails-plugins/neo4j/grails-app/views/neo4j/statistics.gsp deleted file mode 100644 index 806b56afe..000000000 --- a/grails-plugins/neo4j/grails-app/views/neo4j/statistics.gsp +++ /dev/null @@ -1,44 +0,0 @@ - - - Neo4j Statistics - - - - - - - - -
    -

    Counters

    - -

    Nodes

    - - - - - - - - - - - -
    ${item.key}${item.value}
    sum:${typeCounter.values().sum()}
    -

    Relationships

    - - - - - - - - - - - -
    ${item.key}${item.value}
    sum:${reltypeCounter.values().sum()}
    - -
    - - \ No newline at end of file diff --git a/grails-plugins/neo4j/grails-app/views/neo4j/traverse.gsp b/grails-plugins/neo4j/grails-app/views/neo4j/traverse.gsp deleted file mode 100644 index 93781d89c..000000000 --- a/grails-plugins/neo4j/grails-app/views/neo4j/traverse.gsp +++ /dev/null @@ -1,42 +0,0 @@ -<%@ page contentType="text/html;charset=UTF-8" %> - - - Simple GSP page - - - - - - -
    ${flash.message}
    -
    - -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - -
    Node (id)
    Traverseorder
    Stopevaluator
    ReturnableEvaluator
    - -
    - - diff --git a/grails-plugins/neo4j/neo4j.ipr b/grails-plugins/neo4j/neo4j.ipr deleted file mode 100644 index 5356f401f..000000000 --- a/grails-plugins/neo4j/neo4j.ipr +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - http://www.w3.org/1999/xhtml - - - - - - - - - - - - 1.6 - - - - - - - - - diff --git a/grails-plugins/neo4j/scripts/_Install.groovy b/grails-plugins/neo4j/scripts/_Install.groovy deleted file mode 100644 index a21216087..000000000 --- a/grails-plugins/neo4j/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/neo4j/scripts/_Uninstall.groovy b/grails-plugins/neo4j/scripts/_Uninstall.groovy deleted file mode 100644 index 7c5316914..000000000 --- a/grails-plugins/neo4j/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/neo4j/scripts/_Upgrade.groovy b/grails-plugins/neo4j/scripts/_Upgrade.groovy deleted file mode 100644 index 6a1a4c925..000000000 --- a/grails-plugins/neo4j/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/neo4j/test/functional/GebConfig.groovy b/grails-plugins/neo4j/test/functional/GebConfig.groovy deleted file mode 100644 index 3c9a56949..000000000 --- a/grails-plugins/neo4j/test/functional/GebConfig.groovy +++ /dev/null @@ -1,38 +0,0 @@ -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.firefox.FirefoxDriver -//import org.openqa.selenium.htmlunit.HtmlUnitDriver -import org.openqa.selenium.phantomjs.PhantomJSDriver -import org.openqa.selenium.remote.DesiredCapabilities - -/* - This is the Geb configuration file. - - See: http://www.gebish.org/manual/current/configuration.html -*/ - - -// Use htmlunit as the default -// See: http://code.google.com/p/selenium/wiki/HtmlUnitDriver -//driver = { -// def driver = new HtmlUnitDriver() -// driver.javascriptEnabled = true -// driver -//} - -driver = { new PhantomJSDriver(new DesiredCapabilities()) } - -environments { - - // run as “grails -Dgeb.env=chrome test-app” - // See: http://code.google.com/p/selenium/wiki/ChromeDriver - chrome { - driver = { new ChromeDriver() } - } - - // run as “grails -Dgeb.env=firefox test-app” - // See: http://code.google.com/p/selenium/wiki/FirefoxDriver - firefox { - driver = { new FirefoxDriver() } - } - -} \ No newline at end of file diff --git a/grails-plugins/neo4j/test/functional/org/grails/datastore/gorm/neo4j/Neo4jControllerSpec.groovy b/grails-plugins/neo4j/test/functional/org/grails/datastore/gorm/neo4j/Neo4jControllerSpec.groovy deleted file mode 100644 index 12ce024c0..000000000 --- a/grails-plugins/neo4j/test/functional/org/grails/datastore/gorm/neo4j/Neo4jControllerSpec.groovy +++ /dev/null @@ -1,26 +0,0 @@ -package org.grails.datastore.gorm.neo4j - -import geb.spock.GebReportingSpec -import org.grails.datastore.gorm.neo4j.pages.Neo4jPage -import org.grails.datastore.gorm.neo4j.pages.Neo4jPageForward -import spock.lang.Stepwise - - -@Stepwise -class Neo4jControllerSpec extends GebReportingSpec { - - def "navigating nodes"() { - when: - to Neo4jPage - then: - true - } - - def "forwards work"() { - when: - to Neo4jPageForward - then: - true - } - -} diff --git a/grails-plugins/neo4j/test/functional/org/grails/datastore/gorm/neo4j/pages/Neo4jPage.groovy b/grails-plugins/neo4j/test/functional/org/grails/datastore/gorm/neo4j/pages/Neo4jPage.groovy deleted file mode 100644 index 2e1b2895a..000000000 --- a/grails-plugins/neo4j/test/functional/org/grails/datastore/gorm/neo4j/pages/Neo4jPage.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package org.grails.datastore.gorm.neo4j.pages - -import geb.Page - -/** - * Created with IntelliJ IDEA. - * User: stefan - * Date: 01.05.13 - * Time: 19:11 - * To change this template use File | Settings | File Templates. - */ -class Neo4jPage extends Page { - static content = { - heading { $("h1") } - message { $("div.message").text() } - } - static url = "neo4j" - - static at = { - title ==~ /explore node space/ - - } - -} diff --git a/grails-plugins/neo4j/test/functional/org/grails/datastore/gorm/neo4j/pages/Neo4jPageForward.groovy b/grails-plugins/neo4j/test/functional/org/grails/datastore/gorm/neo4j/pages/Neo4jPageForward.groovy deleted file mode 100644 index 99f8e9806..000000000 --- a/grails-plugins/neo4j/test/functional/org/grails/datastore/gorm/neo4j/pages/Neo4jPageForward.groovy +++ /dev/null @@ -1,5 +0,0 @@ -package org.grails.datastore.gorm.neo4j.pages - -class Neo4jPageForward extends Neo4jPage { - static url = "neo4j/doforward" -} 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 deleted file mode 100644 index 3ac3aa972..000000000 --- a/grails-plugins/neo4j/test/integration/org/grails/datastore/gorm/neo4j/GetOrSetSpec.groovy +++ /dev/null @@ -1,69 +0,0 @@ -package org.grails.datastore.gorm.neo4j - -import grails.converters.JSON -import grails.plugin.spock.IntegrationSpec -import org.codehaus.groovy.grails.web.json.JSONElement -import org.neo4j.graphdb.DynamicRelationshipType -import org.neo4j.graphdb.GraphDatabaseService - -class GetOrSetSpec extends IntegrationSpec { - - GraphDatabaseService graphDatabaseService - - def "test getOrSet method on nodes"() { - setup: - def node = graphDatabaseService.createNode() - - when: 'setting a property' - node."$propertyName" = propertyValue - - then: 'retrieving the property' - node."$propertyName" == propertyValue - - where: - propertyName | propertyValue - 'name' | 'abc' - 'createdDate' | new Date() - 'count' | 5 - 'price' | 2.12f - } - - def "marshalling test for nodes"() { - when: - def n = graphDatabaseService.createNode() - n.setProperty('myproperty', 'myvalue') - def json = marshalAsJSON(n) - - - then: - json.id == n.id - json.myproperty == 'myvalue' - json.relationships == [] - - } - - def "marshalling test for relationship"() { - when: - def startNode = graphDatabaseService.createNode() - startNode.setProperty('myproperty', 'startnode') - def endNode = graphDatabaseService.createNode() - endNode.setProperty('myproperty', 'endnode') - def rel = startNode.createRelationshipTo(endNode, DynamicRelationshipType.withName('RELTYPE')) - rel.setProperty('myproperty', 'rel') - def json = marshalAsJSON(rel) - - then: - json.id == rel.id - json.myproperty == 'rel' - json.startNode == startNode.id - json.endNode == endNode.id - json.type == 'RELTYPE' - - } - - private JSONElement marshalAsJSON(object) { - def sw = new StringWriter() - (object as JSON).render(sw) - JSON.parse(sw.toString()) - } -} diff --git a/grails-plugins/redis/.classpath b/grails-plugins/redis/.classpath deleted file mode 100644 index 27107c2b7..000000000 --- a/grails-plugins/redis/.classpath +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/grails-plugins/redis/.gitignore b/grails-plugins/redis/.gitignore deleted file mode 100644 index 629f9a463..000000000 --- a/grails-plugins/redis/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -grails-redis*.zip -plugin.xml diff --git a/grails-plugins/redis/.project b/grails-plugins/redis/.project deleted file mode 100644 index 2194bf0c5..000000000 --- a/grails-plugins/redis/.project +++ /dev/null @@ -1,32 +0,0 @@ - - - redis - - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.grails.ide.eclipse.core.nature - org.eclipse.jdt.groovy.core.groovyNature - org.eclipse.jdt.core.javanature - org.eclipse.wst.common.project.facet.core.nature - - - - .link_to_grails_plugins - 2 - /home/burt/workspace.nosql/grails-data-mapping/grails-plugins/redis/target/plugins - - - diff --git a/grails-plugins/redis/.settings/org.codehaus.groovy.eclipse.preferences.prefs b/grails-plugins/redis/.settings/org.codehaus.groovy.eclipse.preferences.prefs deleted file mode 100644 index bf339c77a..000000000 --- a/grails-plugins/redis/.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/redis/LICENSE b/grails-plugins/redis/LICENSE deleted file mode 100644 index de401aa99..000000000 --- a/grails-plugins/redis/LICENSE +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (C) 2010 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. - */ diff --git a/grails-plugins/redis/RedisGormGrailsPlugin.groovy b/grails-plugins/redis/RedisGormGrailsPlugin.groovy deleted file mode 100644 index 62e0dbd87..000000000 --- a/grails-plugins/redis/RedisGormGrailsPlugin.groovy +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (C) 2010 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. - */ - -import org.grails.datastore.gorm.plugin.support.ApplicationContextConfigurer -import org.grails.datastore.gorm.redis.plugin.support.RedisMethodsConfigurer -import org.grails.datastore.gorm.redis.plugin.support.RedisOnChangeHandler -import org.grails.datastore.gorm.redis.plugin.support.RedisSpringConfigurer - -class RedisGormGrailsPlugin { - 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/GPREDIS" ] - def scm = [ url: "https://github.com/SpringSource/grails-data-mapping" ] - - def version = "1.0.0.M8" - def grailsVersion = "1.3.4 > *" - def loadAfter = ['domainClass', 'hibernate', 'services', 'cloudFoundry'] - def observe = ['services', 'domainClass'] - - def author = "Graeme Rocher" - def authorEmail = "graeme.rocher@springsource.com" - def title = "Redis GORM" - def description = 'A plugin that integrates the Redis key/value datastore into Grails, providing a GORM-like API onto it' - - def pluginExcludes = [ - "grails-app/domain/*.groovy", - "grails-app/services/*.groovy", - "grails-app/controllers/*.groovy" - ] - - def documentation = "http://grails.org/plugin/redis-gorm" - - def doWithSpring = new RedisSpringConfigurer().getConfiguration() - - def doWithDynamicMethods = { ctx -> - def datastore = ctx.redisDatastore - def transactionManager = ctx.redisDatastoreTransactionManager - def methodsConfigurer = new RedisMethodsConfigurer(datastore, transactionManager) - methodsConfigurer.hasExistingDatastore = manager.hasGrailsPlugin("hibernate") - def foe = application?.config?.grails?.gorm?.failOnError - methodsConfigurer.failOnError = foe instanceof Boolean ? foe : false - methodsConfigurer.configure() - } - - def doWithApplicationContext = { ctx -> - new ApplicationContextConfigurer("Redis").configure(ctx) - } - - def onChange = { event -> - if(event.ctx) { - new RedisOnChangeHandler(event.ctx.redisDatastore, event.ctx.redisDatastoreTransactionManager).onChange(delegate, event) - } - } -} diff --git a/grails-plugins/redis/application.properties b/grails-plugins/redis/application.properties deleted file mode 100644 index e151936c6..000000000 --- a/grails-plugins/redis/application.properties +++ /dev/null @@ -1 +0,0 @@ -app.grails.version=2.0.4 diff --git a/grails-plugins/redis/build.gradle b/grails-plugins/redis/build.gradle deleted file mode 100644 index 581f59bb3..000000000 --- a/grails-plugins/redis/build.gradle +++ /dev/null @@ -1,43 +0,0 @@ -buildscript { - - repositories { - mavenCentral() - mavenRepo urls: "http://repo.grails.org/grails/core" - } - - dependencies { - classpath "org.grails:grails-gradle-plugin:1.0", - "org.grails:grails-bootstrap:1.3.4" - } -} - -apply plugin: "grails" - -grailsVersion = "1.3.4" - -repositories { - flatDir dirs: "lib" -} - -configurations { - compile.exclude module: "commons-logging" - compile.exclude module: 'xml-apis' -} - -repositories { - mavenRepo urls:"http://repository.codehaus.org/" -} - -dependencies { - compile project(":grails-datastore-core"), - project(":grails-datastore-redis"), - project(":grails-datastore-gorm"), - project(":grails-datastore-gorm-redis") - - runtime "org.aspectj:aspectjrt:1.6.8" - runtime "org.slf4j:slf4j-simple:1.5.8", - "hsqldb:hsqldb:1.8.0.5", - "net.sf.ehcache:ehcache-core:1.7.1" - compile "org.grails:grails-crud:$grailsVersion", - "org.grails:grails-gorm:$grailsVersion" -} diff --git a/grails-plugins/redis/grails-app/conf/BuildConfig.groovy b/grails-plugins/redis/grails-app/conf/BuildConfig.groovy deleted file mode 100644 index 43964bd64..000000000 --- a/grails-plugins/redis/grails-app/conf/BuildConfig.groovy +++ /dev/null @@ -1,49 +0,0 @@ -grails.project.work.dir = 'target' -grails.project.source.level = 1.6 - -grails.project.dependency.resolution = { - - inherits("global") { - excludes 'xml-apis', 'netty' - } - log 'warn' - - repositories { - grailsCentral() - mavenLocal() - mavenCentral() - } - - dependencies { - def excludes = { - excludes "slf4j-simple", "persistence-api", "commons-logging", "jcl-over-slf4j", "slf4j-api", "jta" - excludes "spring-core", "spring-beans", "spring-aop", "spring-asm","spring-webmvc","spring-tx", "spring-context", "spring-web", "log4j", "slf4j-log4j12" - excludes group:"org.grails", name:'grails-core' - excludes group:"org.grails", name:'grails-gorm' - excludes group:"org.grails", name:'grails-test' - transitive = false - } - - def datastoreVersion = "1.0.0.RELEASE" - def redisDatastoreVersion = "1.0.0.M8" - - compile 'redis.clients:jedis:2.0.0' - - compile("org.grails:grails-datastore-gorm-redis:$redisDatastoreVersion", - "org.grails:grails-datastore-redis:$redisDatastoreVersion", excludes) - - compile("org.grails:grails-datastore-gorm-plugin-support:$datastoreVersion", - "org.grails:grails-datastore-gorm:$datastoreVersion", - "org.grails:grails-datastore-core:$datastoreVersion", - "org.grails:grails-datastore-web:$datastoreVersion", excludes) - - test("org.grails:grails-datastore-gorm-test:$datastoreVersion", - "org.grails:grails-datastore-simple:$datastoreVersion", excludes) - } - - plugins { - build(':release:2.2.0', ':rest-client-builder:1.0.3') { - export = false - } - } -} diff --git a/grails-plugins/redis/grails-app/conf/Config.groovy b/grails-plugins/redis/grails-app/conf/Config.groovy deleted file mode 100644 index d53923251..000000000 --- a/grails-plugins/redis/grails-app/conf/Config.groovy +++ /dev/null @@ -1,26 +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' -} -grails.views.default.codec="none" // none, html, base64 -grails.views.gsp.encoding="UTF-8" diff --git a/grails-plugins/redis/grails-app/conf/DataSource.groovy b/grails-plugins/redis/grails-app/conf/DataSource.groovy deleted file mode 100644 index 91143e70f..000000000 --- a/grails-plugins/redis/grails-app/conf/DataSource.groovy +++ /dev/null @@ -1,32 +0,0 @@ -dataSource { - pooled = true - driverClassName = "org.hsqldb.jdbcDriver" - 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:hsqldb:mem:devDB" - } - } - test { - dataSource { - dbCreate = "update" - url = "jdbc:hsqldb:mem:testDb" - } - } - production { - dataSource { - dbCreate = "update" - url = "jdbc:hsqldb:file:prodDb;shutdown=true" - } - } -} diff --git a/grails-plugins/redis/scripts/_Install.groovy b/grails-plugins/redis/scripts/_Install.groovy deleted file mode 100644 index a21216087..000000000 --- a/grails-plugins/redis/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/redis/scripts/_Uninstall.groovy b/grails-plugins/redis/scripts/_Uninstall.groovy deleted file mode 100644 index 7c5316914..000000000 --- a/grails-plugins/redis/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/redis/scripts/_Upgrade.groovy b/grails-plugins/redis/scripts/_Upgrade.groovy deleted file mode 100644 index 6a1a4c925..000000000 --- a/grails-plugins/redis/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/rest-client/GormRestClientGrailsPlugin.groovy b/grails-plugins/rest-client/GormRestClientGrailsPlugin.groovy deleted file mode 100644 index f11536d2a..000000000 --- a/grails-plugins/rest-client/GormRestClientGrailsPlugin.groovy +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (C) 2013 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. - */ -import org.grails.datastore.gorm.rest.client.plugin.support.* - -/** - * @author Graeme Rocher - */ -class GormRestClientGrailsPlugin { - // the plugin version - def version = "1.0.0.M1" - // the version or versions of Grails the plugin is designed for - def grailsVersion = "2.3 > *" - // resources that are excluded from plugin packaging - def pluginExcludes = [ - "grails-app/views/error.gsp" - ] - - def title = "GORM Rest Client Plugin" // Headline display name of the plugin - def author = "Graeme Rocher" - def authorEmail = "graeme.rocher@gmail.com" - def description = '''\ -A GORM implementation that can back onto a REST web service -''' - - // URL to the plugin's documentation - def documentation = "http://projects.spring.io/grails-data-mapping/rest-client/manual/index.html" - - // Extra (optional) plugin metadata - - // License: one of 'APACHE', 'GPL2', 'GPL3' - def license = "APACHE" - - // Details of company behind the plugin (if there is one) - def organization = [ name: "SpringSource", url: "http://www.springsource.com/" ] - - // Any additional developers beyond the author specified above. - def developers = [ [ name: "Graeme Rocher", email: "graeme.rocher@gmail.com" ]] - - // Location of the plugin's issue tracker. - def issueManagement = [ system: "JIRA", url: "http://jira.grails.org/browse/GRAILS" ] - - // Online location of the plugin's browseable source code. - def scm = [ url: "https://github.com/SpringSource/grails-data-mapping" ] - - def doWithSpring = new RestClientSpringConfigurer().getConfiguration() - - def doWithDynamicMethods = { ctx -> - def datastore = ctx.getBean("restclientDatastore") - def transactionManager = ctx.getBean("restclientTransactionManager") - def methodsConfigurer = new RestClientMethodsConfigurer(datastore, transactionManager) - methodsConfigurer.hasExistingDatastore = manager.hasGrailsPlugin("hibernate") - def foe = application?.config?.grails?.gorm?.failOnError - methodsConfigurer.failOnError = foe instanceof Boolean ? foe : false - methodsConfigurer.configure() - } -} diff --git a/grails-plugins/rest-client/application.properties b/grails-plugins/rest-client/application.properties deleted file mode 100644 index b412db9fb..000000000 --- a/grails-plugins/rest-client/application.properties +++ /dev/null @@ -1,4 +0,0 @@ -#Grails Metadata file -#Tue Aug 27 15:15:35 CEST 2013 -app.grails.version=2.3.0 -app.name=gorm-rest-client diff --git a/grails-plugins/rest-client/grails-app/conf/BuildConfig.groovy b/grails-plugins/rest-client/grails-app/conf/BuildConfig.groovy deleted file mode 100644 index 755dc8df1..000000000 --- a/grails-plugins/rest-client/grails-app/conf/BuildConfig.groovy +++ /dev/null @@ -1,69 +0,0 @@ -grails.project.class.dir = "target/classes" -grails.project.test.class.dir = "target/test-classes" -grails.project.test.reports.dir = "target/test-reports" -grails.project.work.dir="target/work" - -grails.project.fork = [ - // configure settings for compilation JVM, note that if you alter the Groovy version forked compilation is required - // compile: [maxMemory: 256, minMemory: 64, debug: false, maxPerm: 256, daemon:true], - - // configure settings for the test-app JVM, uses the daemon by default - test: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, daemon:true], - // configure settings for the run-app JVM - run: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false], - // configure settings for the run-war JVM - war: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false], - // configure settings for the Console UI JVM - console: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256] -] - -grails.project.dependency.resolver = "maven" // or ivy -grails.project.dependency.resolution = { - // inherit Grails' default dependencies - inherits("global") { - // uncomment to disable ehcache - // excludes 'ehcache' - } - log "warn" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose' - repositories { - grailsCentral() - mavenLocal() - mavenCentral() - // uncomment the below to enable remote dependency resolution - // from public Maven repositories - //mavenRepo "http://repository.codehaus.org" - //mavenRepo "http://download.java.net/maven/2/" - //mavenRepo "http://repository.jboss.com/maven2/" - } - dependencies { - def excludes = { - excludes "slf4j-simple", "persistence-api", "commons-logging", "jcl-over-slf4j", "slf4j-api", "jta" - excludes "spring-core", "spring-beans", "spring-aop", "spring-asm","spring-webmvc","spring-tx", "spring-context", "spring-web", "log4j", "slf4j-log4j12" - excludes group:"org.grails", name:'grails-core' - excludes group:"org.grails", name:'grails-gorm' - excludes group:"org.grails", name:'grails-test' - excludes group:'xml-apis', name:'xml-apis' - excludes 'ehcache-core' - transitive = false - } - - - def datastoreVersion = "2.0.1.RELEASE" - - compile ("org.grails:grails-datastore-rest-client:1.0.0.M2", - "org.grails:grails-datastore-gorm-rest-client:1.0.0.M1",excludes) - compile("org.grails:grails-datastore-gorm-plugin-support:$datastoreVersion", - "org.grails:grails-datastore-gorm:$datastoreVersion", - "org.grails:grails-datastore-core:$datastoreVersion", - "org.grails:grails-datastore-web:$datastoreVersion",excludes) - - runtime 'org.javassist:javassist:3.16.1-GA' - } - - plugins { - build(":release:3.0.0", - ":rest-client-builder:1.0.3") { - export = false - } - } -} diff --git a/grails-plugins/riak/RiakGrailsPlugin.groovy b/grails-plugins/riak/RiakGrailsPlugin.groovy deleted file mode 100644 index 58527a533..000000000 --- a/grails-plugins/riak/RiakGrailsPlugin.groovy +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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. - */ - - -import org.springframework.data.keyvalue.riak.groovy.RiakBuilder -import org.grails.datastore.gorm.plugin.support.ApplicationContextConfigurer -import org.grails.datastore.gorm.riak.plugin.support.* - - -class RiakGrailsPlugin { - def version = "1.0.0.M4" - def grailsVersion = "1.3.7 > *" - def author = "Jon Brisbin" - def authorEmail = "jbrisbin@vmware.com" - def title = "Riak GORM" - def description = '''\\ -A plugin that integrates the Riak document/data store into Grails. -''' - - def observe = ['controllers', 'services', 'domainClass'] - - def documentation = "http://grails.org/plugin/riak" - - def doWithSpring = new RiakSpringConfigurer().getConfiguration() - - def doWithDynamicMethods = { ctx -> - def datastore = ctx.riakDatastore - def transactionManager = ctx.riakDatastoreTransactionManager - def methodsConfigurer = new RiakMethodsConfigurer(datastore, transactionManager) - methodsConfigurer.hasExistingDatastore = manager.hasGrailsPlugin("hibernate") - def foe = application?.config?.grails?.gorm?.failOnError - methodsConfigurer.failOnError = foe instanceof Boolean ? foe : false - methodsConfigurer.configure() - configureRiak(application, ctx) - } - - def doWithApplicationContext = { ctx -> - new ApplicationContextConfigurer("Riak").configure(ctx) - } - - def onChange = { event -> - if(event.ctx) { - new RiakOnChangeHandler(event.ctx.redisDatastore, event.ctx.redisDatastoreTransactionManager).onChange(delegate, event) - } - - configureRiak(event.application, event.ctx) - } - - def configureRiak(app, ctx) { - - app.controllerClasses.each { - it.metaClass.riak = { Closure cl -> doWithRiak(ctx, cl) } - } - app.serviceClasses.each { - it.metaClass.riak = { Closure cl -> doWithRiak(ctx, cl) } - } - } - - def doWithRiak(ctx, cl) { - def riak = new RiakBuilder(ctx.asyncRiakTemplate) - cl.delegate = riak - cl.resolveStrategy = Closure.DELEGATE_FIRST - cl.call() - return riak - } -} diff --git a/grails-plugins/riak/application.properties b/grails-plugins/riak/application.properties deleted file mode 100644 index 2a662db36..000000000 --- a/grails-plugins/riak/application.properties +++ /dev/null @@ -1,5 +0,0 @@ -#Grails Metadata file -#Wed Dec 14 14:35:17 CET 2011 -app.grails.version=2.0.0 -app.name=riak -plugins.svn=1.0.1 diff --git a/grails-plugins/riak/build.gradle b/grails-plugins/riak/build.gradle deleted file mode 100644 index 64e40f51e..000000000 --- a/grails-plugins/riak/build.gradle +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2010 by J. Brisbin - * Portions (c) 2010 by NPC International, Inc. or the - * original author(s). - * - * 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. - */ - -buildscript { - repositories { - mavenCentral() - mavenRepo urls: "http://repository.jboss.org/maven2/" - } - dependencies { - classpath "org.grails:grails-gradle-plugin:1.0", "org.grails:grails-bootstrap:1.3.6" - } -} - -apply plugin: "grails" - -grailsVersion = "1.3.6" - -repositories { - flatDir dirs: "lib" -} - -configurations { - compile.exclude module: "commons-logging" - compile.exclude module: 'xml-apis' -} - -repositories { - mavenRepo urls: "http://repository.codehaus.org/" -} - -dependencies { - compile project(":grails-datastore-core"), - project(":grails-datastore-riak"), - project(":grails-datastore-gorm"), - project(":grails-datastore-gorm-riak") - - runtime "org.aspectj:aspectjrt:1.6.8" - runtime "org.slf4j:slf4j-simple:1.5.8", - "hsqldb:hsqldb:1.8.0.5", - "net.sf.ehcache:ehcache-core:1.7.1" - runtime 'org.codehaus.jackson:jackson-core-asl:1.6.1', - 'org.codehaus.jackson:jackson-mapper-asl:1.6.1', - 'org.springframework.data:spring-data-riak:1.0.0.M2-SNAPSHOT' - - compile "org.grails:grails-crud:1.3.6", - "org.grails:grails-gorm:1.3.6" -} \ No newline at end of file diff --git a/grails-plugins/riak/grails-app/conf/BuildConfig.groovy b/grails-plugins/riak/grails-app/conf/BuildConfig.groovy deleted file mode 100644 index 9223c5b54..000000000 --- a/grails-plugins/riak/grails-app/conf/BuildConfig.groovy +++ /dev/null @@ -1,54 +0,0 @@ -grails.project.class.dir = "target/classes" -grails.project.test.class.dir = "target/test-classes" -grails.project.test.reports.dir = "target/test-reports" - -grails.project.dependency.resolution = { - - inherits "global" - - log "warn" - - repositories { - mavenRepo "http://repo.grails.org/grails/core" - grailsCentral() - } - - dependencies { - - def excludes = { - excludes "slf4j-simple", "persistence-api", "commons-logging", "jcl-over-slf4j", "slf4j-api", "jta" - excludes "spring-core", "spring-beans", "spring-aop", "spring-asm","spring-webmvc","spring-tx", "spring-context", "spring-web", "log4j", "slf4j-log4j12" - excludes group:"org.grails", name:'grails-core' - excludes group:"org.grails", name:'grails-gorm' - excludes group:"org.grails", name:'grails-test' - transitive = false - } - - def datastoreVersion = "1.0.0.RELEASE" - def riakDatastoreVersion = "1.0.0.RC3" - - compile( 'org.springframework.data:spring-data-riak:1.0.0.M3',excludes) - compile( 'org.springframework.data:spring-data-keyvalue-core:1.0.0.M3',excludes ) - - runtime("org.codehaus.jackson:jackson-core-asl:1.7.4",excludes) - runtime("org.codehaus.jackson:jackson-mapper-asl:1.7.4",excludes) - - compile("org.grails:grails-datastore-gorm-riak:$riakDatastoreVersion", - "org.grails:grails-datastore-riak:$riakDatastoreVersion",excludes) - - compile( - "org.grails:grails-datastore-gorm-plugin-support:$datastoreVersion", - "org.grails:grails-datastore-gorm:$datastoreVersion", - "org.grails:grails-datastore-core:$datastoreVersion", - "org.grails:grails-datastore-web:$datastoreVersion",excludes) - - test("org.grails:grails-datastore-gorm-test:$datastoreVersion", - "org.grails:grails-datastore-simple:$datastoreVersion",excludes) - } - - plugins { - build(":release:1.0.0") { - export = false - } - } -} diff --git a/grails-plugins/riak/grails-app/conf/Config.groovy b/grails-plugins/riak/grails-app/conf/Config.groovy deleted file mode 100644 index 2e57c6d88..000000000 --- a/grails-plugins/riak/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/riak/grails-app/conf/DataSource.groovy b/grails-plugins/riak/grails-app/conf/DataSource.groovy deleted file mode 100644 index 91143e70f..000000000 --- a/grails-plugins/riak/grails-app/conf/DataSource.groovy +++ /dev/null @@ -1,32 +0,0 @@ -dataSource { - pooled = true - driverClassName = "org.hsqldb.jdbcDriver" - 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:hsqldb:mem:devDB" - } - } - test { - dataSource { - dbCreate = "update" - url = "jdbc:hsqldb:mem:testDb" - } - } - production { - dataSource { - dbCreate = "update" - url = "jdbc:hsqldb:file:prodDb;shutdown=true" - } - } -} diff --git a/grails-plugins/riak/scripts/_Install.groovy b/grails-plugins/riak/scripts/_Install.groovy deleted file mode 100644 index a21216087..000000000 --- a/grails-plugins/riak/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/riak/scripts/_Uninstall.groovy b/grails-plugins/riak/scripts/_Uninstall.groovy deleted file mode 100644 index 7c5316914..000000000 --- a/grails-plugins/riak/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/riak/scripts/_Upgrade.groovy b/grails-plugins/riak/scripts/_Upgrade.groovy deleted file mode 100644 index 6a1a4c925..000000000 --- a/grails-plugins/riak/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/simpledb/SimpledbGrailsPlugin.groovy b/grails-plugins/simpledb/SimpledbGrailsPlugin.groovy deleted file mode 100644 index fef7b6404..000000000 --- a/grails-plugins/simpledb/SimpledbGrailsPlugin.groovy +++ /dev/null @@ -1,62 +0,0 @@ -import org.codehaus.groovy.grails.commons.GrailsDomainClassProperty - -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.simpledb.engine.SimpleDBDomainResolver -import org.grails.datastore.mapping.simpledb.engine.SimpleDBDomainResolverFactory -import org.grails.datastore.mapping.simpledb.engine.SimpleDBAssociationInfo -import org.grails.datastore.mapping.simpledb.util.SimpleDBTemplate -import org.grails.datastore.mapping.simpledb.util.SimpleDBConst -import org.grails.datastore.gorm.simpledb.plugin.support.SimpleDBSpringConfigurer -import org.grails.datastore.gorm.simpledb.plugin.support.SimpleDBMethodsConfigurer -import org.grails.datastore.gorm.simpledb.plugin.support.SimpleDBOnChangeHandler -import org.grails.datastore.gorm.simpledb.plugin.support.SimpleDBApplicationContextConfigurer - -class SimpledbGrailsPlugin { - def license = "Apache 2.0 License" - def scm = [ url: "https://github.com/SpringSource/grails-data-mapping" ] - def developers = [ - [ name: "Roman Stepanenko", email: "rs.opensource@gmail.com" ] ] - def version = "0.6.BUILD-SNAPSHOT" - def grailsVersion = "1.3.5 > *" - def observe = ['services', 'domainClass'] - def loadAfter = ['domainClass', 'hibernate', 'services', 'cloudFoundry'] - def dependsOn = [:] - def pluginExcludes = [ - "grails-app/views/error.gsp" - ] - - def author = "Roman Stepanenko" - def authorEmail = "rs.opensource@gmail.com" - def title = "SimpleDB GORM" - def description = 'A plugin that integrates the AWS SimpleDB datastore into Grails, providing a GORM API onto it' - - // URL to the plugin's documentation - def documentation = "http://grails.org/plugin/simpledb" - - def doWithSpring = new SimpleDBSpringConfigurer().getConfiguration() - - def doWithDynamicMethods = { ctx -> - println 'simpledb plugin: '+version - def datastore = ctx.simpledbDatastore - def transactionManager = ctx.simpledbTransactionManager - def methodsConfigurer = new SimpleDBMethodsConfigurer(datastore, transactionManager) - methodsConfigurer.hasExistingDatastore = manager.hasGrailsPlugin("hibernate") - def foe = application?.config?.grails?.gorm?.failOnError - methodsConfigurer.failOnError = foe instanceof Boolean ? foe : false - - methodsConfigurer.configure() - } - - def doWithApplicationContext = { ctx -> - new SimpleDBApplicationContextConfigurer().configure(ctx) - } - - - def onChange = { event -> - if(event.ctx) { - new SimpleDBOnChangeHandler(event.ctx.simpledbDatastore, event.ctx.simpledbTransactionManager).onChange(delegate, event) - } - } - -} diff --git a/grails-plugins/simpledb/application.properties b/grails-plugins/simpledb/application.properties deleted file mode 100644 index 7e370586f..000000000 --- a/grails-plugins/simpledb/application.properties +++ /dev/null @@ -1,4 +0,0 @@ -#Grails Metadata file -#Wed Dec 05 21:44:08 EST 2012 -app.grails.version=2.1.1 -app.name=simpledb diff --git a/grails-plugins/simpledb/grails-app/conf/BuildConfig.groovy b/grails-plugins/simpledb/grails-app/conf/BuildConfig.groovy deleted file mode 100644 index e0b71380a..000000000 --- a/grails-plugins/simpledb/grails-app/conf/BuildConfig.groovy +++ /dev/null @@ -1,69 +0,0 @@ -grails.project.class.dir = "target/classes" -grails.project.test.class.dir = "target/test-classes" -grails.project.test.reports.dir = "target/test-reports" - -grails.project.dependency.resolution = { - - inherits "global" - - log "warn" - - String simpledbVersion = "0.6.BUILD-SNAPSHOT" - //for local development and testing of the plugin: - // 1) change version in grails-data-mapping/build.gradle to an appropriate snapshot - // 2) grails-data-mapping/gradle install - // 3) specify the same snapshot version here in the line below after the comments - // 4) in your grails app BuildConfig: grails.plugin.location.'simpledb' = "C:/Source/grails-data-mapping/grails-plugins/simpledb" - // 5) in your grails app BuildConfig: enable mavenLocal() in repositories AND put it first in the list of repos - - // to publish the version of the plugin: - // change version from '0.x.BUILD-SNAPSHOT' to '0.x' in the following files: - // grails-plugins\simpledb\SimpledbGrailsPlugin.groovy - // grails-plugins\simpledb\grails-app\conf\BuildConfig.groovy - // grails-datastore-gorm-simpledb\build.gradle - // grails-datastore-simpledb\build.gradle - - // commit, publish, after release increment the version and use BUILD-SNAPSHOT and commit again - - - String datastoreVersion = "1.0.0.RELEASE" - - repositories { - grailsPlugins() - grailsHome() - grailsCentral() - mavenRepo "http://repo.grails.org/grails/core" - mavenLocal() - mavenCentral() - mavenRepo 'http://repository.codehaus.org' - } - - dependencies { - - def excludes = { - transitive = false - } - compile("org.grails:grails-datastore-gorm-simpledb:$simpledbVersion", - "org.grails:grails-datastore-gorm-plugin-support:$datastoreVersion", - "org.grails:grails-datastore-gorm:$datastoreVersion", - "org.grails:grails-datastore-core:$datastoreVersion", - "org.grails:grails-datastore-simpledb:$simpledbVersion", - "org.grails:grails-datastore-web:$datastoreVersion") { - transitive = false - } - - runtime("stax:stax:1.2.0", excludes) - runtime('com.amazonaws:aws-java-sdk:1.3.23') - - test("org.grails:grails-datastore-gorm-test:$datastoreVersion", - "org.grails:grails-datastore-simple:$datastoreVersion") { - transitive = false - } - } - - plugins { - build( ":release:2.2.0" ) { - exported = false - } - } -} diff --git a/grails-plugins/simpledb/grails-app/conf/Config.groovy b/grails-plugins/simpledb/grails-app/conf/Config.groovy deleted file mode 100644 index d53923251..000000000 --- a/grails-plugins/simpledb/grails-app/conf/Config.groovy +++ /dev/null @@ -1,26 +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' -} -grails.views.default.codec="none" // none, html, base64 -grails.views.gsp.encoding="UTF-8" diff --git a/grails-plugins/simpledb/grails-app/conf/DataSource.groovy b/grails-plugins/simpledb/grails-app/conf/DataSource.groovy deleted file mode 100644 index 91143e70f..000000000 --- a/grails-plugins/simpledb/grails-app/conf/DataSource.groovy +++ /dev/null @@ -1,32 +0,0 @@ -dataSource { - pooled = true - driverClassName = "org.hsqldb.jdbcDriver" - 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:hsqldb:mem:devDB" - } - } - test { - dataSource { - dbCreate = "update" - url = "jdbc:hsqldb:mem:testDb" - } - } - production { - dataSource { - dbCreate = "update" - url = "jdbc:hsqldb:file:prodDb;shutdown=true" - } - } -} diff --git a/grails-plugins/simpledb/scripts/_Install.groovy b/grails-plugins/simpledb/scripts/_Install.groovy deleted file mode 100644 index a21216087..000000000 --- a/grails-plugins/simpledb/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/simpledb/scripts/_Uninstall.groovy b/grails-plugins/simpledb/scripts/_Uninstall.groovy deleted file mode 100644 index 7c5316914..000000000 --- a/grails-plugins/simpledb/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/simpledb/scripts/_Upgrade.groovy b/grails-plugins/simpledb/scripts/_Upgrade.groovy deleted file mode 100644 index 6a1a4c925..000000000 --- a/grails-plugins/simpledb/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/settings.gradle b/settings.gradle deleted file mode 100644 index b7c5e8f05..000000000 --- a/settings.gradle +++ /dev/null @@ -1,57 +0,0 @@ -// Datastore Project -include "grails-datastore-core", - "grails-datastore-gemfire", - "grails-datastore-mongo", - "grails-datastore-jpa", - "grails-datastore-redis", -/* "grails-datastore-riak",*/ - "grails-datastore-simple", - "grails-datastore-web", - "grails-datastore-simpledb", - "grails-datastore-dynamodb", - 'grails-datastore-rest-client', -/* - "grails-datastore-jcr", - "grails-datastore-cassandra", -*/ - - // Documentation - 'grails-documentation-core', - 'grails-documentation-mongo', - 'grails-documentation-redis', -/* 'grails-documentation-riak',*/ - 'grails-documentation-neo4j', - 'grails-documentation-simpledb', - 'grails-documentation-dynamodb', - 'grails-documentation-rest-client', - - // Core GORM Implementation projects - 'grails-datastore-gorm', - 'grails-datastore-gorm-tck', - 'grails-datastore-gorm-test', - 'grails-datastore-gorm-plugin-support', - - // Grails Plugins -/* - 'grails-plugins:redis', - 'grails-plugins:riak', -*/ - - // GORM Implementations - 'grails-datastore-gorm-jpa', - 'grails-datastore-gorm-neo4j', - 'grails-datastore-gorm-redis', - 'grails-datastore-gorm-rest-client', - -/* 'grails-datastore-gorm-riak',*/ - 'grails-datastore-gorm-mongo', - 'grails-datastore-gorm-gemfire', - 'grails-datastore-gorm-simpledb', - 'grails-datastore-gorm-dynamodb', - 'grails-datastore-gorm-hibernate-core', - 'grails-datastore-gorm-hibernate', - 'grails-datastore-gorm-hibernate4' -/* - 'grails-datastore-gorm-jcr', - 'grails-datastore-gorm-simpledb' -*/ diff --git a/src/docs/resources/core.template b/src/docs/resources/core.template deleted file mode 100644 index 13e30a484..000000000 --- a/src/docs/resources/core.template +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - Grails Data Mapping @ GitHub - - - - Fork me on GitHub - -
    -

    GORM for NoSQL

    - - - - - - - - - - - -
    Grails Version1.3.7 and above
    AuthorGraeme Rocher
    -
    -

    Documentation

    - -

    Implementations

    -
      - ${datastores} -
    -
    - - diff --git a/src/docs/resources/datastore.template b/src/docs/resources/datastore.template deleted file mode 100644 index 4b2746bf4..000000000 --- a/src/docs/resources/datastore.template +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - GORM for ${datastore} @ GitHub - - - - Fork me on GitHub - -
    -

    GORM for ${datastore}

    - - - - - - - -
    Grails Version1.3.7 and above
    -
    -

    Documentation

    - -
    - -