diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 8dada3ed..00000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT 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/README.md b/README.md index e64c0957..272b22db 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,2 @@ # Gorm GraphQL -## An automatic GraphQL schema generator for GORM - -[![Java CI](https://github.com/grails/gorm-graphql/actions/workflows/gradle.yml/badge.svg)](https://github.com/grails/gorm-graphql/actions/workflows/gradle.yml) - -Current documentation https://grails.github.io/gorm-graphql/latest/guide/index.html - - -### Dependencies - -- [Graphql Java](https://github.com/graphql-java/graphql-java) \ No newline at end of file +grails-data-graphql (aka gorm-graphql) has been moved to grails-data-mapping as of 5.0.x per https://github.com/grails/grails-data-mapping/pull/1884 \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index caf16f53..00000000 --- a/build.gradle +++ /dev/null @@ -1,88 +0,0 @@ -buildscript { - repositories { - maven { url "https://repo.grails.org/grails/core" } - } - dependencies { - classpath "org.grails:grails-gradle-plugin:$grailsGradlePluginVersion" - classpath "org.grails.plugins:views-gradle:$viewGradleVersion" - classpath "org.grails.plugins:views-json:$viewsJsonVersion" - classpath "org.grails:grails-docs:${project.ext.properties.grailsDocsVersion ?: grailsVersion}" - classpath "io.github.gradle-nexus:publish-plugin:1.3.0" - } -} - -repositories { - mavenCentral() - maven { url "https://repo.grails.org/grails/core" } -} - -version project.projectVersion - -ext { - commonBuild = 'https://raw.githubusercontent.com/grails/grails-common-build/v2.0.1' -} - -subprojects { - - version project.projectVersion - - ext { - userOrg = "grails" - isGrailsPlugin = name.startsWith('grails-plugin') - isBuildSnapshot = version.toString().endsWith("-SNAPSHOT") - } - - repositories { - maven { url "https://repo.grails.org/grails/core" } - } - - tasks.withType(GroovyCompile).configureEach { - configure(groovyOptions) { - forkOptions.jvmArgs = ['-Xmx1024m'] - } - } - - tasks.withType(Test).configureEach { - testLogging { - events "failed" - exceptionFormat "full" - showStandardStreams true - } - } - - if (project.name.startsWith("examples-")) { - if (project.name.startsWith("examples-grails-")) { - apply plugin: "org.grails.grails-web" - } - return - } - - if (isGrailsPlugin) { - group "org.grails.plugins" - } else { - group "org.grails" - } - - if (isGrailsPlugin) { - apply plugin: 'groovy' - apply plugin: 'eclipse' - apply plugin: 'idea' - apply plugin: 'java-library' - apply plugin: "org.grails.grails-plugin" - - sourceCompatibility = 1.11 - targetCompatibility = 1.11 - } else { - apply from: "${commonBuild}/common-project.gradle" - } - - dependencies { - implementation "com.graphql-java:graphql-java:$graphqlJavaVersion" - testImplementation "org.codehaus.groovy:groovy-test:$groovyVersion" - testImplementation "io.projectreactor:reactor-test:3.6.1" - testImplementation("org.spockframework:spock-core:$spockVersion") - implementation 'org.grails:grails-datastore-gorm:7.3.4' - } -} - -apply from: "${commonBuild}/common-publishing.gradle" diff --git a/core/build.gradle b/core/build.gradle deleted file mode 100644 index 5751f98f..00000000 --- a/core/build.gradle +++ /dev/null @@ -1,45 +0,0 @@ -repositories { - mavenCentral() - maven { url "https://repo.grails.org/grails/core" } -} -apply plugin: 'codenarc' - -dependencies { - documentation "org.codehaus.groovy:groovy-cli-picocli:$groovyVersion" - - api "org.grails:grails-datastore-gorm:${gormVersion}" - api "com.graphql-java:graphql-java:$graphqlJavaVersion" - api "com.graphql-java:graphql-java-extended-scalars:$graphqlJavaScalarExtVersion" - api 'com.github.javaparser:javaparser-core:3.25.7' - api "org.grails.plugins:views-json:2.3.2" - api 'org.javassist:javassist:3.29.2-GA' - - codenarc "org.codenarc:CodeNarc:$codenarcVersion" - - testImplementation "org.grails:grails-datastore-gorm-hibernate5:${gormHibernateVersion}" - testImplementation "org.grails:grails-datastore-gorm-mongodb:${gormMongoDbVersion}" - testImplementation 'com.github.fakemongo:fongo:2.1.1' - testImplementation 'com.h2database:h2:2.2.224' - testImplementation "org.apache.tomcat:tomcat-jdbc:8.5.97" - testImplementation "org.apache.tomcat.embed:tomcat-embed-logging-log4j:8.5.2" - testImplementation "org.slf4j:slf4j-api:$slf4jVersion" -} - -targetCompatibility = 1.8 -sourceCompatibility = 1.8 - -codenarc { - toolVersion = codenarcVersion - configFile = file("${projectDir}/config/codenarc/rules.groovy") - maxPriority1Violations = 0 - maxPriority2Violations = 0 - maxPriority3Violations = 0 -} - -codenarcMain { - exclude '**/CustomScalars.groovy' -} - -codenarcTest { - ignoreFailures = true -} diff --git a/core/config/codenarc/rules.groovy b/core/config/codenarc/rules.groovy deleted file mode 100644 index 6afd8400..00000000 --- a/core/config/codenarc/rules.groovy +++ /dev/null @@ -1,376 +0,0 @@ -ruleset { - - // rulesets/basic.xml - AssertWithinFinallyBlock - AssignmentInConditional - BigDecimalInstantiation - BitwiseOperatorInConditional - BooleanGetBoolean - BrokenNullCheck - BrokenOddnessCheck - ClassForName - ComparisonOfTwoConstants - ComparisonWithSelf - ConstantAssertExpression - ConstantIfExpression - ConstantTernaryExpression - DeadCode - DoubleNegative - DuplicateCaseStatement - DuplicateMapKey - DuplicateSetValue - //EmptyCatchBlock - 'EmptyClass' doNotApplyToFilesMatching: '.*Spec.groovy' - EmptyElseBlock - EmptyFinallyBlock - EmptyForStatement - EmptyIfStatement - EmptyInstanceInitializer - EmptyMethod - EmptyStaticInitializer - EmptySwitchStatement - EmptySynchronizedStatement - EmptyTryBlock - EmptyWhileStatement - EqualsAndHashCode - EqualsOverloaded - ExplicitGarbageCollection - ForLoopShouldBeWhileLoop - HardCodedWindowsFileSeparator - HardCodedWindowsRootDirectory - IntegerGetInteger - MultipleUnaryOperators - RandomDoubleCoercedToZero - RemoveAllOnSelf - ReturnFromFinallyBlock - ThrowExceptionFromFinallyBlock - - // rulesets/braces.xml - ElseBlockBraces - ForStatementBraces - IfStatementBraces - WhileStatementBraces - - // rulesets/concurrency.xml - BusyWait - DoubleCheckedLocking - InconsistentPropertyLocking - InconsistentPropertySynchronization - NestedSynchronization - StaticCalendarField - StaticConnection - StaticDateFormatField - StaticMatcherField - StaticSimpleDateFormatField - SynchronizedMethod - SynchronizedOnBoxedPrimitive - SynchronizedOnGetClass - SynchronizedOnReentrantLock - SynchronizedOnString - SynchronizedOnThis - SynchronizedReadObjectMethod - SystemRunFinalizersOnExit - ThisReferenceEscapesConstructor - ThreadGroup - ThreadLocalNotStaticFinal - ThreadYield - UseOfNotifyMethod - VolatileArrayField - VolatileLongOrDoubleField - WaitOutsideOfWhileLoop - - // rulesets/convention.xml - ConfusingTernary - CouldBeElvis - HashtableIsObsolete - IfStatementCouldBeTernary - InvertedIfElse - LongLiteralWithLowerCaseL - 'NoDef' enabled: true - //ParameterReassignment - TernaryCouldBeElvis - VectorIsObsolete - - // rulesets/design.xml - 'AbstractClassWithPublicConstructor' enabled: false - AbstractClassWithoutAbstractMethod - BooleanMethodReturnsNull - BuilderMethodWithSideEffects - CloneableWithoutClone - CloseWithoutCloseable - CompareToWithoutComparable - ConstantsOnlyInterface - EmptyMethodInAbstractClass - FinalClassWithProtectedMember - ImplementationAsType - 'Instanceof' enabled: false - LocaleSetDefault - //NestedForLoop - 'PrivateFieldCouldBeFinal' enabled: false // buggy - PublicInstanceField - ReturnsNullInsteadOfEmptyArray - ReturnsNullInsteadOfEmptyCollection - //SimpleDateFormatMissingLocale - StatelessSingleton - ToStringReturnsNull - - // rulesets/dry.xml - 'DuplicateListLiteral' doNotApplyToFilesMatching: '.*Spec.groovy' - 'DuplicateMapLiteral' doNotApplyToFilesMatching: '.*Spec.groovy' - 'DuplicateNumberLiteral' enabled: false - 'DuplicateStringLiteral' enabled: false - - // rulesets/enhanced.xml - //CloneWithoutCloneable - //JUnitAssertEqualsConstantActualValue - //UnsafeImplementationAsMap - - // rulesets/exceptions.xml - CatchArrayIndexOutOfBoundsException - CatchError - //CatchException - CatchIllegalMonitorStateException - CatchIndexOutOfBoundsException - CatchNullPointerException - CatchRuntimeException - CatchThrowable - ConfusingClassNamedException - ExceptionExtendsError - ExceptionExtendsThrowable - ExceptionNotThrown - MissingNewInThrowStatement - ReturnNullFromCatchBlock - SwallowThreadDeath - ThrowError - ThrowException - ThrowNullPointerException - ThrowRuntimeException - ThrowThrowable - - // rulesets/formatting.xml - //BlankLineBeforePackage - BracesForClass - BracesForForLoop - BracesForIfElse - BracesForMethod - BracesForTryCatchFinally - 'ClassJavadoc' doNotApplyToFilesMatching: '.*Spec.groovy' - ClosureStatementOnOpeningLineOfMultipleLineClosure - ConsecutiveBlankLines - FileEndsWithoutNewline - //'LineLength' doNotApplyToFilesMatching: '*Spec.groovy' - MissingBlankLineAfterImports - MissingBlankLineAfterPackage - SpaceAfterCatch - SpaceAfterClosingBrace - SpaceAfterComma - SpaceAfterFor - SpaceAfterIf - SpaceAfterOpeningBrace - SpaceAfterSemicolon - SpaceAfterSwitch - SpaceAfterWhile - SpaceAroundClosureArrow - 'SpaceAroundMapEntryColon' characterBeforeColonRegex: /\S|\s*/, characterAfterColonRegex: /\s/, doNotApplyToFilesMatching: '.*Spec.groovy' - SpaceAroundOperator - SpaceBeforeClosingBrace - SpaceBeforeOpeningBrace - 'TrailingWhitespace' enabled: false - - // rulesets/generic.xml - IllegalClassMember - IllegalClassReference - IllegalPackageReference - IllegalRegex - IllegalString - IllegalSubclass - RequiredRegex - RequiredString - StatelessClass - - // rulesets/groovyism.xml - AssignCollectionSort - AssignCollectionUnique - ClosureAsLastMethodParameter - CollectAllIsDeprecated - ConfusingMultipleReturns - ExplicitArrayListInstantiation - ExplicitCallToAndMethod - ExplicitCallToCompareToMethod - ExplicitCallToDivMethod - ExplicitCallToEqualsMethod - ExplicitCallToGetAtMethod - ExplicitCallToLeftShiftMethod - ExplicitCallToMinusMethod - ExplicitCallToModMethod - ExplicitCallToMultiplyMethod - ExplicitCallToOrMethod - ExplicitCallToPlusMethod - ExplicitCallToPowerMethod - ExplicitCallToRightShiftMethod - ExplicitCallToXorMethod - ExplicitHashMapInstantiation - ExplicitHashSetInstantiation - ExplicitLinkedHashMapInstantiation - ExplicitLinkedListInstantiation - ExplicitStackInstantiation - ExplicitTreeSetInstantiation - GStringAsMapKey - GStringExpressionWithinString - //GetterMethodCouldBeProperty - GroovyLangImmutable - UseCollectMany - UseCollectNested - - // rulesets/imports.xml - DuplicateImport - ImportFromSamePackage - ImportFromSunPackages - //MisorderedStaticImports - //'NoWildcardImports' doNotApplyToFilesMatching: '.*Spec.groovy' - UnnecessaryGroovyImport - UnusedImport - - // rulesets/jdbc.xml - DirectConnectionManagement - JdbcConnectionReference - JdbcResultSetReference - JdbcStatementReference - - // rulesets/junit.xml - ChainedTest - CoupledTestCase - JUnitAssertAlwaysFails - JUnitAssertAlwaysSucceeds - JUnitFailWithoutMessage - JUnitLostTest - JUnitPublicField - // JUnitPublicNonTestMethod - JUnitPublicProperty - JUnitSetUpCallsSuper - JUnitStyleAssertions - JUnitTearDownCallsSuper - JUnitTestMethodWithoutAssert - JUnitUnnecessarySetUp - JUnitUnnecessaryTearDown - JUnitUnnecessaryThrowsException - SpockIgnoreRestUsed - UnnecessaryFail - UseAssertEqualsInsteadOfAssertTrue - UseAssertFalseInsteadOfNegation - UseAssertNullInsteadOfAssertEquals - UseAssertSameInsteadOfAssertTrue - UseAssertTrueInsteadOfAssertEquals - UseAssertTrueInsteadOfNegation - - // rulesets/logging.xml - LoggerForDifferentClass - LoggerWithWrongModifiers - LoggingSwallowsStacktrace - MultipleLoggers - PrintStackTrace - Println - SystemErrPrint - SystemOutPrint - - // rulesets/naming.xml - AbstractClassName - ClassName - ClassNameSameAsFilename - //ConfusingMethodName - //'FactoryMethodName' doNotApplyToFilesMatching: '.*Spec.groovy' - FieldName - InterfaceName - 'MethodName' doNotApplyToFilesMatching: '.*Spec.groovy' - ObjectOverrideMisspelledMethodName - PackageName - PackageNameMatchesFilePath - ParameterName - PropertyName - VariableName - - // rulesets/security.xml - FileCreateTempFile - InsecureRandom - 'JavaIoPackageAccess' enabled: false - NonFinalPublicField - NonFinalSubclassOfSensitiveInterface - ObjectFinalize - PublicFinalizeMethod - SystemExit - UnsafeArrayDeclaration - - // rulesets/serialization.xml - EnumCustomSerializationIgnored - SerialPersistentFields - SerialVersionUID - 'SerializableClassMustDefineSerialVersionUID' enabled: false - - // rulesets/size.xml - //'AbcMetric' doNotApplyToFilesMatching: '.*Spec.groovy' // Requires the GMetrics jar - ClassSize - CrapMetric // Requires the GMetrics jar and a Cobertura coverage file - //'CyclomaticComplexity' doNotApplyToFilesMatching: '.*Spec.groovy' // Requires the GMetrics jar - MethodCount - //'MethodSize' doNotApplyToFilesMatching: '.*Spec.groovy' - //NestedBlockDepth - 'ParameterCount' maxParameters: 6 - - // rulesets/unnecessary.xml - AddEmptyString - ConsecutiveLiteralAppends - ConsecutiveStringConcatenation - UnnecessaryBigDecimalInstantiation - UnnecessaryBigIntegerInstantiation - 'UnnecessaryBooleanExpression' doNotApplyToFilesMatching: '.*Spec.groovy' - UnnecessaryBooleanInstantiation - UnnecessaryCallForLastElement - UnnecessaryCallToSubstring - //UnnecessaryCast - UnnecessaryCatchBlock - UnnecessaryCollectCall - UnnecessaryCollectionCall - UnnecessaryConstructor - UnnecessaryDefInFieldDeclaration - UnnecessaryDefInMethodDeclaration - UnnecessaryDefInVariableDeclaration - UnnecessaryDotClass - UnnecessaryDoubleInstantiation - UnnecessaryElseStatement - UnnecessaryFinalOnPrivateMethod - UnnecessaryFloatInstantiation - UnnecessaryGString - UnnecessaryGetter - UnnecessaryIfStatement - UnnecessaryInstanceOfCheck - UnnecessaryInstantiationToGetClass - UnnecessaryIntegerInstantiation - UnnecessaryLongInstantiation - UnnecessaryModOne - UnnecessaryNullCheck - UnnecessaryNullCheckBeforeInstanceOf - 'UnnecessaryObjectReferences' doNotApplyToFilesMatching: '.*Spec.groovy' - UnnecessaryOverridingMethod - UnnecessaryPackageReference - UnnecessaryParenthesesForMethodCallWithClosure - UnnecessaryPublicModifier - UnnecessaryReturnKeyword - UnnecessarySafeNavigationOperator - UnnecessarySelfAssignment - UnnecessarySemicolon - UnnecessaryStringInstantiation - UnnecessaryTernaryExpression - UnnecessaryToString - UnnecessaryTransientModifier - - // rulesets/unused.xml - UnusedArray - 'UnusedMethodParameter' enabled: false - UnusedObject - UnusedPrivateField - UnusedPrivateMethod - UnusedPrivateMethodParameter - UnusedVariable - - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/GraphQL.groovy b/core/src/main/groovy/org/grails/gorm/graphql/GraphQL.groovy deleted file mode 100644 index 22dbff59..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/GraphQL.groovy +++ /dev/null @@ -1,28 +0,0 @@ -package org.grails.gorm.graphql - -import java.lang.annotation.ElementType -import java.lang.annotation.Retention -import java.lang.annotation.RetentionPolicy -import java.lang.annotation.Target - -/** - * Annotation used to supply metadata to GraphQL. Can be used - * on entites related to graphl mapped domains even if the - * domain itself isn't mapped. Also useful to annotate on - * enumerations because there is no other alternative. - * - * The default deprecation reason is "Deprecated" - * - * @author James Kleeh - * @since 1.0.0 - */ -@Target([ElementType.TYPE, ElementType.FIELD]) -@Retention(RetentionPolicy.RUNTIME) -@interface GraphQL { - - String value() default '' - - boolean deprecated() default false - - String deprecationReason() default '' -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/GraphQLEntityHelper.groovy b/core/src/main/groovy/org/grails/gorm/graphql/GraphQLEntityHelper.groovy deleted file mode 100644 index d56d8e5c..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/GraphQLEntityHelper.groovy +++ /dev/null @@ -1,105 +0,0 @@ -package org.grails.gorm.graphql - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.config.Entity -import org.grails.datastore.mapping.model.IllegalMappingException -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.entity.dsl.GraphQLMapping -import org.grails.gorm.graphql.entity.dsl.LazyGraphQLMapping - -import java.lang.reflect.Method -import java.lang.reflect.Modifier - -/** - * A helper class to get GraphQL mappings and descriptions for GORM entities - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class GraphQLEntityHelper { - - private static Map mappings = [:] - private static Map descriptions = [:] - - static String getDescription(final PersistentEntity entity) { - if (descriptions.containsKey(entity)) { - return descriptions.get(entity) - } - - String description = getMapping(entity)?.description - - if (description == null) { - GraphQL graphQL = entity.javaClass.getAnnotation(GraphQL) - if (graphQL != null && !graphQL.value().empty) { - description = graphQL.value() - } - else { - try { - Class hibernateMapping = this.classLoader.loadClass('org.grails.orm.hibernate.cfg.Mapping') - Entity mapping = entity.mapping.mappedForm - if (hibernateMapping.isAssignableFrom(mapping.class)) { - description = hibernateMapping.getMethod('getComment').invoke(mapping) - } - } catch (ClassNotFoundException e) { } - } - } - descriptions.put(entity, description) - description - } - - static GraphQLMapping getMapping(final PersistentEntity entity) { - if (mappings.containsKey(entity)) { - return mappings.get(entity) - } - Object graphql - for (Method method: entity.javaClass.declaredMethods) { - if (Modifier.isStatic(method.modifiers) && method.name.equalsIgnoreCase('getgraphql')) { - graphql = method.invoke(null) - break - } - } - GraphQLMapping mapping = null - if (graphql != null) { - if (graphql == Boolean.TRUE) { - mapping = new GraphQLMapping() - } - else if (graphql instanceof Closure) { - mapping = new GraphQLMapping().build((Closure)graphql) - } - else if (graphql instanceof LazyGraphQLMapping) { - mapping = ((LazyGraphQLMapping)graphql).initialize() - } - else if (graphql instanceof GraphQLMapping) { - mapping = (GraphQLMapping)graphql - } - - if (!(mapping instanceof GraphQLMapping)) { - throw new IllegalMappingException("The static graphql property on ${entity.name} is not a Boolean, Closure, or GraphQLMapping") - } - verifyMapping(mapping, entity) - } - mappings.put(entity, mapping) - mapping - } - - static void verifyMapping(GraphQLMapping mapping, PersistentEntity entity) { -/* - Set persistentPropertyNames = new HashSet<>() - if (entity.identity != null) { - persistentPropertyNames.add(entity.identity.name) - } - if (entity.compositeIdentity != null) { - persistentPropertyNames.addAll(entity.compositeIdentity*.name) - } - persistentPropertyNames.addAll(entity.persistentPropertyNames) -*/ - - for (String name: mapping.propertyMappings.keySet()) { - if (entity.getPropertyByName(name) == null) { - throw new IllegalMappingException("GraphQL mapping: The property '${name}' was used to reference an existing property in ${entity.javaClass.name}, but no property exists with that name") - } - } - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/GraphQLServiceManager.groovy b/core/src/main/groovy/org/grails/gorm/graphql/GraphQLServiceManager.groovy deleted file mode 100644 index af73b25f..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/GraphQLServiceManager.groovy +++ /dev/null @@ -1,30 +0,0 @@ -package org.grails.gorm.graphql - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.services.ServiceNotFoundException - -/** - * Used to store references to the actual implementations of most of - * the interfaces used in the project to make it easier to pass - * multiple managers (services) to methods. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class GraphQLServiceManager { - - protected Map services = [:] - - void registerService(Class clazz, Object service) { - services.put(clazz, service) - } - - public T getService(Class serviceType) throws ServiceNotFoundException { - if (services.containsKey(serviceType)) { - return (T)services.get(serviceType) - } - throw new ServiceNotFoundException("No GraphQL service could be found for ${serviceType.name}") - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/Schema.groovy b/core/src/main/groovy/org/grails/gorm/graphql/Schema.groovy deleted file mode 100644 index ac64aa6c..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/Schema.groovy +++ /dev/null @@ -1,512 +0,0 @@ -package org.grails.gorm.graphql - -import graphql.schema.* -import groovy.transform.CompileStatic -import javassist.Modifier -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.gorm.graphql.binding.DataBinderNotFoundException -import org.grails.gorm.graphql.binding.GraphQLDataBinder -import org.grails.gorm.graphql.binding.manager.DefaultGraphQLDataBinderManager -import org.grails.gorm.graphql.binding.manager.GraphQLDataBinderManager -import org.grails.gorm.graphql.entity.GraphQLEntityNamingConvention -import org.grails.gorm.graphql.entity.dsl.GraphQLMapping -import org.grails.gorm.graphql.entity.operations.CustomOperation -import org.grails.gorm.graphql.entity.operations.ListOperation -import org.grails.gorm.graphql.entity.operations.ProvidedOperation -import org.grails.gorm.graphql.entity.property.manager.DefaultGraphQLDomainPropertyManager -import org.grails.gorm.graphql.entity.property.manager.GraphQLDomainPropertyManager -import org.grails.gorm.graphql.fetcher.BindingGormDataFetcher -import org.grails.gorm.graphql.fetcher.DeletingGormDataFetcher -import org.grails.gorm.graphql.fetcher.PaginatingGormDataFetcher -import org.grails.gorm.graphql.fetcher.impl.CountEntityDataFetcher -import org.grails.gorm.graphql.fetcher.impl.CreateEntityDataFetcher -import org.grails.gorm.graphql.fetcher.impl.DeleteEntityDataFetcher -import org.grails.gorm.graphql.fetcher.impl.EntityDataFetcher -import org.grails.gorm.graphql.fetcher.impl.PaginatedEntityDataFetcher -import org.grails.gorm.graphql.fetcher.impl.SingleEntityDataFetcher -import org.grails.gorm.graphql.fetcher.impl.UpdateEntityDataFetcher -import org.grails.gorm.graphql.fetcher.interceptor.InterceptingDataFetcher -import org.grails.gorm.graphql.fetcher.interceptor.InterceptorInvoker -import org.grails.gorm.graphql.fetcher.interceptor.MutationInterceptorInvoker -import org.grails.gorm.graphql.fetcher.interceptor.QueryInterceptorInvoker -import org.grails.gorm.graphql.fetcher.manager.DefaultGraphQLDataFetcherManager -import org.grails.gorm.graphql.fetcher.manager.GraphQLDataFetcherManager -import org.grails.gorm.graphql.interceptor.GraphQLSchemaInterceptor -import org.grails.gorm.graphql.interceptor.manager.DefaultGraphQLInterceptorManager -import org.grails.gorm.graphql.interceptor.manager.GraphQLInterceptorManager -import org.grails.gorm.graphql.response.delete.DefaultGraphQLDeleteResponseHandler -import org.grails.gorm.graphql.response.delete.GraphQLDeleteResponseHandler -import org.grails.gorm.graphql.response.errors.DefaultGraphQLErrorsResponseHandler -import org.grails.gorm.graphql.response.errors.GraphQLErrorsResponseHandler -import org.grails.gorm.graphql.response.pagination.DefaultGraphQLPaginationResponseHandler -import org.grails.gorm.graphql.response.pagination.GraphQLPaginationResponseHandler -import org.grails.gorm.graphql.types.DefaultGraphQLTypeManager -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.types.GraphQLTypeManager -import org.grails.gorm.graphql.types.scalars.coercing.DateCoercion -import org.grails.gorm.graphql.types.scalars.coercing.jsr310.* -import org.springframework.context.support.StaticMessageSource -import javax.annotation.PostConstruct -import java.time.Instant -import java.time.LocalDate -import java.time.LocalDateTime -import java.time.LocalTime -import java.time.OffsetDateTime -import java.time.OffsetTime -import java.time.ZonedDateTime - -import static graphql.schema.FieldCoordinates.coordinates -import static graphql.schema.GraphQLArgument.newArgument -import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition -import static graphql.schema.GraphQLList.list -import static graphql.schema.GraphQLObjectType.newObject -import static graphql.schema.GraphQLScalarType.newScalar -import static org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType.* - -/** - * Created by jameskleeh on 5/19/17. - */ -@CompileStatic -class Schema { - - public static final String DEFAULT_DEPRECATION_REASON = 'Deprecated' - - protected MappingContext[] mappingContexts - - GraphQLCodeRegistry.Builder codeRegistry - GraphQLTypeManager typeManager - GraphQLDeleteResponseHandler deleteResponseHandler - GraphQLEntityNamingConvention namingConvention - GraphQLDataBinderManager dataBinderManager - GraphQLDataFetcherManager dataFetcherManager - GraphQLInterceptorManager interceptorManager - GraphQLErrorsResponseHandler errorsResponseHandler - GraphQLDomainPropertyManager domainPropertyManager - GraphQLPaginationResponseHandler paginationResponseHandler - GraphQLServiceManager serviceManager - - Map listArguments - - List dateFormats - boolean dateFormatLenient = false - - private boolean initialized = false - - Schema(MappingContext... mappingContext) { - this.mappingContexts = mappingContext - } - - void setListArguments(Map arguments) { - listArguments = buildListArguments(arguments) - } - - Map buildListArguments(Map arguments) { - if (arguments != null) { - Map listArguments = [:] - for (Map.Entry entry : arguments) { - GraphQLType type = typeManager.getType(entry.value) - if (!(type instanceof GraphQLInputType)) { - throw new IllegalArgumentException("Error while setting list arguments. Invalid returnType found for ${entry.value.name}. GraphQLType found ${type} of returnType ${type.class.name} is not an instance of ${GraphQLInputType.name}") - } - listArguments.put(entry.key, (GraphQLInputType) type) - } - return listArguments - } - } - - void populateDefaultDateTypes() { - if (!typeManager.hasType(Date)) { - typeManager.registerType(Date, newScalar().name('Date').description('Built-in Date').coercing(new DateCoercion(dateFormats, dateFormatLenient)).build()) - } - if (!typeManager.hasType(Instant)) { - typeManager.registerType(Instant, newScalar().name('Instant').description('Built-in Instant').coercing(new InstantCoercion()).build()) - } - if (!typeManager.hasType(LocalDate)) { - typeManager.registerType(LocalDate, newScalar().name('LocalDate').description('Built-in LocalDate').coercing(new LocalDateCoercion(dateFormats)).build()) - } - if (!typeManager.hasType(LocalDateTime)) { - typeManager.registerType(LocalDateTime, newScalar().name('LocalDateTime').description('Built-in LocalDateTime').coercing(new LocalDateTimeCoercion(dateFormats)).build()) - } - if (!typeManager.hasType(LocalTime)) { - typeManager.registerType(LocalTime, newScalar().name('LocalTime').description('Built-in LocalTime').coercing(new LocalTimeCoercion(dateFormats)).build()) - } - if (!typeManager.hasType(OffsetDateTime)) { - typeManager.registerType(OffsetDateTime, newScalar().name('OffsetDateTime').description('Built-in OffsetDateTime').coercing(new OffsetDateTimeCoercion(dateFormats)).build()) - } - if (!typeManager.hasType(OffsetTime)) { - typeManager.registerType(OffsetTime, newScalar().name('OffsetTime').description('Built-in OffsetTime').coercing(new OffsetTimeCoercion(dateFormats)).build()) - } - if (!typeManager.hasType(ZonedDateTime)) { - typeManager.registerType(ZonedDateTime, newScalar().name('ZonedDateTime').description('Built-in ZonedDateTime').coercing(new ZonedDateTimeCoercion(dateFormats)).build()) - } - } - - @PostConstruct - void initialize() { - if (codeRegistry == null) { - codeRegistry = GraphQLCodeRegistry.newCodeRegistry() - } - if (namingConvention == null) { - namingConvention = new GraphQLEntityNamingConvention() - } - if (errorsResponseHandler == null) { - errorsResponseHandler = new DefaultGraphQLErrorsResponseHandler(new StaticMessageSource(), codeRegistry) - } - if (domainPropertyManager == null) { - domainPropertyManager = new DefaultGraphQLDomainPropertyManager() - } - if (paginationResponseHandler == null) { - paginationResponseHandler = new DefaultGraphQLPaginationResponseHandler() - } - - if (typeManager == null) { - typeManager = new DefaultGraphQLTypeManager(codeRegistry, namingConvention, errorsResponseHandler, domainPropertyManager, paginationResponseHandler) - } - - populateDefaultDateTypes() - - if (deleteResponseHandler == null) { - deleteResponseHandler = new DefaultGraphQLDeleteResponseHandler() - } - if (dataBinderManager == null) { - dataBinderManager = new DefaultGraphQLDataBinderManager() - } - if (dataFetcherManager == null) { - dataFetcherManager = new DefaultGraphQLDataFetcherManager() - } - if (listArguments == null) { - setListArguments(EntityDataFetcher.ARGUMENTS) - } - if (interceptorManager == null) { - interceptorManager = new DefaultGraphQLInterceptorManager() - } - if (serviceManager == null) { - serviceManager = new GraphQLServiceManager() - } - - serviceManager.with { - registerService(GraphQLTypeManager, typeManager) - registerService(GraphQLEntityNamingConvention, namingConvention) - registerService(GraphQLDeleteResponseHandler, deleteResponseHandler) - registerService(GraphQLDataBinderManager, dataBinderManager) - registerService(GraphQLDataFetcherManager, dataFetcherManager) - registerService(GraphQLInterceptorManager, interceptorManager) - registerService(GraphQLDomainPropertyManager, domainPropertyManager) - registerService(GraphQLErrorsResponseHandler, errorsResponseHandler) - registerService(GraphQLPaginationResponseHandler, paginationResponseHandler) - } - - initialized = true - } - - protected void populateIdentityArguments(PersistentEntity entity, GraphQLFieldDefinition.Builder... builders) { - Map identities = [:] - - if (entity.identity != null) { - identities.put(entity.identity.name, entity.identity.type) - } else if (entity.compositeIdentity != null) { - for (PersistentProperty identity : entity.compositeIdentity) { - if (identity instanceof Association) { - PersistentEntity associatedEntity = ((Association) identity).associatedEntity - if (associatedEntity.identity != null) { - identities.put(identity.name, associatedEntity.identity.type) - } else { - throw new UnsupportedOperationException("Mapping domain classes with nested composite keys is not currently supported. ${identity} has a composite key.") - } - } else { - identities.put(identity.name, identity.type) - } - } - } - - for (Map.Entry identity : identities) { - GraphQLInputType inputType = (GraphQLInputType) typeManager.getType(identity.value, false) - - for (GraphQLFieldDefinition.Builder builder : builders) { - builder.argument(newArgument() - .name(identity.key) - .type(inputType)) - } - } - } - - GraphQLSchema generate() { - - if (!initialized) { - initialize() - } - final String queryTypeName = 'Query' - final String mutationTypeName = 'Mutation' - - GraphQLObjectType.Builder queryType = newObject().name(queryTypeName) - GraphQLObjectType.Builder mutationType = newObject().name(mutationTypeName) - - Set childrenNotMapped = [] - - for (MappingContext mappingContext : mappingContexts) { - for (PersistentEntity entity : mappingContext.persistentEntities) { - - GraphQLMapping mapping = GraphQLEntityHelper.getMapping(entity) - if (mapping == null) { - if (!entity.root) { - childrenNotMapped.add(entity) - } - continue - } else if (!mapping.operations.all.enabled) { - continue - } - - List queryFields = [] - List mutationFields = [] - - final GraphQLOutputType objectType = typeManager.getQueryType(entity, GraphQLPropertyType.OUTPUT) - - List requiresIdentityArguments = [] - List postIdentityExecutables = [] - InterceptorInvoker queryInterceptorInvoker = new QueryInterceptorInvoker() - - ProvidedOperation queryOperation = mapping.operations.query - ProvidedOperation mutationOperation = mapping.operations.mutation - - ProvidedOperation getOperation = mapping.operations.get - if (queryOperation.enabled && getOperation.enabled) { - - DataFetcher getFetcher = dataFetcherManager.getReadingFetcher(entity, GET).orElse(new SingleEntityDataFetcher(entity)) - - final String getFieldName = namingConvention.getGet(entity) - - GraphQLFieldDefinition.Builder queryOne = newFieldDefinition() - .name(getFieldName) - .type(objectType) - .description(getOperation.description) - .deprecate(getOperation.deprecationReason) - - codeRegistry - .dataFetcher( - coordinates(queryTypeName, getFieldName), - new InterceptingDataFetcher(entity, serviceManager, queryInterceptorInvoker, GET, getFetcher) - ) - - requiresIdentityArguments.add(queryOne) - queryFields.add(queryOne) - } - - ListOperation listOperation = mapping.operations.list - if (queryOperation.enabled && listOperation.enabled) { - - DataFetcher listFetcher = dataFetcherManager.getReadingFetcher(entity, LIST).orElse(null) - - final String listFieldName = namingConvention.getList(entity) - GraphQLFieldDefinition.Builder queryAll = newFieldDefinition() - .name(listFieldName) - .description(listOperation.description) - .deprecate(listOperation.deprecationReason) - - GraphQLOutputType listOutputType - if (listOperation.paginate) { - if (listFetcher == null) { - listFetcher = new PaginatedEntityDataFetcher(entity) - } - listOutputType = typeManager.getQueryType(entity, GraphQLPropertyType.OUTPUT_PAGED) - } else { - if (listFetcher == null) { - listFetcher = new EntityDataFetcher(entity) - } - listOutputType = list(objectType) - } - queryAll.type(listOutputType) - - if (listFetcher instanceof PaginatingGormDataFetcher) { - ((PaginatingGormDataFetcher) listFetcher).responseHandler = paginationResponseHandler - } - - codeRegistry.dataFetcher( - coordinates(queryTypeName, listFieldName), - new InterceptingDataFetcher(entity, serviceManager, queryInterceptorInvoker, LIST, listFetcher) - ) - - queryFields.add(queryAll) - - for (Map.Entry argument : listArguments) { - queryAll.argument( - newArgument() - .name(argument.key) - .type(argument.value)) - } - } - - ProvidedOperation countOperation = mapping.operations.count - if (queryOperation.enabled && countOperation.enabled) { - - DataFetcher countFetcher = dataFetcherManager.getReadingFetcher(entity, COUNT).orElse(new CountEntityDataFetcher(entity)) - - final String countFieldName = namingConvention.getCount(entity) - final GraphQLOutputType countOutputType = (GraphQLOutputType) typeManager.getType(Integer) - - GraphQLFieldDefinition.Builder queryCount = newFieldDefinition() - .name(countFieldName) - .type(countOutputType) - .description(countOperation.description) - .deprecate(countOperation.deprecationReason) - - codeRegistry.dataFetcher( - coordinates(queryTypeName, countFieldName), - new InterceptingDataFetcher(entity, serviceManager, queryInterceptorInvoker, COUNT, countFetcher) - ) - - queryFields.add(queryCount) - } - - InterceptorInvoker mutationInterceptorInvoker = new MutationInterceptorInvoker() - - GraphQLDataBinder dataBinder = dataBinderManager.getDataBinder(entity.javaClass) - - ProvidedOperation createOperation = mapping.operations.create - if (mutationOperation.enabled && createOperation.enabled && !Modifier.isAbstract(entity.javaClass.modifiers)) { - if (dataBinder == null) { - throw new DataBinderNotFoundException(entity) - } - GraphQLInputType createObjectType = typeManager.getMutationType(entity, GraphQLPropertyType.CREATE, true) - - if (!createObjectType.children.empty) { - BindingGormDataFetcher createFetcher = dataFetcherManager.getBindingFetcher(entity, CREATE).orElse(new CreateEntityDataFetcher(entity)) - createFetcher.dataBinder = dataBinder - - final String createFieldName = namingConvention.getCreate(entity) - - GraphQLFieldDefinition.Builder create = newFieldDefinition() - .name(createFieldName) - .type(objectType) - .description(createOperation.description) - .deprecate(createOperation.deprecationReason) - .argument(newArgument() - .name(entity.decapitalizedName) - .type(createObjectType)) - - codeRegistry.dataFetcher( - coordinates(mutationTypeName, createFieldName), - new InterceptingDataFetcher(entity, serviceManager, mutationInterceptorInvoker, CREATE, createFetcher) - ) - - mutationFields.add(create) - } - } - - ProvidedOperation updateOperation = mapping.operations.update - if (mutationOperation.enabled && updateOperation.enabled) { - if (dataBinder == null) { - throw new DataBinderNotFoundException(entity) - } - GraphQLInputType updateObjectType = typeManager.getMutationType(entity, GraphQLPropertyType.UPDATE, true) - - BindingGormDataFetcher updateFetcher = dataFetcherManager.getBindingFetcher(entity, UPDATE).orElse(new UpdateEntityDataFetcher(entity)) - - updateFetcher.dataBinder = dataBinder - - final String updateFieldName = namingConvention.getUpdate(entity) - - GraphQLFieldDefinition.Builder update = newFieldDefinition() - .name(updateFieldName) - .type(objectType) - .description(updateOperation.description) - .deprecate(updateOperation.deprecationReason) - - codeRegistry.dataFetcher( - coordinates(mutationTypeName, updateFieldName), - new InterceptingDataFetcher(entity, serviceManager, mutationInterceptorInvoker, UPDATE, updateFetcher) - ) - - postIdentityExecutables.add { - update.argument(newArgument() - .name(entity.decapitalizedName) - .type(updateObjectType)) - } - - requiresIdentityArguments.add(update) - mutationFields.add(update) - } - - ProvidedOperation deleteOperation = mapping.operations.delete - if (mutationOperation.enabled && deleteOperation.enabled) { - - DeletingGormDataFetcher deleteFetcher = dataFetcherManager.getDeletingFetcher(entity).orElse(new DeleteEntityDataFetcher(entity)) - - deleteFetcher.responseHandler = deleteResponseHandler - - final String deleteFieldName = namingConvention.getDelete(entity) - final GraphQLObjectType deleteObjectType = deleteResponseHandler.getObjectType(typeManager) - - GraphQLFieldDefinition.Builder delete = newFieldDefinition() - .name(deleteFieldName) - .type(deleteObjectType) - .description(deleteOperation.description) - .deprecate(deleteOperation.deprecationReason) - - codeRegistry.dataFetcher( - coordinates(mutationTypeName, deleteFieldName), - new InterceptingDataFetcher(entity, serviceManager, mutationInterceptorInvoker, DELETE, deleteFetcher) - ) - - requiresIdentityArguments.add(delete) - mutationFields.add(delete) - } - - final GraphQLFieldDefinition.Builder[] builders = requiresIdentityArguments as GraphQLFieldDefinition.Builder[] - populateIdentityArguments(entity, builders) - - for (Closure c : postIdentityExecutables) { - c.call() - } - - for (CustomOperation operation : mapping.customQueryOperations) { - queryFields.add(operation.createField(entity, serviceManager, mappingContext, listArguments)) - } - - for (CustomOperation operation : mapping.customMutationOperations) { - mutationFields.add(operation.createField(entity, serviceManager, mappingContext, Collections.emptyMap())) - } - - for (GraphQLSchemaInterceptor schemaInterceptor : interceptorManager.interceptors) { - schemaInterceptor.interceptEntity(entity, queryFields, mutationFields) - } - - queryType.fields((List) queryFields*.build()) - - mutationType.fields((List) mutationFields*.build()) - } - } - - Set additionalTypes = [] - - for (PersistentEntity entity : childrenNotMapped) { - GraphQLMapping mapping = GraphQLEntityHelper.getMapping(entity.rootEntity) - if (mapping == null) { - continue - } - - additionalTypes.add(typeManager.getQueryType(entity, GraphQLPropertyType.OUTPUT)) - } - - for (GraphQLSchemaInterceptor schemaInterceptor : interceptorManager.interceptors) { - schemaInterceptor.interceptSchema(queryType, mutationType, additionalTypes) - } - - GraphQLSchema.Builder schema = GraphQLSchema.newSchema() - .codeRegistry(codeRegistry.build()) - .additionalTypes(additionalTypes) - - GraphQLObjectType mutation = mutationType.build() - if (mutation.fieldDefinitions) { - schema.mutation(mutation) - } - GraphQLObjectType query = queryType.build() - if (query.fieldDefinitions) { - schema.query(query) - return schema.build() - } - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/binding/DataBinderNotFoundException.groovy b/core/src/main/groovy/org/grails/gorm/graphql/binding/DataBinderNotFoundException.groovy deleted file mode 100644 index 2d3eb958..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/binding/DataBinderNotFoundException.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package org.grails.gorm.graphql.binding - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.PersistentEntity - -/** - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class DataBinderNotFoundException extends RuntimeException { - - DataBinderNotFoundException(PersistentEntity entity) { - this(entity.javaClass) - } - - DataBinderNotFoundException(Class clazz) { - super("A GraphQL data binder could not be found for ${clazz.name}") - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/binding/GraphQLDataBinder.groovy b/core/src/main/groovy/org/grails/gorm/graphql/binding/GraphQLDataBinder.groovy deleted file mode 100644 index 6679cd2f..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/binding/GraphQLDataBinder.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package org.grails.gorm.graphql.binding - -/** - * An interface to bind data from GraphQL to a GORM entity - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GraphQLDataBinder { - - /** - * Binds data to a domain class instance - * - * @param object The domain class instance - * @param data The data to bind - */ - void bind(Object object, Map data) -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/binding/manager/DefaultGraphQLDataBinderManager.groovy b/core/src/main/groovy/org/grails/gorm/graphql/binding/manager/DefaultGraphQLDataBinderManager.groovy deleted file mode 100644 index dcd2cc1c..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/binding/manager/DefaultGraphQLDataBinderManager.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package org.grails.gorm.graphql.binding.manager - -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.binding.GraphQLDataBinder -import org.grails.gorm.graphql.types.KeyClassQuery -import org.springframework.beans.MutablePropertyValues -import org.springframework.validation.DataBinder - -/** - * A default implementation of {@link GraphQLDataBinderManager} that - * will also return a result if the class requested is a subclass - * of a class that exists in the registry. The order of which binders - * are registered is relevant to their resolution. The items added last - * have priority when searching for subclass matches. - * - * Example: - * register(Collection) - * register(List) - * - * When the binder is searched for ArrayList, List will be returned. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class DefaultGraphQLDataBinderManager implements GraphQLDataBinderManager, KeyClassQuery { - - protected final Map dataBinders = Collections.synchronizedMap([:]) - - /** - * Registers a default data binder for the Object class - */ - DefaultGraphQLDataBinderManager() { - //Create the default data binder - registerDataBinder(Object, new GraphQLDataBinder() { - @Override - void bind(Object object, Map data) { - DataBinder dataBinder = new DataBinder(object) - dataBinder.bind(new MutablePropertyValues(data)) - } - }) - } - - /** - * Registers a the data binder provided for the Object class - */ - DefaultGraphQLDataBinderManager(GraphQLDataBinder defaultDataBinder) { - registerDataBinder(Object, defaultDataBinder) - } - - /** - * @see GraphQLDataBinderManager#registerDataBinder - */ - void registerDataBinder(Class clazz, GraphQLDataBinder dataBinder) { - dataBinders.put(clazz, dataBinder) - } - - /** - * @see GraphQLDataBinderManager#getDataBinder - * - * @return NULL if no data binder found - */ - GraphQLDataBinder getDataBinder(Class clazz) { - searchMap(dataBinders, clazz) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/binding/manager/GraphQLDataBinderManager.groovy b/core/src/main/groovy/org/grails/gorm/graphql/binding/manager/GraphQLDataBinderManager.groovy deleted file mode 100644 index 52b1cca3..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/binding/manager/GraphQLDataBinderManager.groovy +++ /dev/null @@ -1,30 +0,0 @@ -package org.grails.gorm.graphql.binding.manager - -import org.grails.gorm.graphql.binding.GraphQLDataBinder - -/** - * An interface to describe a manager that will store - * and return instances of data binders to be used - * with GraphQL operations on GORM entities - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GraphQLDataBinderManager { - - /** - * Register a data binder for use with the provided class - * - * @param clazz The class to be bound - * @param dataBinder The data binding instance to be used - */ - void registerDataBinder(Class clazz, GraphQLDataBinder dataBinder) - - /** - * Returns a data binder to be used for the provided class - * - * @param clazz The class to be bound - * @return The data binding instance to be used - */ - GraphQLDataBinder getDataBinder(Class clazz) -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/EntityFetchOptions.java b/core/src/main/groovy/org/grails/gorm/graphql/entity/EntityFetchOptions.java deleted file mode 100644 index e567ce2e..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/EntityFetchOptions.java +++ /dev/null @@ -1,244 +0,0 @@ -package org.grails.gorm.graphql.entity; - -import graphql.execution.MergedField; -import graphql.language.Field; -import graphql.language.Selection; -import graphql.language.SelectionSet; -import graphql.schema.DataFetchingEnvironment; -import org.grails.datastore.gorm.GormEnhancer; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.model.types.ToMany; -import org.grails.datastore.mapping.model.types.ToOne; - -import java.util.*; -import java.util.stream.Collectors; - -/** - * Helper class to determine which properties should be eagerly - * fetched based on the fields in a {@link DataFetchingEnvironment}. - * - * @author James Kleeh - * @since 1.0.0 - */ -public class EntityFetchOptions { - - private Map associations = new LinkedHashMap<>(); - protected PersistentEntity entity; - protected Set associationNames; - protected String propertyName; - - private static final String JOIN = "join"; - private static final String FETCH = "fetch"; - - public EntityFetchOptions(Class entityClass) { - this(entityClass, null); - } - - public EntityFetchOptions(Class entityClass, String projectionName) { - this(GormEnhancer.findStaticApi(entityClass).getGormPersistentEntity(), projectionName); - } - - public EntityFetchOptions(PersistentEntity entity) { - this(entity, null); - } - - /** - * Designed for use when a projection query is used. The fetch arguments - * need prepended with the projection property name. - * - * @param entity The {@link PersistentEntity} being queried - * @param projectionName The name of the property being projected - */ - public EntityFetchOptions(PersistentEntity entity, String projectionName) { - if (entity == null) { - throw new IllegalArgumentException("Cannot retrieve fetch options for a null entity. Is GORM initialized?"); - } - - this.entity = entity; - this.propertyName = projectionName; - for (Association association : entity.getAssociations()) { - associations.put(association.getName(), association); - } - - associationNames = associations.keySet(); - } - - /** - * @return The associations of the {@link PersistentEntity}. The key - * is the property name and the value is the association. - */ - public Map getAssociations() { - return associations; - } - - protected boolean isForeignKeyInChild(Association association) { - return association instanceof ToOne && ((ToOne) association).isForeignKeyInChild() || association instanceof ToMany; - } - - protected void handleField(String parentName, Field selectedField, Set joinProperties) { - String resolvedName; - - if (parentName != null) { - resolvedName = parentName + "." + selectedField.getName(); - } else { - resolvedName = selectedField.getName(); - } - - Association association = associations.get(selectedField.getName()); - - PersistentEntity entity = association.getAssociatedEntity(); - - if (entity == null) { - joinProperties.add(resolvedName); - return; - } - - final SelectionSet set = selectedField.getSelectionSet(); - List selections = (set == null ? new ArrayList<>() : set.getSelections()); - - if (!association.isEmbedded()) { - if (isForeignKeyInChild(association)) { - joinProperties.add(resolvedName); - } - else if (selections.size() == 1 && selections.get(0) instanceof Field) { - Field field = (Field) selections.get(0); - if (!entity.isIdentityName(field.getName())) { - joinProperties.add(resolvedName); - } - } - else { - joinProperties.add(resolvedName); - } - } - - List fields = new ArrayList<>(); - - selections.stream() - .filter(Field.class::isInstance) - .map(Field.class::cast) - .forEach((Field field) -> { - if (field.getName().equals(association.getReferencedPropertyName())) { - if (field.getSelectionSet() != null) { - - List nestedFields = field - .getSelectionSet() - .getSelections() - .stream() - .filter(Field.class::isInstance) - .map(Field.class::cast) - .collect(Collectors.toList()); - - joinProperties.addAll(getJoinProperties(nestedFields)); - } - } - else { - fields.add(field); - } - }); - - joinProperties.addAll(new EntityFetchOptions(entity, resolvedName).getJoinProperties(fields)); - } - - - public Set getJoinProperties(List fields) { - return getJoinProperties(fields, false); - } - - /** - * Designed for internal use to inspect nested selections - * - * @param fields The list of fields to search - * @param skipCollections Whether to exclude associations that are collections - * @return The list of properties to eagerly fetch - */ - public Set getJoinProperties(List fields, boolean skipCollections) { - Set joinProperties = new HashSet<>(); - - if (fields != null) { - fields.stream() - .filter(field -> associationNames.contains(field.getName())) - .filter(field -> { - if (skipCollections) { - return !(associations.get(field.getName()) instanceof ToMany); - } - else { - return true; - } - }) - .forEach(field -> handleField(propertyName, field, joinProperties)); - } - - return joinProperties; - } - - public Set getJoinProperties(DataFetchingEnvironment environment) { - return getJoinProperties(environment, false); - } - - /** - * Inspects the environment for requested fields and compares - * against the {@link PersistentEntity} associations to determine - * which fields should be eagerly fetched. - * - * @param environment The data fetching environment - * @param skipCollections Whether to exclude associations that are collections - * @return The list of properties to eagerly fetch - */ - public Set getJoinProperties(DataFetchingEnvironment environment, boolean skipCollections) { - List fields = new ArrayList<>(); - MergedField environmentMergedField = environment.getMergedField(); - - if (environmentMergedField != null) { - fields = environmentMergedField - .getFields() - .stream() - .filter(field -> field.getSelectionSet() != null) - .flatMap(field -> field.getSelectionSet().getSelections().stream()) - .filter(Field.class::isInstance) - .map(Field.class::cast) - .collect(Collectors.toList()); - } - - return getJoinProperties(fields, skipCollections); - } - - /** - * Creates the fetch argument prepared to pass to {@link grails.gorm.DetachedCriteria#list(Map)} - * - * @param properties The properties to fetch - * @return The fetch argument - */ - public Map getFetchArgument(Set properties) { - if (properties.isEmpty()) { - return new LinkedHashMap<>(); - } - Map arguments = new LinkedHashMap<>(1); - Map joins = new LinkedHashMap<>(properties.size()); - - for (String prop: properties) { - joins.put(prop, JOIN); - } - arguments.put(FETCH, joins); - return arguments; - } - - - public Map getFetchArgument(DataFetchingEnvironment environment) { - return getFetchArgument(environment, false); - } - - /** - * Inspects the environment for requested fields and compares - * against the {@link PersistentEntity} associations to determine - * which fields should be eagerly fetched. Creates the fetch argument - * prepared to pass to {@link grails.gorm.DetachedCriteria#list(Map)} - * - * @param environment The fetching environment - * @param skipCollections Whether to exclude associations that are collections - * @return The fetch argument - */ - public Map getFetchArgument(DataFetchingEnvironment environment, boolean skipCollections) { - return getFetchArgument(getJoinProperties(environment, skipCollections)); - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/GraphQLEntityNamingConvention.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/GraphQLEntityNamingConvention.groovy deleted file mode 100644 index ba0303c7..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/GraphQLEntityNamingConvention.groovy +++ /dev/null @@ -1,95 +0,0 @@ -package org.grails.gorm.graphql.entity - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.types.GraphQLPropertyType - -/** - * A class to return the names of class types and query/mutation names - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class GraphQLEntityNamingConvention { - - /** - * @param entity The persistent entity - * @return The name to use. Ex: "person" - */ - String getGet(PersistentEntity entity) { - entity.decapitalizedName - } - - /** - * @param entity The persistent entity - * @return The name to use. Ex: "personList" - */ - String getList(PersistentEntity entity) { - entity.decapitalizedName + 'List' - } - - /** - * @param entity The persistent entity - * @return The name to use. Ex: "personCount" - */ - String getCount(PersistentEntity entity) { - entity.decapitalizedName + 'Count' - } - - /** - * @param entity The persistent entity - * @return The name to use. Ex: "personCreate" - */ - String getCreate(PersistentEntity entity) { - entity.decapitalizedName + 'Create' - } - - /** - * @param entity The persistent entity - * @return The name to use. Ex: "personUpdate" - */ - String getUpdate(PersistentEntity entity) { - entity.decapitalizedName + 'Update' - } - - /** - * @param entity The persistent entity - * @return The name to use. Ex: "personDelete" - */ - String getDelete(PersistentEntity entity) { - entity.decapitalizedName + 'Delete' - } - - private String normalizeType(GraphQLPropertyType type) { - type.name().split('_').collect { String name -> - name.toLowerCase().capitalize() - }.join('').replace('Output', '') - } - - /** - * @param entity The persistent entity - * @param type The property returnType - * @return The name to use. Ex: "Person", "PersonCreate", "PersonUpdate", "PersonCreateNested" - */ - String getType(PersistentEntity entity, GraphQLPropertyType type) { - getType(entity.javaClass.simpleName, type) - } - - /** - * @param typeName The custom type name - * @param type The property returnType - * @return The name to use. Ex: "Person", "PersonCreate", "PersonUpdate", "PersonCreateNested" - */ - String getType(String typeName, GraphQLPropertyType type) { - typeName + normalizeType(type) - } - - /** - * @param entity The persistent entity - * @return The name to use. Ex: "PersonPagedResult" - */ - String getPagination(PersistentEntity entity) { - entity.javaClass.simpleName + 'PagedResult' - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/arguments/ComplexArgument.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/arguments/ComplexArgument.groovy deleted file mode 100644 index 7837b889..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/arguments/ComplexArgument.groovy +++ /dev/null @@ -1,48 +0,0 @@ -package org.grails.gorm.graphql.entity.arguments - -import graphql.schema.GraphQLInputType -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.datastore.mapping.model.MappingContext -import org.grails.gorm.graphql.entity.dsl.helpers.ComplexTyped -import org.grails.gorm.graphql.entity.dsl.helpers.ExecutesClosures -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * Used to create arguments to custom operations that are a custom (complex) type - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@InheritConstructors -class ComplexArgument extends CustomArgument implements ComplexTyped, ExecutesClosures { - - String typeName - - ComplexArgument typeName(String typeName) { - this.typeName = typeName - this - } - - private ComplexTyped accepts = (ComplexTyped)new Object().withTraits(ComplexTyped).defaultNull(false) - - void accepts(@DelegatesTo(value = ComplexTyped, strategy = Closure.DELEGATE_ONLY) Closure closure) { - withDelegate(closure, accepts) - } - - @Override - GraphQLInputType getType(GraphQLTypeManager typeManager, MappingContext mappingContext) { - accepts.buildCustomInputType(typeName, typeManager, mappingContext, nullable) - } - - void validate() { - super.validate() - if (typeName == null) { - throw new IllegalArgumentException('The type name must be specified for custom arguments with a complex type') - } - if (accepts.fields.empty) { - throw new IllegalArgumentException('At least 1 field is required for creating a custom argument with a complex type') - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/arguments/CustomArgument.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/arguments/CustomArgument.groovy deleted file mode 100644 index dd8f92db..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/arguments/CustomArgument.groovy +++ /dev/null @@ -1,45 +0,0 @@ -package org.grails.gorm.graphql.entity.arguments - -import graphql.schema.GraphQLArgument -import graphql.schema.GraphQLInputType -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.MappingContext -import org.grails.gorm.graphql.entity.dsl.helpers.Defaultable -import org.grails.gorm.graphql.entity.dsl.helpers.Describable -import org.grails.gorm.graphql.entity.dsl.helpers.Named -import org.grails.gorm.graphql.entity.dsl.helpers.Nullable -import org.grails.gorm.graphql.types.GraphQLTypeManager - -import static graphql.schema.GraphQLArgument.newArgument - -/** - * Describes an argument to a custom operation - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -abstract class CustomArgument implements Named, Describable, Nullable, Defaultable { - - CustomArgument() { - nullable = false - } - - abstract GraphQLInputType getType(GraphQLTypeManager typeManager, MappingContext mappingContext) - - GraphQLArgument.Builder getArgument(GraphQLTypeManager typeManager, MappingContext mappingContext) { - GraphQLInputType type = getType(typeManager, mappingContext) - - newArgument() - .name(name) - .description(description) - .defaultValue(defaultValue) - .type(type) - } - - void validate() { - if (name == null) { - throw new IllegalArgumentException('A name is required for creating custom operations') - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/arguments/SimpleArgument.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/arguments/SimpleArgument.groovy deleted file mode 100644 index 27c3b2aa..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/arguments/SimpleArgument.groovy +++ /dev/null @@ -1,40 +0,0 @@ -package org.grails.gorm.graphql.entity.arguments - -import graphql.schema.GraphQLInputType -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.datastore.mapping.model.MappingContext -import org.grails.gorm.graphql.entity.dsl.helpers.Typed -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * Used to create arguments to custom operations that are a simple type - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@InheritConstructors -class SimpleArgument extends CustomArgument implements Typed { - - GraphQLPropertyType propertyType = GraphQLPropertyType.UPDATE - - SimpleArgument propertyType(GraphQLPropertyType propertyType) { - this.propertyType = propertyType - this - } - - @Override - GraphQLInputType getType(GraphQLTypeManager typeManager, MappingContext mappingContext) { - resolveInputType(typeManager, mappingContext, nullable, propertyType) - } - - void validate() { - super.validate() - - if (returnType == null) { - throw new IllegalArgumentException('A return type is required for creating arguments to custom operations') - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/GraphQLMapping.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/GraphQLMapping.groovy deleted file mode 100644 index c6238e35..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/GraphQLMapping.groovy +++ /dev/null @@ -1,364 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl - -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.entity.dsl.helpers.Deprecatable -import org.grails.gorm.graphql.entity.dsl.helpers.Describable -import org.grails.gorm.graphql.entity.dsl.helpers.ExecutesClosures -import org.grails.gorm.graphql.entity.operations.ComplexOperation -import org.grails.gorm.graphql.entity.operations.CustomOperation -import org.grails.gorm.graphql.entity.operations.OperationType -import org.grails.gorm.graphql.entity.operations.SimpleOperation -import org.grails.gorm.graphql.entity.property.impl.ComplexGraphQLProperty -import org.grails.gorm.graphql.entity.property.impl.CustomGraphQLProperty -import org.grails.gorm.graphql.entity.property.impl.SimpleGraphQLProperty -import org.grails.gorm.graphql.response.pagination.PaginatedType -import org.springframework.beans.MutablePropertyValues -import org.springframework.validation.DataBinder - -/** - * DSL to provide GraphQL specific data for a GORM entity - * - * Usage: - *
- * {@code
- * static graphql = {
- *     exclude 'foo'
- *     add('bar', String)
- *     description 'Business users'
- * }
- * //OR: For code completion
- * static graphql = GraphQLMapping.build {
- *     ...
- * }
- * 
- * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class GraphQLMapping implements Describable, Deprecatable, ExecutesClosures { - - private List additional = [] - private Map propertyMappings = [:] - Set excluded = [] as Set - Operations operations = new Operations() - private List customQueryOperations = [] - private List customMutationOperations = [] - - List getAdditional() { - new ArrayList(additional) - } - - Map getPropertyMappings() { - new HashMap(propertyMappings) - } - - List getCustomQueryOperations() { - new ArrayList(customQueryOperations) - } - - List getCustomMutationOperations() { - new ArrayList(customMutationOperations) - } - - /** - * Exclude one or more properties from being included in the schema - * - * @param properties One or more property names - */ - void exclude(String... properties) { - excluded.addAll(properties) - } - - /** - * Add a new property to be included in the schema. The property may - * or may not be backed by an instance method depending on whether or - * not the property is to be used for response. - * - * @param property The property to include - */ - void add(CustomGraphQLProperty property) { - property.validate() - additional.add(property) - } - - /** - * Add a new property to be included in the schema. The property may - * or may not be backed by an instance method depending on whether or - * not the property is to be used as a part of a response. - * - * @param name The name of property to include - * @param type The returnType of property to include - * @param closure A closure to further configure the property - */ - void add(String name, Class type, @DelegatesTo(value = SimpleGraphQLProperty, strategy = Closure.DELEGATE_ONLY) Closure closure = null) { - CustomGraphQLProperty property = new SimpleGraphQLProperty().name(name).returns(type) - withDelegate(closure, property) - add(property) - } - - /** - * Add a new property to be included in the schema. The property may - * or may not be backed by an instance method depending on whether or - * not the property is to be used as a part of a response. The provided - * list must contain exactly 1 element that is a class. - * - * @param name The name of property to include - * @param type The returnType of property to include - * @param closure A closure to further configure the property - */ - void add(String name, List type, @DelegatesTo(value = SimpleGraphQLProperty, strategy = Closure.DELEGATE_ONLY) Closure closure = null) { - CustomGraphQLProperty property = new SimpleGraphQLProperty().name(name).returns(type) - withDelegate(closure, property) - add(property) - } - - /** - * Add a new property to be included in the schema. The property may - * or may not be backed by an instance method depending on whether or - * not the property is to be used for response. Use this method to define - * a complex type for the property with the returns block. - * - * @param name The name of property to include - * @param typeName The name of the custom type being created - * @param closure A closure to further configure the property - */ - void add(String name, String typeName, @DelegatesTo(value = ComplexGraphQLProperty, strategy = Closure.DELEGATE_ONLY) Closure closure) { - CustomGraphQLProperty property = new ComplexGraphQLProperty().name(name).typeName(typeName) - withDelegate(closure, property) - add(property) - } - - /** - * Supply metadata about an existing property - * - * @param name The property name - * @param closure The closure to build the metadata - * @return The property mapping instance - */ - GraphQLPropertyMapping property(String name, @DelegatesTo(value = GraphQLPropertyMapping, strategy = Closure.DELEGATE_ONLY) Closure closure) { - GraphQLPropertyMapping mapping = GraphQLPropertyMapping.build(closure) - property(name, mapping) - } - - /** - * Supply metadata about an existing property - * - * Example: property('foo', [input: false]) - * - * @param name The property name - * @param namedArgs The arguments to build the mapping - * @return The property mapping instance - */ - GraphQLPropertyMapping property(String name, Map namedArgs) { - GraphQLPropertyMapping mapping = new GraphQLPropertyMapping() - DataBinder dataBinder = new DataBinder(mapping) - dataBinder.bind(new MutablePropertyValues(namedArgs)) - property(name, mapping) - } - - /** - * Supply metadata about an existing property - * - * Example: property('foo', input: false) - * - * @param name The property name - * @param namedArgs The arguments to build the mapping - * @return The property mapping instance - */ - GraphQLPropertyMapping property(Map namedArgs, String name) { - property(name, namedArgs) - } - - /** - * Supply metadata about an existing property - * - * @param name The property name - * @param mapping The property mapping instance - * @return The property mapping instance provided - */ - GraphQLPropertyMapping property(String name, GraphQLPropertyMapping mapping) { - propertyMappings.put(name, mapping) - mapping - } - - /** - * Supplies configuration for an existing property - * - * Usage: - * - * foo { - * description "Foo" - * } - * - * foo description: "Foo" - * - * //Provides code completion - * foo GraphQLPropertyMapping.build { - * description("Foo") - * } - * - * @see GraphQLPropertyMapping - */ - @CompileDynamic - Object methodMissing(String name, Object args) { - if (args && args.getClass().array) { - - if (args[0] instanceof Closure) { - property(name, (Closure) args[0]) - } - else if (args[0] instanceof GraphQLPropertyMapping) { - propertyMappings.put(name, (GraphQLPropertyMapping) args[0]) - } - else if (args[0] instanceof Map) { - property(name, (Map) args[0]) - } - else { - throw new MissingMethodException(name, getClass(), args) - } - } - else { - throw new MissingMethodException(name, getClass(), args) - } - } - - /** - * Builder to provide code completion. The mapping instance will not be evaluated - * until the schema is being generated - * - * @param closure The closure to execute in the context of a mapping - * @return The mapping instance - */ - static LazyGraphQLMapping lazy(@DelegatesTo(value = GraphQLMapping, strategy = Closure.DELEGATE_ONLY) Closure closure) { - new LazyGraphQLMapping(closure) - } - - /** - * Builder to provide code completion - * - * @param closure The closure to execute in the context of a mapping - * @return The mapping instance - */ - static GraphQLMapping build(@DelegatesTo(value = GraphQLMapping, strategy = Closure.DELEGATE_ONLY) Closure closure) { - GraphQLMapping mapping = new GraphQLMapping() - withDelegate(closure, mapping) - mapping - } - - private CustomOperation handleCustomOperation(CustomOperation operation, OperationType type, @DelegatesTo(strategy = Closure.DELEGATE_ONLY)Closure closure) { - operation.operationType = type - withDelegate(closure, operation) - operation.validate() - operation - } - - /** - * Builds a custom query operation with a complex type to be - * built in the provided closure. - * - * @param name The name used by clients of the GraphQL API to execute the operation - * @param typeName The name of the custom type returned from the operation - * @param closure The closure to build the operation - */ - void query(String name, String typeName, @DelegatesTo(value = ComplexOperation, strategy = Closure.DELEGATE_ONLY) Closure closure) { - ComplexOperation operation = new ComplexOperation().name(name).typeName(typeName) - handleCustomOperation(operation, OperationType.QUERY, closure) - customQueryOperations.add(operation) - } - - /** - * Builds a custom query operation. The provided list must ontain exactly 1 - * element that is a class. This method indicates the return type will be a list. - * - * @param name The name used by clients of the GraphQL API to execute the operation - * @param type The return type. A list with exactly 1 element that is a class. The - * class may be an enum, simple type, or domain class. - * @param closure The closure to build the operation - */ - void query(String name, List type, @DelegatesTo(value = SimpleOperation, strategy = Closure.DELEGATE_ONLY) Closure closure) { - SimpleOperation operation = new SimpleOperation().name(name).returns(type) - handleCustomOperation(operation, OperationType.QUERY, closure) - customQueryOperations.add(operation) - } - - /** - * Builds a custom query operation. - * - * @param name The name used by clients of the GraphQL API to execute the operation - * @param type The return type. May be an enum, simple class, or domain class. - * @param closure The closure to build the operation - */ - void query(String name, Class type, @DelegatesTo(value = SimpleOperation, strategy = Closure.DELEGATE_ONLY) Closure closure) { - SimpleOperation operation = new SimpleOperation().name(name).returns(type) - handleCustomOperation(operation, OperationType.QUERY, closure) - customQueryOperations.add(operation) - } - - /** - * Builds a custom query operation that returns a paginated result. - * - * @param name The name used by clients of the GraphQL API to execute the operation - * @param type The return type. May be an enum, simple class, or domain class. - * @param closure The closure to build the operation - */ - void query(String name, PaginatedType type, @DelegatesTo(value = SimpleOperation, strategy = Closure.DELEGATE_ONLY) Closure closure) { - SimpleOperation operation = new SimpleOperation().name(name).returns(type.type) - operation.paginated = true - handleCustomOperation(operation, OperationType.QUERY, closure) - customQueryOperations.add(operation) - } - - /** - * Denotes the return type of an operation should be paginated - * - * @param type The domain class being returned - * @return The type holder - */ - PaginatedType pagedResult(Class type) { - new PaginatedType(type: type) - } - - /** - * Builds a custom mutation operation with a complex type to be - * built in the provided closure. - * - * @param name The name used by clients of the GraphQL API to execute the operation - * @param typeName The name of the custom type returned from the operation - * @param closure The closure to build the operation - */ - void mutation(String name, String typeName, @DelegatesTo(value = ComplexOperation, strategy = Closure.DELEGATE_ONLY) Closure closure) { - ComplexOperation operation = new ComplexOperation().name(name).typeName(typeName) - handleCustomOperation(operation, OperationType.MUTATION, closure) - customMutationOperations.add(operation) - } - - /** - * Builds a custom mutation operation. - * - * @param name The name used by clients of the GraphQL API to execute the operation - * @param type The return type. May be an enum, simple class, or domain class. - * @param closure The closure to build the operation - */ - void mutation(String name, Class type, @DelegatesTo(value = SimpleOperation, strategy = Closure.DELEGATE_ONLY) Closure closure) { - SimpleOperation operation = new SimpleOperation().name(name).returns(type) - handleCustomOperation(operation, OperationType.MUTATION, closure) - customMutationOperations.add(operation) - } - - /** - * Builds a custom mutation operation. The provided list must ontain exactly 1 - * element that is a class. This method indicates the return type will be a list. - * - * @param name The name used by clients of the GraphQL API to execute the operation - * @param type The return type. A list with exactly 1 element that is a class. The - * class may be an enum, simple type, or domain class. - * @param closure The closure to build the operation - */ - void mutation(String name, List type, @DelegatesTo(value = SimpleOperation, strategy = Closure.DELEGATE_ONLY) Closure closure) { - SimpleOperation operation = new SimpleOperation().name(name).returns(type) - handleCustomOperation(operation, OperationType.MUTATION, closure) - customMutationOperations.add(operation) - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/GraphQLPropertyMapping.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/GraphQLPropertyMapping.groovy deleted file mode 100644 index ada0ad26..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/GraphQLPropertyMapping.groovy +++ /dev/null @@ -1,76 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl - -import groovy.transform.CompileStatic -import groovy.transform.builder.Builder -import groovy.transform.builder.SimpleStrategy -import org.grails.gorm.graphql.entity.dsl.helpers.Deprecatable -import org.grails.gorm.graphql.entity.dsl.helpers.Describable -import org.grails.gorm.graphql.entity.dsl.helpers.ExecutesClosures -import org.grails.gorm.graphql.entity.dsl.helpers.Named - -/** - * Builder to provide GraphQL specific data for a GORM entity property - * - * Usage: - *
- * {@code
- * static graphql = {
- *     someProperty input: false, description: "foo"
- *     otherProperty {
- *         input false
- *         description "otherFoo"
- *     }
- *     //OR: For code completion
- *     otherProperty GraphQLPropertyMapping.build {
- *
- *     }
- *     //If the property name conflicts with a existing method name ex: "description"
- *     property("description") {
- *         ...
- *     }
- *     property "description", [:]
- * }
- * }
- * 
- * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@Builder(builderStrategy = SimpleStrategy, prefix = '') -class GraphQLPropertyMapping implements Describable, Deprecatable, Named, ExecutesClosures { - - /** - * Whether or not the property should be available to - * be sent by the client in CREATE or UPDATE operations - */ - boolean input = true - - /** - * Whether or not the property should be available to - * be requested by the client - */ - boolean output = true - - /** - * Override whether the property is nullable. - * Only takes effect for CREATE types - */ - Boolean nullable - - /** - * The fetcher to retrieve the property - */ - Closure dataFetcher - - /** - * The order the property will be in the schema - */ - Integer order - - static GraphQLPropertyMapping build(@DelegatesTo(value = GraphQLPropertyMapping, strategy = Closure.DELEGATE_ONLY) Closure closure) { - GraphQLPropertyMapping mapping = new GraphQLPropertyMapping() - withDelegate(closure, mapping) - mapping - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/LazyGraphQLMapping.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/LazyGraphQLMapping.groovy deleted file mode 100644 index 08fac612..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/LazyGraphQLMapping.groovy +++ /dev/null @@ -1,28 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl - -import org.grails.gorm.graphql.entity.dsl.helpers.ExecutesClosures - -/** - * A class to lazy initialize GraphQL mappings on - * GORM entities. This is to allow users to access the - * mapping context API (for example to specify data fetching - * instances) inside of the mapping closure without needing - * the API to be available - * - * @author James Kleeh - * @since 1.0.0 - */ -class LazyGraphQLMapping implements ExecutesClosures { - - Closure closure - - protected LazyGraphQLMapping(Closure closure) { - this.closure = closure - } - - GraphQLMapping initialize() { - GraphQLMapping mapping = new GraphQLMapping() - withDelegate(closure, mapping) - mapping - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/Operations.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/Operations.groovy deleted file mode 100644 index 53c82e4b..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/Operations.groovy +++ /dev/null @@ -1,26 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl - -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.entity.operations.ListOperation -import org.grails.gorm.graphql.entity.operations.ProvidedOperation - -/** - * Stores metadata about the default operations provided - * by this library - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class Operations { - - ProvidedOperation mutation = new ProvidedOperation() - ProvidedOperation query = new ProvidedOperation() - ProvidedOperation all = new ProvidedOperation() - ProvidedOperation get = new ProvidedOperation() - ListOperation list = new ListOperation() - ProvidedOperation create = new ProvidedOperation() - ProvidedOperation update = new ProvidedOperation() - ProvidedOperation delete = new ProvidedOperation() - ProvidedOperation count = new ProvidedOperation() -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Arguable.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Arguable.groovy deleted file mode 100644 index fd3188da..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Arguable.groovy +++ /dev/null @@ -1,77 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl.helpers - -import graphql.schema.GraphQLArgument -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.MappingContext -import org.grails.gorm.graphql.entity.arguments.ComplexArgument -import org.grails.gorm.graphql.entity.arguments.CustomArgument -import org.grails.gorm.graphql.entity.arguments.SimpleArgument -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * Decorates a class with a description property and builder method. - * - * @param The implementing class - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -trait Arguable extends ExecutesClosures { - - List arguments = [] - - private void handleArgumentClosure(CustomArgument argument, @DelegatesTo(strategy = Closure.DELEGATE_ONLY)Closure closure) { - withDelegate(closure, (Object)argument) - argument.validate() - arguments.add(argument) - } - - List getArguments(GraphQLTypeManager typeManager, MappingContext mappingContext) { - arguments.collect { - it.getArgument(typeManager, mappingContext).build() - } - } - - /** - * Creates an argument to the operation that is a list of a simple type. - * The list can not have more than 1 element and that element must be a class. - * - * @param name The name of the argument - * @param type The returnType of the argument - * @param closure To provide additional data about the argument - * @return The operation in order to chain method calls - */ - T argument(String name, List> type, @DelegatesTo(value = SimpleArgument, strategy = Closure.DELEGATE_ONLY) Closure closure = null) { - CustomArgument argument = new SimpleArgument().name(name).returns(type) - handleArgumentClosure(argument, closure) - (T)this - } - - /** - * Creates an argument to the operation that is of the returnType provided. - * - * @param name The name of the argument - * @param type The returnType of the argument - * @param closure To provide additional data about the argument - * @return The operation in order to chain method calls - */ - T argument(String name, Class type, @DelegatesTo(value = SimpleArgument, strategy = Closure.DELEGATE_ONLY) Closure closure = null) { - CustomArgument argument = new SimpleArgument().name(name).returns(type) - handleArgumentClosure(argument, closure) - (T)this - } - - /** - * Creates an argument to the operation that is a custom type. - * - * @param name The name of the argument - * @param closure To provide additional data about the argument - * @return The operation in order to chain method calls - */ - T argument(String name, String typeName, @DelegatesTo(value = ComplexArgument, strategy = Closure.DELEGATE_ONLY) Closure closure) { - CustomArgument argument = new ComplexArgument().name(name).typeName(typeName) - handleArgumentClosure(argument, closure) - (T)this - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/ComplexTyped.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/ComplexTyped.groovy deleted file mode 100644 index 5c4fab38..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/ComplexTyped.groovy +++ /dev/null @@ -1,138 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl.helpers - -import graphql.schema.* -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.MappingContext -import org.grails.gorm.graphql.entity.fields.ComplexField -import org.grails.gorm.graphql.entity.fields.Field -import org.grails.gorm.graphql.entity.fields.SimpleField -import org.grails.gorm.graphql.types.GraphQLTypeManager - -import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition -import static graphql.schema.GraphQLInputObjectField.newInputObjectField - -/** - * Decorates a class with the ability to build a custom type - * - * @param The implementing class - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -trait ComplexTyped extends ExecutesClosures { - - boolean collection = false - - T collection(boolean collection) { - this.collection = collection - (T)this - } - - List fields = [] - - boolean defaultNull = true - - T defaultNull(boolean defaultNull) { - this.defaultNull = defaultNull - (T)this - } - - /** - * Builds a custom object returnType if the supplied return returnType is a Map - * - * @param typeManager The returnType manager - * @param mappingContext The mapping context - * @return The custom returnType - */ - GraphQLOutputType buildCustomType(String name, GraphQLTypeManager typeManager, MappingContext mappingContext) { - GraphQLObjectType.Builder builder = GraphQLObjectType.newObject() - .name(name) - - for (Field field: fields) { - if (field.output) { - builder.field(newFieldDefinition() - .name(field.name) - .description(field.description) - .deprecate(field.deprecationReason) - .type(field.getType(typeManager, mappingContext))) - } - } - GraphQLObjectType type = builder.build() - - if (collection) { - GraphQLList.list(type) - } - else { - type - } - } - - private GraphQLInputType customInputType - - /** - * Builds a custom object returnType if the supplied return returnType is a Map - * - * @param typeManager The returnType manager - * @param mappingContext The mapping context - * @return The custom returnType - */ - GraphQLInputType buildCustomInputType(String name, GraphQLTypeManager typeManager, MappingContext mappingContext, boolean nullable) { - if (customInputType == null) { - GraphQLInputObjectType.Builder builder = GraphQLInputObjectType.newInputObject() - .name(name) - - for (Field field: fields) { - if (field.input) { - builder.field(newInputObjectField() - .name(field.name) - .description(field.description) - .defaultValue(field.defaultValue) - .type(field.getInputType(typeManager, mappingContext))) - } - } - GraphQLInputType type = builder.build() - - if (!nullable) { - type = GraphQLNonNull.nonNull(type) - } - - if (collection) { - type = GraphQLList.list((GraphQLInputType) type) - } - customInputType = (GraphQLInputType) type - } - - customInputType - } - - private void handleField(@DelegatesTo(strategy = Closure.DELEGATE_ONLY)Closure closure, Field field) { - field.nullable(defaultNull) - withDelegate(closure, (Object)field) - handleField(field) - } - - private void handleField(Field field) { - field.validate() - fields.add(field) - } - - void field(String name, List type, @DelegatesTo(value = SimpleField, strategy = Closure.DELEGATE_ONLY) Closure closure = null) { - Field field = new SimpleField().name(name).returns(type) - handleField(closure, field) - } - - void field(String name, Class type, @DelegatesTo(value = SimpleField, strategy = Closure.DELEGATE_ONLY) Closure closure = null) { - Field field = new SimpleField().name(name).returns(type) - handleField(closure, field) - } - - void field(String name, String typeName, @DelegatesTo(value = ComplexField, strategy = Closure.DELEGATE_ONLY) Closure closure) { - Field field = new ComplexField().name(name).typeName(typeName) - handleField(closure, field) - } - - void field(ComplexField field) { - handleField(field) - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Defaultable.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Defaultable.groovy deleted file mode 100644 index 570409ab..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Defaultable.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl.helpers - -import groovy.transform.CompileStatic - -/** - * Decorates a class with the ability to store a default value - * - * @param The implementing class - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -trait Defaultable { - - Object defaultValue - - T defaultValue(Object defaultValue) { - this.defaultValue = defaultValue - (T)this - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Deprecatable.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Deprecatable.groovy deleted file mode 100644 index 17538b5e..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Deprecatable.groovy +++ /dev/null @@ -1,34 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl.helpers - -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.Schema - -/** - * Decorates a class with a builder syntax to provide - * deprecation data. - * - * @param The implementing class - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -trait Deprecatable { - - boolean deprecated = false - String deprecationReason - - T deprecated(boolean deprecated) { - this.deprecated = deprecated - (T)this - } - - T deprecationReason(String deprecationReason) { - this.deprecationReason = deprecationReason - (T)this - } - - String getDeprecationReason() { - deprecationReason ?: (deprecated ? Schema.DEFAULT_DEPRECATION_REASON : null) - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Describable.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Describable.groovy deleted file mode 100644 index 2dec2aef..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Describable.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl.helpers - -import groovy.transform.CompileStatic - -/** - * Decorates a class with a description property and builder method. - * - * @param The implementing class - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -trait Describable { - - String description - - T description(String description) { - this.description = description - (T)this - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/ExecutesClosures.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/ExecutesClosures.groovy deleted file mode 100644 index be94b8e4..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/ExecutesClosures.groovy +++ /dev/null @@ -1,28 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl.helpers - -import groovy.transform.CompileStatic - -/** - * Decorates a class with the ability to execute closures with - * a delegate - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -trait ExecutesClosures { - - static void withDelegate(@DelegatesTo(strategy = Closure.DELEGATE_ONLY)Closure closure, Object delegate) { - if (closure != null) { - closure.resolveStrategy = Closure.DELEGATE_ONLY - closure.delegate = delegate - - try { - closure.call() - } finally { - closure.delegate = null - } - } - } -} - diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Named.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Named.groovy deleted file mode 100644 index e980873f..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Named.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl.helpers - -import groovy.transform.CompileStatic - -/** - * Decorates a class with a name property and builder method - * - * @param The class the trait is applied to - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -trait Named { - - String name - - T name(String name) { - this.name = name - (T)this - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Nullable.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Nullable.groovy deleted file mode 100644 index 61ddc6d2..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Nullable.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl.helpers - -import groovy.transform.CompileStatic - -/** - * Decorates a class with a nullable property and builder method - * - * @param The class the trait is applied to - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -trait Nullable { - - boolean nullable = true - - T nullable(boolean nullable) { - this.nullable = nullable - (T)this - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Typed.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Typed.groovy deleted file mode 100644 index 793761f4..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/dsl/helpers/Typed.groovy +++ /dev/null @@ -1,92 +0,0 @@ -package org.grails.gorm.graphql.entity.dsl.helpers - -import graphql.schema.GraphQLInputType -import graphql.schema.GraphQLOutputType -import graphql.schema.GraphQLType -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.types.GraphQLOperationType -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.types.GraphQLTypeManager -import org.grails.gorm.graphql.types.TypeNotFoundException - -import static graphql.schema.GraphQLList.list - -/** - * Parses types for custom arguments, operations, and properties - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -trait Typed { - - Class returnType - boolean collection = false - boolean paginated = false - - T returns(List list) { - if (list.empty || list.size() > 1 || !(list[0] instanceof Class)) { - throw new IllegalArgumentException('When setting the returnType of a custom operation or argument with a list, the list may only have one element that is a class.') - } - returnType = (Class)list[0] - collection = true - (T)this - } - - T returns(Class clazz) { - returnType = clazz - collection = false - (T)this - } - - GraphQLInputType resolveInputType(GraphQLTypeManager typeManager, MappingContext mappingContext, boolean nullable, GraphQLPropertyType propertyType = GraphQLPropertyType.CREATE) { - (GraphQLInputType)resolveType(typeManager, mappingContext, propertyType, nullable) - } - - GraphQLType resolveType(GraphQLTypeManager typeManager, MappingContext mappingContext, GraphQLPropertyType propertyType, boolean nullable) { - GraphQLType graphQLType - Class type = returnType - - if (type.enum) { - graphQLType = typeManager.getEnumType(type, nullable) - } - else if (typeManager.hasType(type)) { - graphQLType = typeManager.getType(type, nullable) - } - else { - PersistentEntity entity = mappingContext?.getPersistentEntity(type.name) - - if (entity != null) { - if (propertyType.operationType == GraphQLOperationType.OUTPUT) { - graphQLType = typeManager.getQueryType(entity, propertyType) - } - else { - graphQLType = typeManager.getMutationType(entity, propertyType, nullable) - } - } - else { - throw new TypeNotFoundException(type) - } - } - - if (collection) { - graphQLType = list(graphQLType) - } - - graphQLType - } - - GraphQLOutputType resolveOutputType(GraphQLTypeManager typeManager, MappingContext mappingContext) { - GraphQLPropertyType propertyType - if (paginated) { - propertyType = GraphQLPropertyType.OUTPUT_PAGED - } - else { - propertyType = GraphQLPropertyType.OUTPUT - } - (GraphQLOutputType)resolveType(typeManager, mappingContext, propertyType, true) - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/fields/ComplexField.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/fields/ComplexField.groovy deleted file mode 100644 index 1534f538..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/fields/ComplexField.groovy +++ /dev/null @@ -1,46 +0,0 @@ -package org.grails.gorm.graphql.entity.fields - -import graphql.schema.GraphQLInputType -import graphql.schema.GraphQLOutputType -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.MappingContext -import org.grails.gorm.graphql.entity.dsl.helpers.ComplexTyped -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * A class used to represent a field that has a custom (complex) type - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class ComplexField extends Field implements ComplexTyped { - - String typeName - - ComplexField typeName(String typeName) { - this.typeName = typeName - this - } - - @Override - GraphQLOutputType getType(GraphQLTypeManager typeManager, MappingContext mappingContext) { - buildCustomType(typeName, typeManager, mappingContext) - } - - @Override - GraphQLInputType getInputType(GraphQLTypeManager typeManager, MappingContext mappingContext) { - buildCustomInputType(typeName + 'Input', typeManager, mappingContext, nullable) - } - - @Override - void validate() { - super.validate() - if (typeName == null) { - throw new IllegalArgumentException('The type name must be specified for fields with a complex type') - } - if (fields.empty) { - throw new IllegalArgumentException('At least 1 field is required for fields with a complex type') - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/fields/Field.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/fields/Field.groovy deleted file mode 100644 index 1db70af0..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/fields/Field.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package org.grails.gorm.graphql.entity.fields - -import graphql.schema.GraphQLInputType -import graphql.schema.GraphQLOutputType -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.MappingContext -import org.grails.gorm.graphql.entity.dsl.helpers.Deprecatable -import org.grails.gorm.graphql.entity.dsl.helpers.Describable -import org.grails.gorm.graphql.entity.dsl.helpers.Named -import org.grails.gorm.graphql.entity.dsl.helpers.Nullable -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * Generic class used to represent a field in a custom object. Used - * in arguments, operations, and custom properties. - * - * @param The implementing class - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -abstract class Field implements Named, Describable, Deprecatable, Nullable { - - Object defaultValue - boolean input = true - boolean output = true - - T defaultValue(Object defaultValue) { - this.defaultValue = defaultValue - (T)this - } - - T input(boolean input) { - this.input = input - (T)this - } - - T output(boolean output) { - this.output = output - (T)this - } - - abstract GraphQLOutputType getType(GraphQLTypeManager typeManager, MappingContext mappingContext) - - abstract GraphQLInputType getInputType(GraphQLTypeManager typeManager, MappingContext mappingContext) - - void validate() { - if (name == null) { - throw new IllegalArgumentException('A name is required for a custom field') - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/fields/SimpleField.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/fields/SimpleField.groovy deleted file mode 100644 index fa25c00c..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/fields/SimpleField.groovy +++ /dev/null @@ -1,43 +0,0 @@ -package org.grails.gorm.graphql.entity.fields - -import graphql.schema.GraphQLInputType -import graphql.schema.GraphQLOutputType -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.entity.dsl.helpers.Typed -import org.grails.datastore.mapping.model.MappingContext -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * A field with a simple type. {@see Field} - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class SimpleField extends Field implements Typed { - - GraphQLPropertyType propertyType = GraphQLPropertyType.UPDATE - - SimpleField propertyType(GraphQLPropertyType propertyType) { - this.propertyType = propertyType - this - } - - GraphQLOutputType getType(GraphQLTypeManager typeManager, MappingContext mappingContext) { - resolveOutputType(typeManager, mappingContext) - } - - @Override - GraphQLInputType getInputType(GraphQLTypeManager typeManager, MappingContext mappingContext) { - resolveInputType(typeManager, mappingContext, nullable, propertyType) - } - - void validate() { - super.validate() - - if (returnType == null) { - throw new IllegalArgumentException('A return type is required for creating fields') - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/ComplexOperation.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/ComplexOperation.groovy deleted file mode 100644 index f8b74b82..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/ComplexOperation.groovy +++ /dev/null @@ -1,47 +0,0 @@ -package org.grails.gorm.graphql.entity.operations - -import graphql.schema.GraphQLOutputType -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.MappingContext -import org.grails.gorm.graphql.entity.dsl.helpers.ComplexTyped -import org.grails.gorm.graphql.entity.dsl.helpers.ExecutesClosures -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * Used to create custom operations with custom (complex) types - * - * @author James Kleeh - * @since 1.0.0 - */ - -@CompileStatic -class ComplexOperation extends CustomOperation implements ExecutesClosures { - - String typeName - - ComplexOperation typeName(String typeName) { - this.typeName = typeName - this - } - - private ComplexTyped returns = new Object().withTraits(ComplexTyped) - - void returns(@DelegatesTo(value = ComplexTyped, strategy = Closure.DELEGATE_ONLY) Closure closure) { - withDelegate(closure, returns) - } - - @Override - protected GraphQLOutputType getType(GraphQLTypeManager typeManager, MappingContext mappingContext) { - returns.buildCustomType(typeName, typeManager, mappingContext) - } - - void validate() { - super.validate() - if (typeName == null) { - throw new IllegalArgumentException('The type name must be specified for custom operations with a complex type') - } - if (returns.fields.empty) { - throw new IllegalArgumentException('At least 1 field is required for creating a custom operation with a complex type') - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/CustomOperation.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/CustomOperation.groovy deleted file mode 100644 index 5cd49e02..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/CustomOperation.groovy +++ /dev/null @@ -1,130 +0,0 @@ -package org.grails.gorm.graphql.entity.operations - -import graphql.schema.* -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.GraphQLServiceManager -import org.grails.gorm.graphql.entity.dsl.helpers.Arguable -import org.grails.gorm.graphql.entity.dsl.helpers.Deprecatable -import org.grails.gorm.graphql.entity.dsl.helpers.Describable -import org.grails.gorm.graphql.entity.dsl.helpers.ExecutesClosures -import org.grails.gorm.graphql.entity.dsl.helpers.Named -import org.grails.gorm.graphql.entity.arguments.CustomArgument -import org.grails.gorm.graphql.fetcher.interceptor.CustomMutationInterceptorInvoker -import org.grails.gorm.graphql.fetcher.interceptor.CustomQueryInterceptorInvoker -import org.grails.gorm.graphql.fetcher.interceptor.InterceptingDataFetcher -import org.grails.gorm.graphql.fetcher.interceptor.InterceptorInvoker -import org.grails.gorm.graphql.types.GraphQLTypeManager - -import static graphql.schema.GraphQLArgument.newArgument -import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition - -/** - * This class stores data about custom query operations - * that users provide in the mapping of the entity. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -abstract class CustomOperation implements Named, Describable, Deprecatable, Arguable, ExecutesClosures { - - private static InterceptorInvoker queryInvoker = new CustomQueryInterceptorInvoker() - private static InterceptorInvoker mutationInvoker = new CustomMutationInterceptorInvoker() - DataFetcher dataFetcher - boolean defaultListArguments = false - - T dataFetcher(DataFetcher dataFetcher) { - this.dataFetcher = dataFetcher - (T)this - } - - OperationType operationType - - /** - * If the argument is true, the default list arguments created in the - * schema through configuration will be prepended to any other - * arguments defined for the operation. - * (max, offset, sort, order, etc..) - * - * @param useDefaultListArguments Whether to use the default list args - * @return The operation in order to chain method calls - */ - CustomOperation defaultListArguments(boolean useDefaultListArguments = true) { - if (operationType == OperationType.MUTATION && useDefaultListArguments) { - throw new UnsupportedOperationException('The default list arguments are only supported for query operations') - } - this.defaultListArguments = useDefaultListArguments - this - } - - protected abstract GraphQLOutputType getType(GraphQLTypeManager typeManager, MappingContext mappingContext) - - void validate() { - if (name == null) { - throw new IllegalArgumentException('A name is required for creating custom operations') - } - if (dataFetcher == null) { - throw new IllegalArgumentException('A data fetcher is required for creating custom operations') - } - } - - protected DataFetcher buildDataFetcher(PersistentEntity entity, - GraphQLServiceManager serviceManager) { - InterceptorInvoker interceptorInvoker = null - if (operationType == OperationType.QUERY) { - interceptorInvoker = queryInvoker - } - else if (operationType == OperationType.MUTATION) { - interceptorInvoker = mutationInvoker - } - - new InterceptingDataFetcher(entity, serviceManager, interceptorInvoker, null, dataFetcher) - } - - /** - * Creates the field to be added to the query or mutation returnType in the schema. - * - * @param entity The persistent entity the operation belongs to - * @param typeManager The returnType manager - * @param interceptorManager The interceptor manager to be used for executing - * interceptors with the custom data fetcher - * @param mappingContext The mapping context - * @return The custom field - */ - GraphQLFieldDefinition.Builder createField(PersistentEntity entity, - GraphQLServiceManager serviceManager, - MappingContext mappingContext, - Map listArguments) { - - validate() - - GraphQLTypeManager typeManager = serviceManager.getService(GraphQLTypeManager) - - GraphQLOutputType outputType = getType(typeManager, mappingContext) - - GraphQLFieldDefinition.Builder customQuery = newFieldDefinition() - .name(name) - .type(outputType) - .description(description) - .deprecate(deprecationReason) - .dataFetcher(buildDataFetcher(entity, serviceManager)) - - if (defaultListArguments) { - for (Map.Entry argument: listArguments) { - customQuery.argument(newArgument() - .name(argument.key) - .type(argument.value)) - } - } - - if (!arguments.empty) { - for (CustomArgument argument: arguments) { - customQuery.argument(argument.getArgument(typeManager, mappingContext)) - } - } - - customQuery - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/ListOperation.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/ListOperation.groovy deleted file mode 100644 index 94d1e8f0..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/ListOperation.groovy +++ /dev/null @@ -1,22 +0,0 @@ -package org.grails.gorm.graphql.entity.operations - -import groovy.transform.CompileStatic -import groovy.transform.builder.Builder -import groovy.transform.builder.SimpleStrategy -import org.grails.gorm.graphql.entity.dsl.helpers.Deprecatable -import org.grails.gorm.graphql.entity.dsl.helpers.Describable - -/** - * Stores metadata about the list operation that this library - * provides by default. Also allows the user to disable the - * operation and convert the object type to support pagination. - * - * @author James Kleeh - * @since 1.0.0 - */ -@Builder(prefix = '', builderStrategy = SimpleStrategy) -@CompileStatic -class ListOperation implements Describable, Deprecatable { - boolean enabled = true - boolean paginate = false -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/OperationType.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/OperationType.groovy deleted file mode 100644 index df240c6b..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/OperationType.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package org.grails.gorm.graphql.entity.operations - -import groovy.transform.CompileStatic - -/** - * Used to determine if a custom operation is for - * querying or mutating. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -enum OperationType { - QUERY, - MUTATION -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/ProvidedOperation.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/ProvidedOperation.groovy deleted file mode 100644 index 37a833d4..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/ProvidedOperation.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package org.grails.gorm.graphql.entity.operations - -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.entity.dsl.helpers.Deprecatable -import org.grails.gorm.graphql.entity.dsl.helpers.Describable - -/** - * Stores metadata about the operations that this library - * provides by default. Also allows the user to disable the - * operation. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class ProvidedOperation implements Describable, Deprecatable { - - boolean enabled = true - - ProvidedOperation enabled(boolean enabled) { - this.enabled = enabled - this - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/SimpleOperation.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/SimpleOperation.groovy deleted file mode 100644 index a0a1c14c..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/operations/SimpleOperation.groovy +++ /dev/null @@ -1,64 +0,0 @@ -package org.grails.gorm.graphql.entity.operations - -import graphql.schema.DataFetcher -import graphql.schema.GraphQLOutputType -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.GraphQLServiceManager -import org.grails.gorm.graphql.binding.manager.GraphQLDataBinderManager -import org.grails.gorm.graphql.entity.dsl.helpers.Typed -import org.grails.gorm.graphql.fetcher.BindingGormDataFetcher -import org.grails.gorm.graphql.fetcher.DeletingGormDataFetcher -import org.grails.gorm.graphql.fetcher.PaginatingGormDataFetcher -import org.grails.gorm.graphql.response.delete.GraphQLDeleteResponseHandler -import org.grails.gorm.graphql.response.pagination.GraphQLPaginationResponseHandler -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * Used to create custom operations with simple types - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class SimpleOperation extends CustomOperation implements Typed { - - @Override - protected GraphQLOutputType getType(GraphQLTypeManager typeManager, MappingContext mappingContext) { - resolveOutputType(typeManager, mappingContext) - } - - protected DataFetcher buildDataFetcher(PersistentEntity entity, - GraphQLServiceManager serviceManager) { - - if (dataFetcher instanceof BindingGormDataFetcher) { - BindingGormDataFetcher bindingFetcher = ((BindingGormDataFetcher) dataFetcher) - if (bindingFetcher.dataBinder == null) { - bindingFetcher.dataBinder = serviceManager.getService(GraphQLDataBinderManager).getDataBinder(returnType) - } - } - if (dataFetcher instanceof DeletingGormDataFetcher) { - DeletingGormDataFetcher deletingFetcher = ((DeletingGormDataFetcher) dataFetcher) - if (deletingFetcher.responseHandler == null) { - deletingFetcher.responseHandler = serviceManager.getService(GraphQLDeleteResponseHandler) - } - } - if (dataFetcher instanceof PaginatingGormDataFetcher) { - PaginatingGormDataFetcher paginatingFetcher = (PaginatingGormDataFetcher) dataFetcher - if (paginatingFetcher.responseHandler == null) { - paginatingFetcher.responseHandler = serviceManager.getService(GraphQLPaginationResponseHandler) - } - } - - super.buildDataFetcher(entity, serviceManager) - } - - void validate() { - super.validate() - - if (returnType == null) { - throw new IllegalArgumentException('A return type is required for creating custom operations') - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/GraphQLDomainProperty.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/property/GraphQLDomainProperty.groovy deleted file mode 100644 index e00ea47a..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/GraphQLDomainProperty.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package org.grails.gorm.graphql.entity.property - -import graphql.schema.DataFetcher -import graphql.schema.GraphQLType -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * An interface to describe a property to be used in the - * creation of a GraphQL schema - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GraphQLDomainProperty { - - /** - * @return The name of the property - */ - String getName() - - /** - * @param typeManager The returnType manager used to retrieve GraphQL types - * @param propertyType The returnType of property being created - * @return The GraphQLType representing the property - */ - GraphQLType getGraphQLType(GraphQLTypeManager typeManager, GraphQLPropertyType propertyType) - - /** - * @return The description of the property - */ - String getDescription() - - /** - * @return True if the property is deprecated - */ - boolean isDeprecated() - - /** - * @return The reason why the property is deprecated, or null if it isn't - */ - String getDeprecationReason() - - /** - * @return True if the property is to be used for input operations (CREATE/UPDATE) - */ - boolean isInput() - - /** - * @return True if the property is to be used for output operations (GET/LIST) - */ - boolean isOutput() - - /** - * @return True if the property allows nulls - */ - boolean isNullable() - - /** - * @return The closure to retrieve the data for the property. If not null, it - * will be used to create a {@link org.grails.gorm.graphql.fetcher.impl.ClosureDataFetcher}, - * otherwise the default fetcher will be used. - */ - DataFetcher getDataFetcher() - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/ComplexGraphQLProperty.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/ComplexGraphQLProperty.groovy deleted file mode 100644 index ad299b14..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/ComplexGraphQLProperty.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package org.grails.gorm.graphql.entity.property.impl - -import graphql.schema.GraphQLType -import groovy.transform.AutoClone -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.entity.dsl.helpers.ComplexTyped -import org.grails.gorm.graphql.entity.dsl.helpers.ExecutesClosures -import org.grails.gorm.graphql.types.GraphQLOperationType -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * Used to represent a custom property that has a custom (complex) type - * - * @author James Kleeh - * @since 1.0.0 - */ -@AutoClone -@CompileStatic -class ComplexGraphQLProperty extends CustomGraphQLProperty implements ExecutesClosures { - - String typeName - - ComplexGraphQLProperty typeName(String typeName) { - this.typeName = typeName - this - } - - @Override - GraphQLType getGraphQLType(GraphQLTypeManager typeManager, GraphQLPropertyType propertyType) { - String name = typeManager.namingConvention.getType(typeName, propertyType) - - if (propertyType.operationType == GraphQLOperationType.OUTPUT) { - returns.buildCustomType(name, typeManager, mappingContext) - } - else { - returns.buildCustomInputType(name, typeManager, mappingContext, nullable) - } - } - - private ComplexTyped returns = new Object().withTraits(ComplexTyped) - - void type(@DelegatesTo(value = ComplexTyped, strategy = Closure.DELEGATE_ONLY) Closure closure) { - withDelegate(closure, returns) - } - - void validate() { - super.validate() - - if (typeName == null) { - throw new IllegalArgumentException('The type name must be specified for custom properties with a complex type') - } - if (returns.fields.empty) { - throw new IllegalArgumentException("$name: At least 1 field is required for creating a custom property") - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/CustomGraphQLProperty.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/CustomGraphQLProperty.groovy deleted file mode 100644 index 6420f5a2..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/CustomGraphQLProperty.groovy +++ /dev/null @@ -1,74 +0,0 @@ -package org.grails.gorm.graphql.entity.property.impl - -import graphql.schema.DataFetcher -import graphql.schema.GraphQLType -import groovy.transform.AutoClone -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.MappingContext -import org.grails.gorm.graphql.entity.dsl.helpers.Arguable -import org.grails.gorm.graphql.entity.dsl.helpers.Deprecatable -import org.grails.gorm.graphql.entity.dsl.helpers.Describable -import org.grails.gorm.graphql.entity.dsl.helpers.Named -import org.grails.gorm.graphql.entity.dsl.helpers.Nullable -import org.grails.gorm.graphql.entity.property.GraphQLDomainProperty -import org.grails.gorm.graphql.fetcher.impl.ClosureDataFetcher -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * Implementation of {@link GraphQLDomainProperty} to be used to define - * additional properties beyond the ones defined in GORM entities - * - * @author James Kleeh - * @since 1.0.0 - */ -@AutoClone -@CompileStatic -abstract class CustomGraphQLProperty extends OrderedGraphQLProperty implements Named, Describable, Deprecatable, Nullable, Arguable { - - Integer order = null - boolean input = true - boolean output = true - Closure closureDataFetcher = null - - T dataFetcher(Closure dataFetcher) { - this.closureDataFetcher = dataFetcher - (T)this - } - - T input(boolean input) { - this.input = input - (T)this - } - - T output(boolean output) { - this.output = output - (T)this - } - - T order(Integer order) { - this.order = order - (T)this - } - - //should be set by the property manager - protected MappingContext mappingContext - - void setMappingContext(MappingContext mappingContext) { - this.mappingContext = mappingContext - } - - @Override - abstract GraphQLType getGraphQLType(GraphQLTypeManager typeManager, GraphQLPropertyType propertyType) - - DataFetcher getDataFetcher() { - closureDataFetcher ? new ClosureDataFetcher(closureDataFetcher) : null - } - - void validate() { - if (name == null) { - throw new IllegalArgumentException('A name is required for creating custom properties') - } - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/OrderedGraphQLProperty.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/OrderedGraphQLProperty.groovy deleted file mode 100644 index aee3d5b0..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/OrderedGraphQLProperty.groovy +++ /dev/null @@ -1,37 +0,0 @@ -package org.grails.gorm.graphql.entity.property.impl - -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.entity.property.GraphQLDomainProperty - -/** - * A class to extend from to support the default sorting mechanism - * for GraphQL properties - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -abstract class OrderedGraphQLProperty implements GraphQLDomainProperty, Comparable { - - abstract Integer getOrder() - - @Override - int compareTo(OrderedGraphQLProperty o) { - if (order != null) { - if (o.order == null) { - -1 - } - else { - order <=> o.order ?: name <=> o.name - } - } - else { - if (o.order != null) { - 1 - } - else { - name <=> o.name - } - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/PersistentGraphQLProperty.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/PersistentGraphQLProperty.groovy deleted file mode 100644 index 4591d827..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/PersistentGraphQLProperty.groovy +++ /dev/null @@ -1,208 +0,0 @@ -package org.grails.gorm.graphql.entity.property.impl - -import grails.gorm.validation.ConstrainedProperty -import grails.gorm.validation.PersistentEntityValidator -import graphql.schema.DataFetcher -import graphql.schema.GraphQLType -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.config.Property -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.Basic -import org.grails.datastore.mapping.model.types.ToMany -import org.grails.gorm.graphql.GraphQL -import org.grails.gorm.graphql.Schema -import org.grails.gorm.graphql.entity.dsl.GraphQLPropertyMapping -import org.grails.gorm.graphql.entity.property.GraphQLDomainProperty -import org.grails.gorm.graphql.fetcher.impl.ClosureDataFetcher -import org.grails.gorm.graphql.fetcher.impl.PersistentPropertyDataFetcher -import org.grails.gorm.graphql.types.GraphQLOperationType -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.types.GraphQLTypeManager -import org.springframework.validation.Validator - -import java.lang.reflect.Field - -import static graphql.schema.GraphQLList.list - -/** - * Implementation of {@link GraphQLDomainProperty} to represent a property - * on a GORM entity - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class PersistentGraphQLProperty extends OrderedGraphQLProperty { - - final Integer order - final String name - final Class type - final boolean collection - final boolean nullable - String description - String deprecationReason - final boolean input - final boolean output - final DataFetcher dataFetcher - - PersistentProperty property - private MappingContext mappingContext - - private static final int DEFAULT_ID_ORDER = -20 - private static final int DEFAULT_VERSION_ORDER = -10 - - PersistentGraphQLProperty(MappingContext mappingContext, PersistentProperty property, GraphQLPropertyMapping mapping) { - this.property = property - this.mappingContext = mappingContext - this.name = mapping.name ?: property.name - this.type = getBaseType(property) - this.collection = (property instanceof ToMany) - if (mapping.nullable != null) { - this.nullable = mapping.nullable - } - else { - this.nullable = ((Property) property.mapping.mappedForm).nullable - } - this.output = mapping.output - this.input = mapping.input - this.dataFetcher = mapping.dataFetcher ? new ClosureDataFetcher(mapping.dataFetcher) : new PersistentPropertyDataFetcher((PersistentProperty) property) - if (mapping.order != null) { - this.order = mapping.order - } - else { - Validator validator = mappingContext.getEntityValidator(property.owner) - if (validator instanceof PersistentEntityValidator) { - ConstrainedProperty constrainedProperty = ((PersistentEntityValidator) validator).constrainedProperties.get(name) - if (constrainedProperty != null) { - this.order = constrainedProperty.order - } - } - } - if (this.order == null) { - if (isIdentifier(property.owner, name)) { - this.order = DEFAULT_ID_ORDER - } - else if (name == 'version') { - this.order = DEFAULT_VERSION_ORDER - } - } - - initializeMetadata(mapping) - } - - private void initializeMetadata(GraphQLPropertyMapping mapping) { - this.description = mapping.description - this.deprecationReason = mapping.deprecationReason - try { - Field field = property.owner.javaClass.getDeclaredField(property.name) - if (field != null) { - GraphQL graphQL = field.getAnnotation(GraphQL) - if (graphQL != null) { - if (description == null && !graphQL.value().empty) { - description = graphQL.value() - } - if (deprecationReason == null && !graphQL.deprecationReason().empty) { - deprecationReason = graphQL.deprecationReason() - } - if (graphQL.deprecated() && deprecationReason == null) { - deprecationReason = Schema.DEFAULT_DEPRECATION_REASON - } - } - if (field.getAnnotation(Deprecated) != null && deprecationReason == null) { - deprecationReason = Schema.DEFAULT_DEPRECATION_REASON - } - } - } catch (NoSuchFieldException e) { } - - if (mapping.deprecated && deprecationReason == null) { - deprecationReason = Schema.DEFAULT_DEPRECATION_REASON - } - } - - protected Class getBaseType(PersistentProperty property) { - if (property instanceof Association) { - Association association = (Association)property - if (association.basic) { - ((Basic) property).componentType - } - else { - association.associatedEntity.javaClass - } - } - else { - property.type - } - } - - @Override - boolean isDeprecated() { - deprecationReason != null - } - - @Override - GraphQLType getGraphQLType(GraphQLTypeManager typeManager, GraphQLPropertyType propertyType) { - GraphQLType graphQLType - - if (type.enum) { - graphQLType = typeManager.getEnumType(type, nullable) - } - else { - boolean embedded = false - PersistentEntity entity - if (property instanceof Association) { - Association association = ((Association)property) - entity = association.associatedEntity - embedded = association.embedded - } - if (entity == null) { - entity = mappingContext.getPersistentEntity(type.name) - } - if (entity != null) { - if (propertyType.operationType == GraphQLOperationType.OUTPUT) { - if (embedded) { - graphQLType = typeManager.getQueryType(entity, propertyType.embeddedType) - } - else { - graphQLType = typeManager.getQueryType(entity, GraphQLPropertyType.OUTPUT) - } - } - else { - GraphQLPropertyType mutationType - if (embedded) { - mutationType = propertyType.embeddedType - } - else { - mutationType = propertyType.nestedType - } - graphQLType = typeManager.getMutationType(entity, mutationType, nullable) - } - } - else { - graphQLType = typeManager.getType(type, nullable) - } - } - - if (collection) { - graphQLType = list(graphQLType) - } - - graphQLType - } - - private boolean isIdentifier(PersistentEntity entity, String name) { - if (entity.identity != null) { - return entity.identity.name == name - } - else if (entity.compositeIdentity != null) { - for (PersistentProperty property: entity.compositeIdentity) { - if (property.name == name) { - return true - } - } - } - false - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/SimpleGraphQLProperty.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/SimpleGraphQLProperty.groovy deleted file mode 100644 index cccfa5cd..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/impl/SimpleGraphQLProperty.groovy +++ /dev/null @@ -1,30 +0,0 @@ -package org.grails.gorm.graphql.entity.property.impl - -import graphql.schema.DataFetcher -import graphql.schema.GraphQLType -import groovy.transform.AutoClone -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.entity.dsl.helpers.Typed -import org.grails.gorm.graphql.fetcher.impl.ClosureDataFetcher -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * A class for creating custom properties that have a simple type - * - * @author James Kleeh - * @since 1.0.0 - */ -@AutoClone -@CompileStatic -class SimpleGraphQLProperty extends CustomGraphQLProperty implements Typed { - - @Override - GraphQLType getGraphQLType(GraphQLTypeManager typeManager, GraphQLPropertyType propertyType) { - resolveType(typeManager, mappingContext, propertyType, nullable) - } - - DataFetcher getDataFetcher() { - closureDataFetcher ? new ClosureDataFetcher(closureDataFetcher, returnType) : null - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/manager/DefaultGraphQLDomainPropertyManager.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/property/manager/DefaultGraphQLDomainPropertyManager.groovy deleted file mode 100644 index 44623c7b..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/manager/DefaultGraphQLDomainPropertyManager.groovy +++ /dev/null @@ -1,173 +0,0 @@ -package org.grails.gorm.graphql.entity.property.manager - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.config.Property -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.gorm.graphql.GraphQLEntityHelper -import org.grails.gorm.graphql.entity.dsl.GraphQLMapping -import org.grails.gorm.graphql.entity.dsl.GraphQLPropertyMapping -import org.grails.gorm.graphql.entity.property.GraphQLDomainProperty -import org.grails.gorm.graphql.entity.property.impl.CustomGraphQLProperty -import org.grails.gorm.graphql.entity.property.impl.PersistentGraphQLProperty - -import java.lang.reflect.Method - -/** - * A class to retrieve {@link PersistentProperty} instances in combination - * with a {@link GraphQLMapping} to produce a list of {@link GraphQLDomainProperty} - * instances used in creation of the GraphQL schema. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class DefaultGraphQLDomainPropertyManager implements GraphQLDomainPropertyManager { - - //To support older versions of GORM - private static Method derivedMethod - static { - try { - derivedMethod = Property.getMethod('isDerived', (Class[]) null) - } catch (NoSuchMethodException | SecurityException e) { } - } - - @Override - Builder builder() { - new Builder() - } - - private static class Builder implements GraphQLDomainPropertyManager.Builder { - Set excludedProperties = [] as Set - boolean identifiers = true - boolean compositeIdentifiers = true - Closure customCondition = null - boolean overrideNullable = false - - @Override - Builder excludeIdentifiers(boolean exceptComposite = false) { - this.identifiers = false - this.compositeIdentifiers = exceptComposite - this - } - - @Override - Builder excludeVersion() { - excludedProperties.add('version') - this - } - - @Override - Builder excludeTimestamps() { - excludedProperties.addAll(['dateCreated', 'lastUpdated']) - this - } - - @Override - Builder exclude(String... props) { - excludedProperties.addAll(props) - this - } - - @Override - Builder condition(Closure closure) { - this.customCondition = closure - this - } - - @Override - Builder alwaysNullable() { - this.overrideNullable = true - this - } - - @Override - List getProperties(PersistentEntity entity) { - getProperties(entity, GraphQLEntityHelper.getMapping(entity)) - } - - private GraphQLPropertyMapping getPropertyMapping(PersistentProperty property, GraphQLMapping mapping, boolean id = false) { - GraphQLPropertyMapping propertyMapping - if (mapping.propertyMappings.containsKey(property.name)) { - propertyMapping = mapping.propertyMappings.get(property.name) - } - else { - propertyMapping = new GraphQLPropertyMapping() - } - - if (overrideNullable) { - propertyMapping.nullable(true) - } - else if (id && propertyMapping.nullable == null) { - propertyMapping.nullable(false) - } - - if (derivedMethod != null) { - Property prop = property.mapping.mappedForm - if (derivedMethod.invoke(prop, (Object[]) null)) { - propertyMapping.input(false) - } - } - propertyMapping - } - - @Override - List getProperties(PersistentEntity entity, GraphQLMapping mapping) { - List properties = [] - MappingContext mappingContext = entity.mappingContext - if (mapping == null) { - mapping = new GraphQLMapping() - } - - if (identifiers) { - if (entity.identity != null) { - properties.add(new PersistentGraphQLProperty(mappingContext, entity.identity, getPropertyMapping(entity.identity, mapping))) - } - } - - if (compositeIdentifiers) { - if (entity.compositeIdentity != null) { - for (PersistentProperty prop: entity.compositeIdentity) { - properties.add( - new PersistentGraphQLProperty(mappingContext, prop, getPropertyMapping(prop, mapping)) - ) - } - } - } - - for (PersistentProperty prop: entity.persistentProperties) { - if (mapping.excluded.contains(prop.name)) { - continue - } - if (excludedProperties.contains(prop.name)) { - continue - } - if (customCondition != null && !customCondition.call(prop)) { - continue - } - if (prop.name == 'version' && !entity.versioned) { - continue - } - - properties.add(new PersistentGraphQLProperty(mappingContext, prop, getPropertyMapping(prop, mapping))) - } - - for (CustomGraphQLProperty property: mapping.additional) { - CustomGraphQLProperty prop - if (overrideNullable && !property.nullable) { - prop = (CustomGraphQLProperty)property.clone().nullable(true) - } - else { - prop = property - } - prop.mappingContext = mappingContext - properties.add(prop) - } - - properties.sort(true) - properties - } - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/manager/GraphQLDomainPropertyManager.groovy b/core/src/main/groovy/org/grails/gorm/graphql/entity/property/manager/GraphQLDomainPropertyManager.groovy deleted file mode 100644 index 851133c8..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/entity/property/manager/GraphQLDomainPropertyManager.groovy +++ /dev/null @@ -1,86 +0,0 @@ -package org.grails.gorm.graphql.entity.property.manager - -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.entity.dsl.GraphQLMapping -import org.grails.gorm.graphql.entity.property.GraphQLDomainProperty - -/** - * An interface to describe a class creates builder instances that retrieve - * {@link GraphQLDomainProperty} instances based on conditions - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GraphQLDomainPropertyManager { - - /** - * @return A new builder instance - */ - Builder builder() - - interface Builder { - - /** - * Exclude identifier properties from being returned - */ - Builder excludeIdentifiers() - - /** - * Exclude identifier properties from being returned - * - * @param exceptComposite If true, composite identifiers will be included - */ - Builder excludeIdentifiers(boolean exceptComposite) - - /** - * Exclude the version property from being returned - */ - Builder excludeVersion() - - /** - * Exclude 'dateCreated' and 'lastUpdated' from being returned - */ - Builder excludeTimestamps() - - /** - * Exclude properties from being returned - * - * @param props One or more property names - */ - Builder exclude(String... props) - - /** - * Exclude properties based on the return returnType of the provided - * closure. If the closure returns false, the property will not - * be returned. - * - * @param closure The closure to execute. The {@link org.grails.datastore.mapping.model.PersistentProperty} - * instance will be passed as the first argument. - */ - Builder condition(Closure closure) - - /** - * Whether or not properties should allow nulls should be overridden - * so that properties are nullable, even if they otherwise would not be. - */ - Builder alwaysNullable() - - /** - * Retrieves the desired properties based on the conditions previously applied - * The mapping will be retrieved from the entity `static graphql = ..` - * - * @param entity The entity to retrieve properties from - * @return The list of GraphQL domain properties - */ - List getProperties(PersistentEntity entity) - - /** - * Retrieves the desired properties based on the conditions previously applied - * - * @param entity The entity to retrieve properties from - * @param mapping The entity mapping to build domain properties with - * @return The list of GraphQL domain properties - */ - List getProperties(PersistentEntity entity, GraphQLMapping mapping) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/BindingGormDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/BindingGormDataFetcher.groovy deleted file mode 100644 index 6387b8f4..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/BindingGormDataFetcher.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package org.grails.gorm.graphql.fetcher - -import org.grails.gorm.graphql.binding.GraphQLDataBinder - -/** - * An interface to describe data fetchers that use data binding - * - * @author James Kleeh - * @since 1.0.0 - */ -interface BindingGormDataFetcher extends GormDataFetcher { - - void setDataBinder(GraphQLDataBinder dataBinder) - - GraphQLDataBinder getDataBinder() -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/DataFetcherNotFoundException.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/DataFetcherNotFoundException.groovy deleted file mode 100644 index 77482498..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/DataFetcherNotFoundException.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package org.grails.gorm.graphql.fetcher - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.PersistentEntity - -/** - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class DataFetcherNotFoundException extends RuntimeException { - - DataFetcherNotFoundException(PersistentEntity entity, GraphQLDataFetcherType type) { - this(entity.javaClass, type) - } - - DataFetcherNotFoundException(Class clazz, GraphQLDataFetcherType type) { - super("No ${type.name()} data fetcher could be found for ${clazz.name}") - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/DefaultGormDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/DefaultGormDataFetcher.groovy deleted file mode 100644 index 347f4428..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/DefaultGormDataFetcher.groovy +++ /dev/null @@ -1,129 +0,0 @@ -package org.grails.gorm.graphql.fetcher - -import grails.gorm.DetachedCriteria -import grails.gorm.multitenancy.Tenants -import grails.gorm.transactions.TransactionService -import graphql.schema.DataFetcher -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j -import org.grails.datastore.gorm.GormEnhancer -import org.grails.datastore.gorm.GormEntity -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.mapping.core.Datastore -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.multitenancy.MultiTenantCapableDatastore -import org.grails.datastore.mapping.transactions.CustomizableRollbackTransactionAttribute -import org.grails.gorm.graphql.entity.EntityFetchOptions - -/** - * A generic class to assist with querying entities with GraphQL - * - * @param The domain returnType to query - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@Slf4j -abstract class DefaultGormDataFetcher implements DataFetcher { - - protected Map associations = [:] - protected PersistentEntity entity - protected String propertyName - protected EntityFetchOptions entityFetchOptions - - DefaultGormDataFetcher(PersistentEntity entity) { - this(entity, null) - } - - DefaultGormDataFetcher(PersistentEntity entity, String projectionName) { - this.entity = entity - this.propertyName = projectionName - this.entityFetchOptions = new EntityFetchOptions(entity, projectionName) - initializeEntity(entity) - } - - protected void initializeEntity(PersistentEntity entity) { - this.associations = this.entityFetchOptions.associations - } - - protected Map getFetchArguments(DataFetchingEnvironment environment, boolean skipCollections = false) { - Set joinProperties = entityFetchOptions.getJoinProperties(environment, skipCollections) - - if (propertyName) { - joinProperties.add(propertyName) - } - - entityFetchOptions.getFetchArgument(joinProperties) - } - - protected Object loadEntity(PersistentEntity entity, Object argument) { - GormEnhancer.findStaticApi(entity.javaClass).load((Serializable)argument) - } - - protected Map getIdentifierValues(DataFetchingEnvironment environment) { - Map idProperties = [:] - - PersistentProperty identity = entity.identity - if (identity != null) { - idProperties.put(identity.name, environment.getArgument(identity.name)) - } - else if (entity.compositeIdentity != null) { - for (PersistentProperty p: entity.compositeIdentity) { - Object value - Object argument = environment.getArgument(p.name) - if (associations.containsKey(p.name)) { - PersistentEntity associatedEntity = associations.get(p.name).associatedEntity - value = loadEntity(associatedEntity, argument) - } else { - value = argument - } - idProperties.put(p.name, value) - } - } - - idProperties - } - - protected DetachedCriteria buildCriteria(DataFetchingEnvironment environment) { - Map idProperties = getIdentifierValues(environment) - new DetachedCriteria(entity.javaClass).build { - for (Map.Entry prop: idProperties) { - eq(prop.key, prop.value) - } - } - } - - protected GormEntity queryInstance(DataFetchingEnvironment environment) { - buildCriteria(environment).get(getFetchArguments(environment)) - } - - protected Object withTransaction(boolean readOnly, Closure closure) { - Datastore datastore - if (entity.multiTenant && this.datastore instanceof MultiTenantCapableDatastore) { - MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore)this.datastore - Serializable currentTenantId = Tenants.currentId(multiTenantCapableDatastore) - datastore = multiTenantCapableDatastore.getDatastoreForTenantId(currentTenantId) - } - else { - datastore = this.datastore - } - - TransactionService txService = datastore.getService(TransactionService) - CustomizableRollbackTransactionAttribute transactionAttribute = new CustomizableRollbackTransactionAttribute() - transactionAttribute.setReadOnly(readOnly) - txService.withTransaction(transactionAttribute, closure) - } - - protected Datastore getDatastore() { - staticApi.datastore - } - - protected GormStaticApi getStaticApi() { - GormEnhancer.findStaticApi(entity.javaClass) - } - - abstract T get(DataFetchingEnvironment environment) -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/DeletingGormDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/DeletingGormDataFetcher.groovy deleted file mode 100644 index 3e1ed287..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/DeletingGormDataFetcher.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package org.grails.gorm.graphql.fetcher - -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.response.delete.GraphQLDeleteResponseHandler - -/** - * A trait to describe data fetchers that delete - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -trait DeletingGormDataFetcher implements GormDataFetcher { - - @Override - boolean supports(GraphQLDataFetcherType type) { - type == GraphQLDataFetcherType.DELETE - } - - abstract void setResponseHandler(GraphQLDeleteResponseHandler responseHandler) - - abstract GraphQLDeleteResponseHandler getResponseHandler() -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/GormDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/GormDataFetcher.groovy deleted file mode 100644 index 7f24de33..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/GormDataFetcher.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package org.grails.gorm.graphql.fetcher - -import graphql.schema.DataFetcher - -/** - * A base interface to describe fetchers that - * work with GORM - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GormDataFetcher extends DataFetcher { - - boolean supports(GraphQLDataFetcherType type) -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/GraphQLDataFetcherType.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/GraphQLDataFetcherType.groovy deleted file mode 100644 index 55c901a3..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/GraphQLDataFetcherType.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package org.grails.gorm.graphql.fetcher - -import groovy.transform.CompileStatic - -/** - * An enum defining the different data fetcher types and their - * required interfaces - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -enum GraphQLDataFetcherType { - - CREATE(BindingGormDataFetcher), - GET(ReadingGormDataFetcher), - LIST(ReadingGormDataFetcher), - COUNT(ReadingGormDataFetcher), - UPDATE(BindingGormDataFetcher), - DELETE(DeletingGormDataFetcher) - - final Class requiredClass - - GraphQLDataFetcherType(Class requiredClass) { - this.requiredClass = requiredClass - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/PaginatingGormDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/PaginatingGormDataFetcher.groovy deleted file mode 100644 index 8e394bcc..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/PaginatingGormDataFetcher.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package org.grails.gorm.graphql.fetcher - -import org.grails.gorm.graphql.response.pagination.GraphQLPaginationResponseHandler - -/** - * An interface to describe data fetchers that return a page - * of data at a time - * - * @author James Kleeh - * @since 1.0.0 - */ -interface PaginatingGormDataFetcher extends ReadingGormDataFetcher { - - void setResponseHandler(GraphQLPaginationResponseHandler dataBinder) - - GraphQLPaginationResponseHandler getResponseHandler() -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/ReadingGormDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/ReadingGormDataFetcher.groovy deleted file mode 100644 index 4602eeca..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/ReadingGormDataFetcher.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package org.grails.gorm.graphql.fetcher - -/** - * An interface to describe data fetchers that read - * - * @author James Kleeh - * @since 1.0.0 - */ -interface ReadingGormDataFetcher extends GormDataFetcher { - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/context/LocaleAwareContext.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/context/LocaleAwareContext.groovy deleted file mode 100644 index 16c35477..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/context/LocaleAwareContext.groovy +++ /dev/null @@ -1,12 +0,0 @@ -package org.grails.gorm.graphql.fetcher.context - -/** - * Interface to describe objects that have a locale - * - * @author James Kleeh - * @since 1.0.0 - */ -interface LocaleAwareContext { - - Locale getLocale() -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/ClosureDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/ClosureDataFetcher.groovy deleted file mode 100644 index c29a7f28..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/ClosureDataFetcher.groovy +++ /dev/null @@ -1,50 +0,0 @@ -package org.grails.gorm.graphql.fetcher.impl - -import graphql.schema.DataFetcher -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import org.grails.datastore.gorm.GormEntity -import org.grails.gorm.graphql.entity.EntityFetchOptions - -/** - * A class to retrieve data from the environment source - * with a closure. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class ClosureDataFetcher implements DataFetcher { - - private Closure closure - private Class domainType - private boolean initialized - private EntityFetchOptions fetchOptions - - ClosureDataFetcher(Closure closure, Class domainType = null) { - this.closure = closure - this.domainType = domainType - } - - @Override - Object get(DataFetchingEnvironment environment) { - Object source = environment.source - if (closure.maximumNumberOfParameters == 2) { - closure.call(source, new ClosureDataFetchingEnvironment(environment, domainType)) - } - else { - closure.call(source) - } - } - - EntityFetchOptions buildFetchOptions() { - if (initialized) { - return fetchOptions - } - if (domainType != null && GormEntity.isAssignableFrom(domainType)) { - fetchOptions = new EntityFetchOptions(domainType) - } - initialized = true - fetchOptions - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/ClosureDataFetchingEnvironment.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/ClosureDataFetchingEnvironment.groovy deleted file mode 100644 index ae6f8abc..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/ClosureDataFetchingEnvironment.groovy +++ /dev/null @@ -1,80 +0,0 @@ -package org.grails.gorm.graphql.fetcher.impl - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import org.grails.datastore.gorm.GormEntity -import org.grails.gorm.graphql.entity.EntityFetchOptions - -/** - * Provides the data fetching environment for closures. Available - * as the second parameter to dataFetcher closures provided by - * custom properties. The main purpose of this class is to provide - * the ability to get fetch arguments for custom properties with a - * return type that is a domain class. This allows the same query - * efficiency that is provided by the generic data fetchers by default. - * - * Usage: - *
- * {@code
- * class Foo {
- *     static graphql = GraphQLMapping.build {
- *         add('bar', Bar) {
- *             dataFetcher { Foo foo, ClosureDataFetchingEnvironment env ->
- *                 //The fetchArguments will be populated based on what properties
- *                 //were requested from the 'bar'
- *                 Bar.where { }.list(env.fetchArguments)
- *             }
- *         }
- *     }
- * }
- * }
- * 
- * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class ClosureDataFetchingEnvironment { - - @Delegate - DataFetchingEnvironment environment - - private EntityFetchOptions fetchOptions - private Class domainType - - ClosureDataFetchingEnvironment(DataFetchingEnvironment environment, Class domainType) { - this.environment = environment - this.domainType = domainType - } - - private void initializeFetchOptions(String propertyName = null) { - if (fetchOptions == null && domainType != null && GormEntity.isAssignableFrom(domainType)) { - fetchOptions = new EntityFetchOptions(domainType, propertyName) - } - } - - /** - * For use with domain class return types only. All other - * invocations will return null. - * - * @param projectedProperty The property name being projected on in the query - * @return The fetch arguments to be used in your query. - */ - Map getFetchArguments(String projectedProperty = null) { - initializeFetchOptions(projectedProperty) - fetchOptions?.getFetchArgument(environment) - } - - /** - * Which properties should be joined in the subsequent query. - * Based upon which fields were requested to be returned by - * the end user. - * - * @param projectedProperty The property name being projected on in the query - * @return A set of strings representing properties to be joined - */ - Set getJoinProperties(String projectedProperty = null) { - initializeFetchOptions(projectedProperty) - fetchOptions?.getJoinProperties(environment) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/CountEntityDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/CountEntityDataFetcher.groovy deleted file mode 100644 index f85461f9..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/CountEntityDataFetcher.groovy +++ /dev/null @@ -1,35 +0,0 @@ -package org.grails.gorm.graphql.fetcher.impl - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.gorm.graphql.fetcher.DefaultGormDataFetcher -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType -import org.grails.gorm.graphql.fetcher.ReadingGormDataFetcher - -/** - * A class for retrieving how many entities exist in the datastore - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@InheritConstructors -class CountEntityDataFetcher extends DefaultGormDataFetcher implements ReadingGormDataFetcher { - - protected Integer queryCount() { - staticApi.count() - } - - @Override - Integer get(DataFetchingEnvironment environment) { - (Integer) withTransaction(true) { - queryCount() - } - } - - @Override - boolean supports(GraphQLDataFetcherType type) { - type == GraphQLDataFetcherType.COUNT - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/CreateEntityDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/CreateEntityDataFetcher.groovy deleted file mode 100644 index 292dadf1..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/CreateEntityDataFetcher.groovy +++ /dev/null @@ -1,50 +0,0 @@ -package org.grails.gorm.graphql.fetcher.impl - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.datastore.gorm.GormEntity -import org.grails.gorm.graphql.binding.GraphQLDataBinder -import org.grails.gorm.graphql.fetcher.BindingGormDataFetcher -import org.grails.gorm.graphql.fetcher.DefaultGormDataFetcher -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType - -/** - * A class for creating entities with GraphQL - * - * @param The domain returnType to create - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@InheritConstructors -class CreateEntityDataFetcher extends DefaultGormDataFetcher implements BindingGormDataFetcher { - - GraphQLDataBinder dataBinder - - @Override - T get(DataFetchingEnvironment environment) { - (T) withTransaction(false) { - GormEntity instance = newInstance - dataBinder.bind(instance, getArgument(environment)) - if (!instance.hasErrors()) { - instance.save() - } - instance - } - } - - protected GormEntity getNewInstance() { - (GormEntity) entity.newInstance() - } - - protected Map getArgument(DataFetchingEnvironment environment) { - (Map) environment.getArgument(entity.decapitalizedName) - } - - @Override - boolean supports(GraphQLDataFetcherType type) { - type == GraphQLDataFetcherType.CREATE - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/DeleteEntityDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/DeleteEntityDataFetcher.groovy deleted file mode 100644 index 4fc1ddb4..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/DeleteEntityDataFetcher.groovy +++ /dev/null @@ -1,48 +0,0 @@ -package org.grails.gorm.graphql.fetcher.impl - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.datastore.gorm.GormEntity -import org.grails.gorm.graphql.fetcher.DefaultGormDataFetcher -import org.grails.gorm.graphql.fetcher.DeletingGormDataFetcher -import org.grails.gorm.graphql.response.delete.GraphQLDeleteResponseHandler - -/** - * A class for deleting entities with GraphQL - * - * @param The domain returnType to delete - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@InheritConstructors -class DeleteEntityDataFetcher extends DefaultGormDataFetcher implements DeletingGormDataFetcher { - - GraphQLDeleteResponseHandler responseHandler - - void delete(DataFetchingEnvironment environment) { - withTransaction(false) { - GormEntity instance = queryInstance(environment) - deleteInstance(instance) - } - } - - protected void deleteInstance(GormEntity instance) { - instance.delete(failOnError: true) - } - - @Override - T get(DataFetchingEnvironment environment) { - boolean success = false - Exception exception - try { - delete(environment) - success = true - } catch (Exception e) { - exception = e - } - - (T)responseHandler.createResponse(environment, success, exception) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/EntityDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/EntityDataFetcher.groovy deleted file mode 100644 index 8af39ce6..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/EntityDataFetcher.groovy +++ /dev/null @@ -1,72 +0,0 @@ -package org.grails.gorm.graphql.fetcher.impl - -import grails.gorm.DetachedCriteria -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import groovy.util.logging.Slf4j -import org.grails.gorm.graphql.fetcher.DefaultGormDataFetcher -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType -import org.grails.gorm.graphql.fetcher.ReadingGormDataFetcher - -/** - * A class for retrieving a list of entities with GraphQL - * - * @param The collection return type - * @author James Kleeh - * @since 1.0.0 - */ -@InheritConstructors -@Slf4j -@CompileStatic -class EntityDataFetcher extends DefaultGormDataFetcher implements ReadingGormDataFetcher { - - //The new LinkedHasMap is to work around a static compilation bug - static final Map ARGUMENTS = new LinkedHashMap([ - max: Integer, - offset: Integer, - sort: String, - order: String, - ignoreCase: Boolean - ]) - - static final String MAX = 'max' - static final String OFFSET = 'offset' - - protected Map getArguments(DataFetchingEnvironment environment) { - environment.arguments - } - - @Override - T get(DataFetchingEnvironment environment) { - (T)withTransaction(true) { - - Map queryArgs = [:] - - for (Map.Entry entry: getArguments(environment)) { - if (ARGUMENTS.containsKey(entry.key) && entry.value != null) { - queryArgs.put(entry.key, entry.value) - } - } - - boolean skipCollections = queryArgs.containsKey(MAX) || queryArgs.containsKey(OFFSET) - - queryArgs.putAll(getFetchArguments(environment, skipCollections)) - - executeQuery(environment, queryArgs) - } - } - - protected DetachedCriteria buildCriteria(DataFetchingEnvironment environment) { - new DetachedCriteria(entity.javaClass) - } - - protected T executeQuery(DataFetchingEnvironment environment, Map queryArgs) { - buildCriteria(environment).list(queryArgs) - } - - @Override - boolean supports(GraphQLDataFetcherType type) { - type == GraphQLDataFetcherType.LIST - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/PaginatedEntityDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/PaginatedEntityDataFetcher.groovy deleted file mode 100644 index aa738a5e..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/PaginatedEntityDataFetcher.groovy +++ /dev/null @@ -1,34 +0,0 @@ -package org.grails.gorm.graphql.fetcher.impl - -import grails.gorm.PagedResultList -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.gorm.graphql.fetcher.PaginatingGormDataFetcher -import org.grails.gorm.graphql.response.pagination.GraphQLPaginationResponseHandler -import org.grails.gorm.graphql.response.pagination.PagedResultListPaginationResponse - -/** - * A class for retrieving a single page of entities with GraphQL - * - * @param The collection return type - * @author James Kleeh - * @since 1.0.0 - */ -@InheritConstructors -@CompileStatic -class PaginatedEntityDataFetcher extends EntityDataFetcher implements PaginatingGormDataFetcher { - - GraphQLPaginationResponseHandler responseHandler - - protected T executeQuery(DataFetchingEnvironment environment, Map queryArgs) { - if (!queryArgs.containsKey('max')) { - queryArgs.put('max', responseHandler.defaultMax) - } - if (!queryArgs.containsKey('offset')) { - queryArgs.put('offset', responseHandler.defaultOffset) - } - PagedResultList results = (PagedResultList)buildCriteria(environment).list(queryArgs) - (T)responseHandler.createResponse(environment, new PagedResultListPaginationResponse(results)) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/PersistentPropertyDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/PersistentPropertyDataFetcher.groovy deleted file mode 100644 index 3194c1f7..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/PersistentPropertyDataFetcher.groovy +++ /dev/null @@ -1,33 +0,0 @@ -package org.grails.gorm.graphql.fetcher.impl - -import graphql.schema.DataFetcher -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.mapping.reflect.EntityReflector -import org.grails.datastore.mapping.reflect.FieldEntityAccess - -/** - * A default data fetcher for persistent properties that - * uses GORM instead of the standard reflection used by the - * default {@link graphql.schema.PropertyDataFetcher} - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class PersistentPropertyDataFetcher implements DataFetcher { - - private String name - private EntityReflector entityReflector - - PersistentPropertyDataFetcher(PersistentProperty property) { - this.name = property.name - this.entityReflector = FieldEntityAccess.getOrIntializeReflector(property.owner) - } - - @Override - Object get(DataFetchingEnvironment environment) { - entityReflector.getPropertyReader(name).getter().invoke(environment.source) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/SingleEntityDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/SingleEntityDataFetcher.groovy deleted file mode 100644 index a8714d95..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/SingleEntityDataFetcher.groovy +++ /dev/null @@ -1,32 +0,0 @@ -package org.grails.gorm.graphql.fetcher.impl - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.gorm.graphql.fetcher.DefaultGormDataFetcher -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType -import org.grails.gorm.graphql.fetcher.ReadingGormDataFetcher - -/** - * A class for querying a single entity with GraphQL - * - * @param The domain returnType to query - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@InheritConstructors -class SingleEntityDataFetcher extends DefaultGormDataFetcher implements ReadingGormDataFetcher { - - @Override - T get(DataFetchingEnvironment environment) { - (T)withTransaction(true) { - queryInstance(environment) - } - } - - @Override - boolean supports(GraphQLDataFetcherType type) { - type == GraphQLDataFetcherType.GET - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/SoftDeleteEntityDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/SoftDeleteEntityDataFetcher.groovy deleted file mode 100644 index dd1002c1..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/SoftDeleteEntityDataFetcher.groovy +++ /dev/null @@ -1,38 +0,0 @@ -package org.grails.gorm.graphql.fetcher.impl - -import groovy.transform.CompileStatic -import org.grails.datastore.gorm.GormEntity -import org.grails.datastore.mapping.engine.EntityAccess -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity - -/** - * Used to soft delete entity instances. Alternative to - * {@link DeleteEntityDataFetcher} to allow users to register - * their own instances. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class SoftDeleteEntityDataFetcher extends DeleteEntityDataFetcher { - - final String propertyName - final Object value - final MappingContext mappingContext - - SoftDeleteEntityDataFetcher(PersistentEntity entity, String propertyName, Object value) { - super(entity) - this.mappingContext = entity.mappingContext - this.propertyName = propertyName - this.value = value - } - - @Override - protected void deleteInstance(GormEntity instance) { - EntityAccess entityAccess = mappingContext.createEntityAccess(entity, instance) - entityAccess.setProperty(propertyName, value) - instance.markDirty(propertyName) - instance.save() - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/UpdateEntityDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/UpdateEntityDataFetcher.groovy deleted file mode 100644 index 8f0e6577..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/impl/UpdateEntityDataFetcher.groovy +++ /dev/null @@ -1,60 +0,0 @@ -package org.grails.gorm.graphql.fetcher.impl - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.datastore.gorm.GormEntity -import org.grails.gorm.graphql.binding.GraphQLDataBinder -import org.grails.gorm.graphql.fetcher.BindingGormDataFetcher -import org.grails.gorm.graphql.fetcher.DefaultGormDataFetcher -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType - -import static org.grails.datastore.mapping.model.config.GormProperties.VERSION - -/** - * A class for updating an entity with GraphQL - * - * @param The domain returnType to update - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@InheritConstructors -class UpdateEntityDataFetcher extends DefaultGormDataFetcher implements BindingGormDataFetcher { - - GraphQLDataBinder dataBinder - - @Override - T get(DataFetchingEnvironment environment) { - (T)withTransaction(false) { - GormEntity instance = getInstance(environment) - Map dataToBind = getEntityArgument(environment) - if (entity.versioned && dataToBind.containsKey(VERSION)) { - Long entityVersion = (Long)entity.mappingContext.createEntityAccess(entity, instance).getProperty(VERSION) - Long versionParam = (Long)dataToBind.get(VERSION) - if (versionParam != null && versionParam < entityVersion) { - instance.errors.rejectValue(VERSION, 'default.optimistic.locking.failure', [entity.javaClass.simpleName] as Object[], 'Another user has updated this {0} while you were editing') - return instance - } - } - dataBinder.bind(instance, dataToBind) - if (!instance.hasErrors()) { - instance.save() - } - instance - } - } - - protected GormEntity getInstance(DataFetchingEnvironment environment) { - queryInstance(environment) - } - - protected Map getEntityArgument(DataFetchingEnvironment environment) { - (Map)environment.getArgument(entity.decapitalizedName) - } - - @Override - boolean supports(GraphQLDataFetcherType type) { - type == GraphQLDataFetcherType.UPDATE - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/CustomInterceptorInvoker.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/CustomInterceptorInvoker.groovy deleted file mode 100644 index 2de47a6e..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/CustomInterceptorInvoker.groovy +++ /dev/null @@ -1,30 +0,0 @@ -package org.grails.gorm.graphql.fetcher.interceptor - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType -import org.grails.gorm.graphql.interceptor.GraphQLFetcherInterceptor - -/** - * Executes interceptors for custom operations - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@Slf4j -abstract class CustomInterceptorInvoker extends InterceptorInvoker { - - @Override - final boolean invoke(GraphQLFetcherInterceptor interceptor, DataFetchingEnvironment environment, GraphQLDataFetcherType type) { - final String name = getName(environment) - boolean result = invoke(interceptor, name, environment) - if (!result) { - log.info("Execution of ${name} was prevented by an interceptor") - } - result - } - - abstract boolean invoke(GraphQLFetcherInterceptor interceptor, String name, DataFetchingEnvironment environment) -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/CustomMutationInterceptorInvoker.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/CustomMutationInterceptorInvoker.groovy deleted file mode 100644 index d392e0fa..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/CustomMutationInterceptorInvoker.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package org.grails.gorm.graphql.fetcher.interceptor - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.interceptor.GraphQLFetcherInterceptor - -/** - * Executes the onCustomMutation method of an interceptor - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class CustomMutationInterceptorInvoker extends CustomInterceptorInvoker { - - @Override - boolean invoke(GraphQLFetcherInterceptor interceptor, String name, DataFetchingEnvironment environment) { - interceptor.onCustomMutation(name, environment) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/CustomQueryInterceptorInvoker.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/CustomQueryInterceptorInvoker.groovy deleted file mode 100644 index 858407ca..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/CustomQueryInterceptorInvoker.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package org.grails.gorm.graphql.fetcher.interceptor - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.interceptor.GraphQLFetcherInterceptor - -/** - * Executes the onCustomQuery method of an interceptor - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class CustomQueryInterceptorInvoker extends CustomInterceptorInvoker { - - @Override - boolean invoke(GraphQLFetcherInterceptor interceptor, String name, DataFetchingEnvironment environment) { - interceptor.onCustomQuery(name, environment) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/InterceptingDataFetcher.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/InterceptingDataFetcher.groovy deleted file mode 100644 index cff32ac0..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/InterceptingDataFetcher.groovy +++ /dev/null @@ -1,68 +0,0 @@ -package org.grails.gorm.graphql.fetcher.interceptor - -import graphql.schema.DataFetcher -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.GraphQLServiceManager -import org.grails.gorm.graphql.fetcher.DataFetcherNotFoundException -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType -import org.grails.gorm.graphql.interceptor.GraphQLFetcherInterceptor -import org.grails.gorm.graphql.interceptor.manager.GraphQLInterceptorManager - -/** - * Data fetcher to wrap another data fetcher to apply - * interceptor execution - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class InterceptingDataFetcher implements DataFetcher { - - private Class clazz - private GraphQLServiceManager serviceManager - private DataFetcher wrappedFetcher - private GraphQLDataFetcherType fetcherType - private InterceptorInvoker interceptorInvoker - - protected List interceptors - - InterceptingDataFetcher(PersistentEntity entity, - GraphQLServiceManager serviceManager, - InterceptorInvoker interceptorInvoker, - GraphQLDataFetcherType fetcherType, - DataFetcher dataFetcher) { - this(entity.javaClass, serviceManager, interceptorInvoker, fetcherType, dataFetcher) - } - - InterceptingDataFetcher(Class clazz, - GraphQLServiceManager serviceManager, - InterceptorInvoker interceptorInvoker, - GraphQLDataFetcherType fetcherType, - DataFetcher dataFetcher) { - this.clazz = clazz - this.serviceManager = serviceManager - this.wrappedFetcher = dataFetcher - this.interceptorInvoker = interceptorInvoker - this.fetcherType = fetcherType - - if (wrappedFetcher == null) { - throw new DataFetcherNotFoundException(clazz, fetcherType) - } - } - - T get(DataFetchingEnvironment environment) { - if (interceptors == null) { - interceptors = serviceManager.getService(GraphQLInterceptorManager).getInterceptors(clazz) ?: (List) [] - } - - for (GraphQLFetcherInterceptor i: interceptors) { - if (!interceptorInvoker.invoke(i, environment, fetcherType)) { - return null - } - } - - wrappedFetcher.get(environment) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/InterceptorInvoker.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/InterceptorInvoker.groovy deleted file mode 100644 index 32362e0d..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/InterceptorInvoker.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package org.grails.gorm.graphql.fetcher.interceptor - -import graphql.schema.DataFetchingEnvironment -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType -import org.grails.gorm.graphql.interceptor.GraphQLFetcherInterceptor - -/** - * A generic interface for custom operations to separate which event - * will be called based on the returnType of the operation. - * - * @author James Kleeh - * @since 1.0.0 - */ -abstract class InterceptorInvoker { - - protected String getName(DataFetchingEnvironment environment) { - environment.fields.empty ? 'UNKNOWN' : environment.fields[0].name - } - - abstract boolean invoke(GraphQLFetcherInterceptor interceptor, DataFetchingEnvironment environment, GraphQLDataFetcherType type) -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/MutationInterceptorInvoker.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/MutationInterceptorInvoker.groovy deleted file mode 100644 index d017618e..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/MutationInterceptorInvoker.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package org.grails.gorm.graphql.fetcher.interceptor - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType -import org.grails.gorm.graphql.interceptor.GraphQLFetcherInterceptor - -/** - * Executes the onMutation method of an interceptor - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class MutationInterceptorInvoker extends ProvidedInterceptorInvoker { - - @Override - boolean call(GraphQLFetcherInterceptor interceptor, DataFetchingEnvironment environment, GraphQLDataFetcherType type) { - interceptor.onMutation(environment, type) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/ProvidedInterceptorInvoker.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/ProvidedInterceptorInvoker.groovy deleted file mode 100644 index c24e511f..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/ProvidedInterceptorInvoker.groovy +++ /dev/null @@ -1,30 +0,0 @@ -package org.grails.gorm.graphql.fetcher.interceptor - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType -import org.grails.gorm.graphql.interceptor.GraphQLFetcherInterceptor - -/** - * Executes interceptors for provided operations - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@Slf4j -abstract class ProvidedInterceptorInvoker extends InterceptorInvoker { - - @Override - final boolean invoke(GraphQLFetcherInterceptor interceptor, DataFetchingEnvironment environment, GraphQLDataFetcherType type) { - final String name = getName(environment) - boolean result = call(interceptor, environment, type) - if (!result) { - log.info("Execution of ${name} was prevented by an interceptor") - } - result - } - - abstract boolean call(GraphQLFetcherInterceptor interceptor, DataFetchingEnvironment environment, GraphQLDataFetcherType type) -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/QueryInterceptorInvoker.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/QueryInterceptorInvoker.groovy deleted file mode 100644 index e9336b1d..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/interceptor/QueryInterceptorInvoker.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package org.grails.gorm.graphql.fetcher.interceptor - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType -import org.grails.gorm.graphql.interceptor.GraphQLFetcherInterceptor - -/** - * Executes the onQuery method of an interceptor - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class QueryInterceptorInvoker extends ProvidedInterceptorInvoker { - - @Override - boolean call(GraphQLFetcherInterceptor interceptor, DataFetchingEnvironment environment, GraphQLDataFetcherType type) { - interceptor.onQuery(environment, type) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/manager/DefaultGraphQLDataFetcherManager.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/manager/DefaultGraphQLDataFetcherManager.groovy deleted file mode 100644 index 4baec58d..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/manager/DefaultGraphQLDataFetcherManager.groovy +++ /dev/null @@ -1,119 +0,0 @@ -package org.grails.gorm.graphql.fetcher.manager - -import graphql.schema.DataFetcher -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.fetcher.BindingGormDataFetcher -import org.grails.gorm.graphql.fetcher.DeletingGormDataFetcher -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType -import org.grails.gorm.graphql.fetcher.ReadingGormDataFetcher - -/** - * A default implementation of {@link GraphQLDataFetcherManager}. - * - * When retrieving fetcher instances, the exact class provided will be - * searched for. If a parent class is registered and a subclass is searched, - * the parent class fetcher will not be returned. If no fetchers are found, - * the optional provided default fetchers will be searched. If no default - * fetchers are provided, null will be returned. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class DefaultGraphQLDataFetcherManager implements GraphQLDataFetcherManager { - - protected final Map> dataFetchers = [:] - - DefaultGraphQLDataFetcherManager() { - } - - DefaultGraphQLDataFetcherManager(Map defaultFetchers) { - for (GraphQLDataFetcherType type: GraphQLDataFetcherType.values()) { - verifyFetcher(defaultFetchers.get(type), type.requiredClass) - } - - dataFetchers.put(Object, defaultFetchers) - } - - protected void verifyFetcher(DataFetcher instance, Class requiredType) { - if (instance != null && !(requiredType.isAssignableFrom(instance.class))) { - throw new IllegalArgumentException("Data binder supplied ${instance.class.name} must be of returnType ${requiredType.name}") - } - } - - protected void registerFetcher(Class clazz, DataFetcher fetcher, GraphQLDataFetcherType type) { - if (!dataFetchers.containsKey(clazz)) { - dataFetchers.put(clazz, [:]) - } - verifyFetcher(fetcher, type.requiredClass) - dataFetchers.get(clazz).put(type, fetcher) - } - - @Override - void registerBindingDataFetcher(Class clazz, BindingGormDataFetcher fetcher) { - for (GraphQLDataFetcherType type: GraphQLDataFetcherType.values()) { - if (type.requiredClass == BindingGormDataFetcher) { - if (fetcher.supports(type)) { - registerFetcher(clazz, fetcher, type) - } - } - } - } - - @Override - void registerDeletingDataFetcher(Class clazz, DeletingGormDataFetcher fetcher) { - registerFetcher(clazz, fetcher, GraphQLDataFetcherType.DELETE) - } - - @Override - void registerReadingDataFetcher(Class clazz, ReadingGormDataFetcher fetcher) { - for (GraphQLDataFetcherType type: GraphQLDataFetcherType.values()) { - if (type.requiredClass == ReadingGormDataFetcher) { - if (fetcher.supports(type)) { - registerFetcher(clazz, fetcher, type) - } - } - } - } - - protected DataFetcher getCustomFetcher(Class clazz, GraphQLDataFetcherType type) { - if (dataFetchers.containsKey(clazz)) { - Map fetchers = dataFetchers.get(clazz) - if (fetchers.containsKey(type)) { - return fetchers.get(type) - } - } - null - } - - protected Optional getCustomFetcher(PersistentEntity entity, GraphQLDataFetcherType type) { - DataFetcher fetcher = getCustomFetcher(entity.javaClass, type) ?: getCustomFetcher(Object, type) - if (fetcher != null) { - Optional.of(fetcher) - } else { - Optional.empty() - } - } - - @Override - Optional getBindingFetcher(PersistentEntity entity, GraphQLDataFetcherType type) { - if (type?.requiredClass != BindingGormDataFetcher) { - throw new IllegalArgumentException("The type specified (${type}) is null or invalid") - } - getCustomFetcher(entity, type).map { DataFetcher d -> (BindingGormDataFetcher) d } - } - - @Override - Optional getDeletingFetcher(PersistentEntity entity) { - getCustomFetcher(entity, GraphQLDataFetcherType.DELETE).map { DataFetcher d -> (DeletingGormDataFetcher) d } - } - - @Override - Optional getReadingFetcher(PersistentEntity entity, GraphQLDataFetcherType type) { - if (type?.requiredClass != ReadingGormDataFetcher) { - throw new IllegalArgumentException("The type specified (${type}) is null or invalid") - } - getCustomFetcher(entity, type).map { DataFetcher d -> (ReadingGormDataFetcher) d } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/manager/GraphQLDataFetcherManager.groovy b/core/src/main/groovy/org/grails/gorm/graphql/fetcher/manager/GraphQLDataFetcherManager.groovy deleted file mode 100644 index 970a96a8..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/fetcher/manager/GraphQLDataFetcherManager.groovy +++ /dev/null @@ -1,70 +0,0 @@ -package org.grails.gorm.graphql.fetcher.manager - -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.fetcher.BindingGormDataFetcher -import org.grails.gorm.graphql.fetcher.DeletingGormDataFetcher -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType -import org.grails.gorm.graphql.fetcher.ReadingGormDataFetcher - -/** - * An interface to register and retrieve data fetcher instances - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GraphQLDataFetcherManager { - - /** - * Register a fetcher instance to be used for CREATE or UPDATE for the - * provided class. - * - * @param clazz The class to be updated or deleted - * @param fetcher The fetcher instance to be used - */ - void registerBindingDataFetcher(Class clazz, BindingGormDataFetcher fetcher) - - /** - * Register a fetcher instance to be used for DELETE for the - * provided class. - * - * @param clazz The class to be deleted - * @param fetcher The fetcher instance to be used - */ - void registerDeletingDataFetcher(Class clazz, DeletingGormDataFetcher fetcher) - - /** - * Register a fetcher instance to be used for GET or LIST for the - * provided class. - * - * @param clazz The class to be retrieved - * @param fetcher The fetcher instance to be used - */ - void registerReadingDataFetcher(Class clazz, ReadingGormDataFetcher fetcher) - - /** - * Returns a data fetcher instance to be used in CREATE or UPDATE - * - * @param entity The entity representing the domain used in the fetcher - * @param type Which returnType of fetcher to return (CREATE or UPDATE) - * @return An optional data fetcher - */ - Optional getBindingFetcher(PersistentEntity entity, GraphQLDataFetcherType type) - - /** - * Returns a data fetcher instance to be used in DELETE - * - * @param entity The entity representing the domain used in the fetcher - * @return An optional data fetcher - */ - Optional getDeletingFetcher(PersistentEntity entity) - - /** - * Returns a data fetcher instance to be used in GET or LIST - * - * @param entity The entity representing the domain used in the fetcher - * @param type Which returnType of fetcher to return (GET or LIST) - * @return An optional data fetcher - */ - Optional getReadingFetcher(PersistentEntity entity, GraphQLDataFetcherType type) - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/interceptor/GraphQLFetcherInterceptor.groovy b/core/src/main/groovy/org/grails/gorm/graphql/interceptor/GraphQLFetcherInterceptor.groovy deleted file mode 100644 index 38c949da..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/interceptor/GraphQLFetcherInterceptor.groovy +++ /dev/null @@ -1,55 +0,0 @@ -package org.grails.gorm.graphql.interceptor - -import graphql.schema.DataFetchingEnvironment -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType - -/** - * Interface to describe a class that can intercept GraphQL data - * fetchers and prevent the execution of their functionality. - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GraphQLFetcherInterceptor { - - /** - * This method will be executed before query operations provided by this library. - * - * @param environment The data fetching environment provided by GraphQL - * @param type The data fetcher returnType. Either {@link GraphQLDataFetcherType#GET} or - * {@link GraphQLDataFetcherType#LIST} - * @return If FALSE, prevent execution of the interceptor - */ - boolean onQuery(DataFetchingEnvironment environment, GraphQLDataFetcherType type) - - /** - * This method will be executed before mutation operations provided by this library. - * - * @param environment The data fetching environment provided by GraphQL - * @param type The data fetcher returnType. Either {@link GraphQLDataFetcherType#CREATE}, - * {@link GraphQLDataFetcherType#UPDATE}, or {@link GraphQLDataFetcherType#DELETE} - * @return If FALSE, prevent execution of the interceptor - */ - boolean onMutation(DataFetchingEnvironment environment, GraphQLDataFetcherType type) - - /** - * This method will be executed before custom query operations provided by the user of - * this library. - * - * @param name The name of the operation attempting to be executed - * @param environment The data fetching environment provided by GraphQL - * @return If FALSE, prevent execution of the interceptor - */ - boolean onCustomQuery(String name, DataFetchingEnvironment environment) - - /** - * This method will be executed before custom mutation operations provided by the user of - * this library. - * - * @param name The name of the operation attempting to be executed - * @param environment The data fetching environment provided by GraphQL - * @return If FALSE, prevent execution of the interceptor - */ - boolean onCustomMutation(String name, DataFetchingEnvironment environment) - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/interceptor/GraphQLSchemaInterceptor.groovy b/core/src/main/groovy/org/grails/gorm/graphql/interceptor/GraphQLSchemaInterceptor.groovy deleted file mode 100644 index 498edc72..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/interceptor/GraphQLSchemaInterceptor.groovy +++ /dev/null @@ -1,39 +0,0 @@ -package org.grails.gorm.graphql.interceptor - -import graphql.schema.GraphQLFieldDefinition -import graphql.schema.GraphQLObjectType -import graphql.schema.GraphQLType -import org.grails.datastore.mapping.model.PersistentEntity - -/** - * Interface to describe a class that can modify the fields and types used - * to build the GraphQL schema. - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GraphQLSchemaInterceptor { - - /** - * Executed for each entity mapped with GraphQL. The fields are mutable - * and their changes will be applied to the schema. - * - * @param entity The entity being processed - * @param queryFields The query fields associated with the entity - * @param mutationFields The query fields associated with the entity - */ - void interceptEntity(PersistentEntity entity, - List queryFields, - List mutationFields) - - /** - * Executed a single time before the schema is created. The types are - * mutable and their changes will be applied in the schema. - * - * @param queryType The root query returnType - * @param mutationType The root mutation returnType - */ - void interceptSchema(GraphQLObjectType.Builder queryType, - GraphQLObjectType.Builder mutationType, - Set additionalTypes) -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/interceptor/impl/BaseGraphQLFetcherInterceptor.groovy b/core/src/main/groovy/org/grails/gorm/graphql/interceptor/impl/BaseGraphQLFetcherInterceptor.groovy deleted file mode 100644 index d722a49a..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/interceptor/impl/BaseGraphQLFetcherInterceptor.groovy +++ /dev/null @@ -1,34 +0,0 @@ -package org.grails.gorm.graphql.interceptor.impl - -import graphql.schema.DataFetchingEnvironment -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.fetcher.GraphQLDataFetcherType -import org.grails.gorm.graphql.interceptor.GraphQLFetcherInterceptor - -/** - * Base class to extend from for custom data fetcher interceptors. Provides default - * implementations of all methods. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class BaseGraphQLFetcherInterceptor implements GraphQLFetcherInterceptor { - - boolean onQuery(DataFetchingEnvironment environment, GraphQLDataFetcherType type) { - true - } - - boolean onMutation(DataFetchingEnvironment environment, GraphQLDataFetcherType type) { - true - } - - boolean onCustomQuery(String name, DataFetchingEnvironment environment) { - true - } - - boolean onCustomMutation(String name, DataFetchingEnvironment environment) { - true - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/interceptor/manager/DefaultGraphQLInterceptorManager.groovy b/core/src/main/groovy/org/grails/gorm/graphql/interceptor/manager/DefaultGraphQLInterceptorManager.groovy deleted file mode 100644 index 63fe27ac..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/interceptor/manager/DefaultGraphQLInterceptorManager.groovy +++ /dev/null @@ -1,72 +0,0 @@ -package org.grails.gorm.graphql.interceptor.manager - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.core.order.OrderedComparator -import org.grails.gorm.graphql.interceptor.GraphQLFetcherInterceptor -import org.grails.gorm.graphql.interceptor.GraphQLSchemaInterceptor -import org.grails.gorm.graphql.types.KeyClassQuery - -/** - * Default implementation of {@link GraphQLInterceptorManager} that - * will also return a result if the class requested is a subclass - * of a class that exists in the registry. All interceptors for the - * exact class searched and any parent classes will be returned. Multiple - * interceptors for the same class can be registered. - * - * Example: - * registerInterceptor(Collection, interceptor1) - * registerInterceptor(Collection, interceptor2) - * registerInterceptor(List, interceptor3) - * - * If an ArrayList is being intercepted, all 3 interceptors will fire - * - * The resulting list will be sorted based on order. Implement the - * {@link org.grails.datastore.mapping.core.Ordered} trait to - * control the order of your interceptors. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class DefaultGraphQLInterceptorManager implements GraphQLInterceptorManager, KeyClassQuery> { - - protected Map> interceptors = Collections.synchronizedMap([:]).withDefault { [] } - - protected List schemaInterceptors = [] - - protected Comparator interceptorComparator = new OrderedComparator<>() - - /** - * @see GraphQLInterceptorManager#registerInterceptor - */ - @Override - void registerInterceptor(Class type, GraphQLFetcherInterceptor interceptor) { - if (type == null) { - throw new IllegalArgumentException('Cannot register an interceptor for a null type') - } - if (interceptor == null) { - throw new IllegalArgumentException('Registering a null interceptor is not allowed') - } - interceptors.get(type).add(interceptor) - } - - @Override - void registerInterceptor(GraphQLSchemaInterceptor interceptor) { - schemaInterceptors.add(interceptor) - } - - /** - * @see GraphQLInterceptorManager#getInterceptors - * - * @return NULL if no interceptors found - */ - @Override - List getInterceptors(Class clazz) { - searchMapAll(interceptors, clazz). sort(true, interceptorComparator) - } - - @Override - List getInterceptors() { - schemaInterceptors. sort(true, interceptorComparator) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/interceptor/manager/GraphQLInterceptorManager.groovy b/core/src/main/groovy/org/grails/gorm/graphql/interceptor/manager/GraphQLInterceptorManager.groovy deleted file mode 100644 index 5743719a..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/interceptor/manager/GraphQLInterceptorManager.groovy +++ /dev/null @@ -1,41 +0,0 @@ -package org.grails.gorm.graphql.interceptor.manager - -import org.grails.gorm.graphql.interceptor.GraphQLFetcherInterceptor -import org.grails.gorm.graphql.interceptor.GraphQLSchemaInterceptor - -/** - * Describes a class that stores and retrieves fetcher interceptor - * instances based on a class - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GraphQLInterceptorManager { - - /** - * Registers the interceptor - * - * @param clazz The class operations should be intercepted for - * @param interceptor The interceptor to register - */ - void registerInterceptor(Class clazz, GraphQLFetcherInterceptor interceptor) - - /** - * Registers the interceptor - * - * @param interceptor The interceptor to register - */ - void registerInterceptor(GraphQLSchemaInterceptor interceptor) - - /** - * @param clazz The class to search for - * @return Interceptors that support the class - */ - List getInterceptors(Class clazz) - - /** - * @param clazz The class to search for - * @return Interceptors of the schema - */ - List getInterceptors() -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/response/CachingGraphQLResponseHandler.groovy b/core/src/main/groovy/org/grails/gorm/graphql/response/CachingGraphQLResponseHandler.groovy deleted file mode 100644 index 8a5f061c..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/response/CachingGraphQLResponseHandler.groovy +++ /dev/null @@ -1,25 +0,0 @@ -package org.grails.gorm.graphql.response - -import graphql.schema.GraphQLObjectType -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * Generic class to cache the creation of {@link GraphQLObjectType} instances - * by providing a reference if the object was already created when requested. - * - * @author James Kleeh - * @since 1.0.0 - */ -abstract class CachingGraphQLResponseHandler { - - private GraphQLObjectType cachedDefinition - - GraphQLObjectType getDefinition(GraphQLTypeManager typeManager) { - if (cachedDefinition == null) { - cachedDefinition = buildDefinition(typeManager) - } - cachedDefinition - } - - abstract protected GraphQLObjectType buildDefinition(GraphQLTypeManager typeManager) -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/response/delete/DefaultGraphQLDeleteResponseHandler.groovy b/core/src/main/groovy/org/grails/gorm/graphql/response/delete/DefaultGraphQLDeleteResponseHandler.groovy deleted file mode 100644 index 47a6c54b..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/response/delete/DefaultGraphQLDeleteResponseHandler.groovy +++ /dev/null @@ -1,51 +0,0 @@ -package org.grails.gorm.graphql.response.delete - -import graphql.schema.DataFetchingEnvironment -import graphql.schema.GraphQLFieldDefinition -import graphql.schema.GraphQLObjectType -import graphql.schema.GraphQLOutputType -import groovy.transform.CompileStatic -import org.grails.gorm.graphql.response.CachingGraphQLResponseHandler -import org.grails.gorm.graphql.types.GraphQLTypeManager - -import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition -import static graphql.schema.GraphQLObjectType.newObject - -/** - * The default data available in a delete mutation response - * - * success: Boolean - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class DefaultGraphQLDeleteResponseHandler extends CachingGraphQLResponseHandler implements GraphQLDeleteResponseHandler { - - protected String description = 'Whether or not the operation was successful' - protected String name = 'DeleteResult' - - @Override - GraphQLObjectType getObjectType(GraphQLTypeManager typeManager) { - getDefinition(typeManager) - } - - protected List buildFieldDefinitions(GraphQLTypeManager typeManager) { - [newFieldDefinition().name('success').type((GraphQLOutputType)typeManager.getType(Boolean, false)).build(), - newFieldDefinition().name('error').type((GraphQLOutputType)typeManager.getType(String)).build()] - } - - @Override - protected GraphQLObjectType buildDefinition(GraphQLTypeManager typeManager) { - newObject() - .name(name) - .description(description) - .fields(buildFieldDefinitions(typeManager)) - .build() - } - - @Override - Object createResponse(DataFetchingEnvironment environment, boolean success, Exception exception) { - [success: success, error: exception?.message] - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/response/delete/GraphQLDeleteResponseHandler.groovy b/core/src/main/groovy/org/grails/gorm/graphql/response/delete/GraphQLDeleteResponseHandler.groovy deleted file mode 100644 index 7f821391..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/response/delete/GraphQLDeleteResponseHandler.groovy +++ /dev/null @@ -1,32 +0,0 @@ -package org.grails.gorm.graphql.response.delete - -import graphql.schema.DataFetchingEnvironment -import graphql.schema.GraphQLObjectType -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * Responsible for determining the data available in a GraphQL delete mutation response - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GraphQLDeleteResponseHandler { - - /** - * Creates the schema object for a delete response - * - * @param typeManager The type manager - * @return The GraphQL type - */ - GraphQLObjectType getObjectType(GraphQLTypeManager typeManager) - - /** - * Create the response data to be sent to the client - * - * @param environment The data fetching environment - * @param success Whether or not the operation was successful - * @param exception If not successful, the exception that occurred - * @return Response data - */ - Object createResponse(DataFetchingEnvironment environment, boolean success, Exception exception) -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/response/errors/DefaultGraphQLErrorsResponseHandler.groovy b/core/src/main/groovy/org/grails/gorm/graphql/response/errors/DefaultGraphQLErrorsResponseHandler.groovy deleted file mode 100644 index 02aea4db..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/response/errors/DefaultGraphQLErrorsResponseHandler.groovy +++ /dev/null @@ -1,131 +0,0 @@ -package org.grails.gorm.graphql.response.errors - -import graphql.schema.DataFetcher -import graphql.schema.DataFetchingEnvironment -import graphql.schema.GraphQLCodeRegistry -import graphql.schema.GraphQLFieldDefinition -import graphql.schema.GraphQLObjectType -import graphql.schema.GraphQLOutputType -import groovy.transform.CompileStatic -import org.grails.datastore.gorm.GormValidateable -import org.grails.gorm.graphql.fetcher.context.LocaleAwareContext -import org.grails.gorm.graphql.types.GraphQLTypeManager -import org.springframework.context.MessageSource -import org.springframework.validation.FieldError - -import static graphql.schema.FieldCoordinates.coordinates -import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition -import static graphql.schema.GraphQLList.list -import static graphql.schema.GraphQLObjectType.newObject - -/** - * The default way to respond with validation errors in GraphQL. - * Will look for the locale in the environment context to properly format - * error messages. Defaults to {@link Locale#getDefault()}. - * - * errors { - * field - * message - * } - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class DefaultGraphQLErrorsResponseHandler implements GraphQLErrorsResponseHandler { - - protected MessageSource messageSource - protected String name = 'Error' - protected String description = 'Validation Errors' - protected String fieldName = 'errors' - protected String fieldDescription = 'A list of validation errors on the entity' - protected final GraphQLCodeRegistry.Builder codeRegistry - - DefaultGraphQLErrorsResponseHandler(MessageSource messageSource, GraphQLCodeRegistry.Builder codeRegistry) { - this.messageSource = messageSource - this.codeRegistry = codeRegistry - } - - protected Locale getLocale(DataFetchingEnvironment environment) { - if (environment.context instanceof Map) { - Map context = (Map)environment.context - if (context.containsKey('locale')) { - Object localContext = context.get('locale') - if (localContext instanceof Locale) { - return (Locale)localContext - } - } - } - if (environment.context instanceof LocaleAwareContext) { - return ((LocaleAwareContext) environment.context).locale - } - Locale.default - } - - protected DataFetcher fieldFetcher = new DataFetcher() { - @Override - String get(DataFetchingEnvironment environment) { - ((FieldError) environment.source).field - } - } - - protected DataFetcher messageFetcher = new DataFetcher() { - @Override - String get(DataFetchingEnvironment environment) { - messageSource.getMessage((FieldError) environment.source, getLocale(environment)) - } - } - - protected DataFetcher errorsFetcher = new DataFetcher>() { - @Override - List get(DataFetchingEnvironment environment) { - ((GormValidateable) environment.source).errors.fieldErrors - } - } - - protected List getFieldDefinitions(GraphQLTypeManager typeManager) { - [newFieldDefinition() - .name('field') - .type((GraphQLOutputType)typeManager.getType(String, false)) - .build(), - - newFieldDefinition() - .name('message') - .type((GraphQLOutputType)typeManager.getType(String)) - .build()] - } - - protected GraphQLObjectType buildDefinition(GraphQLTypeManager typeManager) { - codeRegistry.dataFetcher( - coordinates(name, 'field'), - fieldFetcher) - .dataFetcher( - coordinates(name, 'message'), - messageFetcher) - - newObject() - .name(name) - .description(description) - .fields(getFieldDefinitions(typeManager)) - .build() - } - - private GraphQLFieldDefinition cachedDefinition - - @Override - GraphQLFieldDefinition getFieldDefinition(GraphQLTypeManager typeManager, - String parentType) { - if (cachedDefinition == null) { - cachedDefinition = newFieldDefinition() - .name(fieldName) - .description(fieldDescription) - .type(list(buildDefinition(typeManager))) - .build() - } - codeRegistry.dataFetcher( - coordinates(parentType, fieldName), - errorsFetcher - ) - cachedDefinition - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/response/errors/GraphQLErrorsResponseHandler.groovy b/core/src/main/groovy/org/grails/gorm/graphql/response/errors/GraphQLErrorsResponseHandler.groovy deleted file mode 100644 index 09064e64..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/response/errors/GraphQLErrorsResponseHandler.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package org.grails.gorm.graphql.response.errors - -import graphql.schema.GraphQLFieldDefinition -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * Responsible for defining what data is available in a response - * to return validation errors to the user - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GraphQLErrorsResponseHandler { - - GraphQLFieldDefinition getFieldDefinition(GraphQLTypeManager typeManager, - String parentType) - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/DefaultGraphQLPaginationResponseHandler.groovy b/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/DefaultGraphQLPaginationResponseHandler.groovy deleted file mode 100644 index b3ac9e2b..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/DefaultGraphQLPaginationResponseHandler.groovy +++ /dev/null @@ -1,59 +0,0 @@ -package org.grails.gorm.graphql.response.pagination - -import graphql.schema.DataFetchingEnvironment -import graphql.schema.GraphQLFieldDefinition -import graphql.schema.GraphQLList -import graphql.schema.GraphQLOutputType -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.types.GraphQLTypeManager - -import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition - -/** - * Controls how a page of results are returned - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class DefaultGraphQLPaginationResponseHandler implements GraphQLPaginationResponseHandler { - - protected String resultsField = 'results' - protected String totalField = 'totalCount' - - @Override - List getFields(GraphQLOutputType resultsType, GraphQLTypeManager typeManager) { - [newFieldDefinition() - .name(resultsField) - .type(GraphQLList.list(resultsType)) - .build(), - newFieldDefinition() - .name(totalField) - .type((GraphQLOutputType)typeManager.getType(Long)) - .build()] - } - - @Override - String getDescription(PersistentEntity entity) { - null - } - - @Override - Object createResponse(DataFetchingEnvironment environment, PaginationResult result) { - Map response = new LinkedHashMap(2) - response.put(resultsField, result.results) - response.put(totalField, result.totalCount) - response - } - - @Override - int getDefaultMax() { - 100 - } - - @Override - int getDefaultOffset() { - 0 - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/GraphQLPaginationResponseHandler.groovy b/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/GraphQLPaginationResponseHandler.groovy deleted file mode 100644 index 77ad5057..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/GraphQLPaginationResponseHandler.groovy +++ /dev/null @@ -1,49 +0,0 @@ -package org.grails.gorm.graphql.response.pagination - -import graphql.schema.DataFetchingEnvironment -import graphql.schema.GraphQLFieldDefinition -import graphql.schema.GraphQLOutputType -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * Defines how a pagination response is defined and built - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GraphQLPaginationResponseHandler { - - /** - * Creates the fields to be used in the schema object for a pagination response - * - * @param resultsType The graphql type of the results - * @param typeManager The type manager - * @return The GraphQL type - */ - List getFields(GraphQLOutputType resultsType, GraphQLTypeManager typeManager) - - /** - * @return The description to use in the schema, or null - */ - String getDescription(PersistentEntity entity) - - /** - * Create the response data to be sent to the client - * - * @param environment The data fetching environment - * @param results The data retrieved from the query - * @return Response data - */ - Object createResponse(DataFetchingEnvironment environment, PaginationResult result) - - /** - * @return The default maximum value if none provided - */ - int getDefaultMax() - - /** - * @return The default offset value if none provided - */ - int getDefaultOffset() -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/PagedResultListPaginationResponse.groovy b/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/PagedResultListPaginationResponse.groovy deleted file mode 100644 index cde2bb18..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/PagedResultListPaginationResponse.groovy +++ /dev/null @@ -1,31 +0,0 @@ -package org.grails.gorm.graphql.response.pagination - -import grails.gorm.PagedResultList -import groovy.transform.CompileStatic - -/** - * A default pagination response that gathers data - * from a {@link PagedResultList} - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class PagedResultListPaginationResponse implements PaginationResult { - - private PagedResultList resultList - - PagedResultListPaginationResponse(PagedResultList resultList) { - this.resultList = resultList - } - - @Override - Collection getResults() { - resultList - } - - @Override - Long getTotalCount() { - resultList.totalCount.longValue() - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/PaginatedType.groovy b/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/PaginatedType.groovy deleted file mode 100644 index 8385b5aa..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/PaginatedType.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package org.grails.gorm.graphql.response.pagination - -import groovy.transform.CompileStatic - -/** - * Helper class to inform the type system that a custom operation - * returns a paginated result for the given type. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class PaginatedType { - - Class type -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/PaginationResult.groovy b/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/PaginationResult.groovy deleted file mode 100644 index 94374146..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/response/pagination/PaginationResult.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package org.grails.gorm.graphql.response.pagination - -/** - * Stores the result of a pagination query - * - * @author James Kleeh - * @since 1.0.0 - */ -interface PaginationResult { - - Collection getResults() - - Long getTotalCount() -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/testing/GraphQLSchemaSpec.groovy b/core/src/main/groovy/org/grails/gorm/graphql/testing/GraphQLSchemaSpec.groovy deleted file mode 100644 index 3d04ec89..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/testing/GraphQLSchemaSpec.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package org.grails.gorm.graphql.testing - -import graphql.schema.GraphQLList -import graphql.schema.GraphQLNonNull -import graphql.schema.GraphQLType - -trait GraphQLSchemaSpec { - - GraphQLType unwrap(List list, GraphQLType type) { - if (list == null) { - ((GraphQLNonNull)type).wrappedType - } - else if (list.empty) { - ((GraphQLList)type).wrappedType - } - else if (list[0] == null) { - ((GraphQLNonNull)((GraphQLList)type).wrappedType).wrappedType - } - else { - null - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/testing/MockDataFetchingEnvironment.groovy b/core/src/main/groovy/org/grails/gorm/graphql/testing/MockDataFetchingEnvironment.groovy deleted file mode 100644 index 365cc7be..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/testing/MockDataFetchingEnvironment.groovy +++ /dev/null @@ -1,116 +0,0 @@ -package org.grails.gorm.graphql.testing - -import graphql.GraphQLContext -import graphql.cachecontrol.CacheControl -import graphql.execution.ExecutionId -import graphql.execution.ExecutionStepInfo -import graphql.execution.MergedField -import graphql.execution.directives.QueryDirectives -import graphql.language.Document -import graphql.language.Field -import graphql.language.FragmentDefinition -import graphql.language.OperationDefinition -import graphql.schema.* -import groovy.transform.CompileStatic -import org.dataloader.DataLoader -import org.dataloader.DataLoaderRegistry - -/** - * A class to use to provide a mock DataFetchingEnvironment to - * test custom data fetchers. - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class MockDataFetchingEnvironment implements DataFetchingEnvironment { - - Object source - Object context - Object localContext - Map arguments = [:] - List fields = [] - GraphQLOutputType fieldType - GraphQLType parentType - GraphQLSchema graphQLSchema - Map fragmentsByName - ExecutionId executionId - DataLoaderRegistry dataLoaderRegistry - CacheControl cacheControl - OperationDefinition operationDefinition - Locale locale - DataFetchingFieldSelectionSet selectionSet - GraphQLFieldDefinition fieldDefinition - Object root - MergedField mergedField - Field field - ExecutionStepInfo executionStepInfo - Document document - Map variables - QueryDirectives queryDirectives - - @Override - boolean containsArgument(String name) { - arguments.containsKey(name) - } - - @Override - GraphQLContext getGraphQlContext() { - GraphQLContext.newContext().build() - } - - @Override - Object getArgumentOrDefault(String name, Object defaultValue) { - arguments.getOrDefault(name, defaultValue) - } - - @Override - Object getLocalContext() { - localContext - } - - @Override - MergedField getMergedField() { - MergedField.newMergedField(fields).build() - } - - @Override - QueryDirectives getQueryDirectives() { - queryDirectives - } - - @Override - def DataLoader getDataLoader(String dataLoaderName) { - dataLoaderRegistry ? dataLoaderRegistry.getDataLoader(dataLoaderName) : null - } - - @Override - CacheControl getCacheControl() { - cacheControl - } - - @Override - Locale getLocale() { - locale - } - - @Override - OperationDefinition getOperationDefinition() { - operationDefinition - } - - @Override - Document getDocument() { - document - } - - @Override - Map getVariables() { - variables - } - - @Override - Object getArgument(String name) { - arguments.get(name) - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/DefaultGraphQLTypeManager.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/DefaultGraphQLTypeManager.groovy deleted file mode 100644 index bf8d49cc..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/DefaultGraphQLTypeManager.groovy +++ /dev/null @@ -1,255 +0,0 @@ -package org.grails.gorm.graphql.types - -import graphql.Scalars -import graphql.scalars.ExtendedScalars -import graphql.schema.* -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.reflect.ClassUtils -import org.grails.gorm.graphql.GraphQL -import org.grails.gorm.graphql.Schema -import org.grails.gorm.graphql.entity.GraphQLEntityNamingConvention -import org.grails.gorm.graphql.entity.property.manager.GraphQLDomainPropertyManager -import org.grails.gorm.graphql.response.errors.GraphQLErrorsResponseHandler -import org.grails.gorm.graphql.response.pagination.GraphQLPaginationResponseHandler -import org.grails.gorm.graphql.types.input.* -import org.grails.gorm.graphql.types.output.EmbeddedObjectTypeBuilder -import org.grails.gorm.graphql.types.output.ObjectTypeBuilder -import org.grails.gorm.graphql.types.output.PaginatedObjectTypeBuilder -import org.grails.gorm.graphql.types.output.ShowObjectTypeBuilder -import org.grails.gorm.graphql.types.scalars.CustomScalars - -import java.lang.reflect.Array -import java.sql.Time -import java.sql.Timestamp -import java.util.concurrent.ConcurrentHashMap - -/** - * The default implementation of {@link GraphQLTypeManager} - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class DefaultGraphQLTypeManager implements GraphQLTypeManager { - - private Map> entitiesInProgress = [:].withDefault { [] } - - protected static final Map TYPE_MAP = new ConcurrentHashMap([ - (Integer): Scalars.GraphQLInt, - (Long): ExtendedScalars.GraphQLLong, - (Short): ExtendedScalars.GraphQLShort, - (Byte): ExtendedScalars.GraphQLByte, - (Byte[]): CustomScalars.GraphQLByteArray, - (Double): Scalars.GraphQLFloat, - (Float): Scalars.GraphQLFloat, - (BigInteger): ExtendedScalars.GraphQLBigInteger, - (BigDecimal): ExtendedScalars.GraphQLBigDecimal, - (String): Scalars.GraphQLString, - (Boolean): Scalars.GraphQLBoolean, - (Character): ExtendedScalars.GraphQLChar, - (Character[]): CustomScalars.GraphQLCharacterArray, - (UUID): CustomScalars.GraphQLUUID, - (URL): CustomScalars.GraphQLURL, - (URI): CustomScalars.GraphQLURI, - (Time): CustomScalars.GraphQLTime, - (java.sql.Date): CustomScalars.GraphQLSqlDate, - (Timestamp): CustomScalars.GraphQLTimestamp, - (Currency): CustomScalars.GraphQLCurrency, - (TimeZone): CustomScalars.GraphQLTimeZone - ]) - - protected static final Map ENUM_TYPES = new ConcurrentHashMap<>() - - final GraphQLCodeRegistry.Builder codeRegistry - GraphQLEntityNamingConvention namingConvention - GraphQLErrorsResponseHandler errorsResponseHandler - GraphQLDomainPropertyManager propertyManager - GraphQLPaginationResponseHandler paginationResponseHandler - - Map inputObjectTypeBuilders = [:] - Map objectTypeBuilders = [:] - - DefaultGraphQLTypeManager(GraphQLCodeRegistry.Builder codeRegistry, - GraphQLEntityNamingConvention namingConvention, - GraphQLErrorsResponseHandler errorsResponseHandler, - GraphQLDomainPropertyManager propertyManager, - GraphQLPaginationResponseHandler paginationResponseHandler) { - this.codeRegistry = codeRegistry - this.namingConvention = namingConvention - this.propertyManager = propertyManager - this.errorsResponseHandler = errorsResponseHandler - this.paginationResponseHandler = paginationResponseHandler - initialize() - } - - void initialize() { - List inputBuilders = [] - GraphQLTypeManager typeManager = this - inputBuilders.with { - add(new CreateInputObjectTypeBuilder(propertyManager, typeManager)) - add(new NestedInputObjectTypeBuilder(propertyManager, typeManager, GraphQLPropertyType.CREATE_NESTED)) - add(new NestedInputObjectTypeBuilder(propertyManager, typeManager, GraphQLPropertyType.UPDATE_NESTED)) - add(new UpdateInputObjectTypeBuilder(propertyManager, typeManager)) - add(new EmbeddedInputObjectTypeBuilder(propertyManager, typeManager, GraphQLPropertyType.UPDATE_EMBEDDED)) - add(new EmbeddedInputObjectTypeBuilder(propertyManager, typeManager, GraphQLPropertyType.CREATE_EMBEDDED)) - } - - for (InputObjectTypeBuilder builder: inputBuilders) { - inputObjectTypeBuilders.put(builder.type, builder) - } - - List builders = [] - builders.add(new EmbeddedObjectTypeBuilder(codeRegistry, propertyManager, typeManager, null)) - builders.add(new ShowObjectTypeBuilder(codeRegistry, propertyManager, typeManager, errorsResponseHandler)) - builders.add(new PaginatedObjectTypeBuilder(paginationResponseHandler, typeManager)) - - for (ObjectTypeBuilder builder: builders) { - objectTypeBuilders.put(builder.type, builder) - } - } - - private Class unwrap(Class clazz) { - if (clazz.array) { - if (clazz.componentType.primitive) { - clazz = Array.newInstance(boxPrimitive(clazz.componentType), 0).getClass() - } - } - else if (clazz.primitive) { - clazz = boxPrimitive(clazz) - } - clazz - } - - @Override - GraphQLType getType(Class clazz, boolean nullable = true) { - clazz = unwrap(clazz) - - GraphQLType type = TYPE_MAP.get(clazz) - if (type == null) { - throw new TypeNotFoundException(clazz) - } - if (nullable) { - type - } - else { - GraphQLNonNull.nonNull(type) - } - } - - @Override - boolean hasType(Class clazz) { - TYPE_MAP.containsKey(unwrap(clazz)) - } - - protected Class boxPrimitive(Class clazz) { - ClassUtils.PRIMITIVE_TYPE_COMPATIBLE_CLASSES.get(clazz) - } - - @Override - void registerType(Class clazz, GraphQLType type) { - TYPE_MAP.put(clazz, type) - } - - @Override - GraphQLType getEnumType(Class clazz, boolean nullable) { - GraphQLEnumType enumType - - if (ENUM_TYPES.containsKey(clazz)) { - enumType = ENUM_TYPES.get(clazz) - } - else { - GraphQLEnumType.Builder builder = GraphQLEnumType.newEnum() - .name(clazz.simpleName) - - GraphQL annotation = clazz.getAnnotation(GraphQL) - - if (annotation != null && !annotation.value().empty) { - builder.description(annotation.value()) - } - - for (Enum anEnum: clazz.enumConstants) { - final String name = anEnum.name() - - String description = null - String deprecationReason = null - - GraphQL valueAnnotation = clazz.getField(name).getAnnotation(GraphQL) - if (valueAnnotation != null) { - if (!valueAnnotation.deprecationReason().empty) { - deprecationReason = valueAnnotation.deprecationReason() - } - else if (valueAnnotation.deprecated()) { - deprecationReason = Schema.DEFAULT_DEPRECATION_REASON - } - if (!valueAnnotation.value().empty) { - description = valueAnnotation.value() - } - } - - builder.value(name, anEnum, description, deprecationReason) - } - - enumType = builder.build() - ENUM_TYPES.put(clazz, enumType) - } - - if (nullable) { - enumType - } - else { - GraphQLNonNull.nonNull(enumType) - } - } - - @Override - GraphQLTypeReference createReference(PersistentEntity entity, GraphQLPropertyType type) { - new GraphQLTypeReference(namingConvention.getType(entity, type)) - } - - @Override - GraphQLOutputType getQueryType(PersistentEntity entity, GraphQLPropertyType type) { - if (objectTypeBuilders.containsKey(type)) { - List entitiesInProgress = entitiesInProgress.get(type) - if (entitiesInProgress.contains(entity)) { - (GraphQLOutputType)createReference(entity, type) - } - else { - entitiesInProgress.add(entity) - GraphQLOutputType outputType = objectTypeBuilders.get(type).build(entity) - entitiesInProgress.removeElement(entity) - outputType - } - } - else { - throw new IllegalArgumentException("Invalid type specified. ${type.name()} is not a valid query type") - } - } - - @Override - GraphQLInputType getMutationType(PersistentEntity entity, GraphQLPropertyType type, boolean nullable) { - if (inputObjectTypeBuilders.containsKey(type)) { - GraphQLInputType inputType - List entitiesInProgress = entitiesInProgress.get(type) - if (entitiesInProgress.contains(entity)) { - inputType = (GraphQLInputType)createReference(entity, type) - } - else { - entitiesInProgress.add(entity) - inputType = inputObjectTypeBuilders.get(type).build(entity) - entitiesInProgress.removeElement(entity) - } - - if (nullable) { - inputType - } - else { - GraphQLNonNull.nonNull(inputType) - } - } - else { - throw new IllegalArgumentException("Invalid type specified. ${type.name()} is not a valid mutation type") - } - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/GraphQLOperationType.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/GraphQLOperationType.groovy deleted file mode 100644 index f4fed28e..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/GraphQLOperationType.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package org.grails.gorm.graphql.types - -import groovy.transform.CompileStatic - -/** - * An enum to store the base operations provided - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -enum GraphQLOperationType { - CREATE, - UPDATE, - OUTPUT, - DELETE -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/GraphQLPropertyType.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/GraphQLPropertyType.groovy deleted file mode 100644 index 3e9e5883..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/GraphQLPropertyType.groovy +++ /dev/null @@ -1,108 +0,0 @@ -package org.grails.gorm.graphql.types - -import groovy.transform.CompileStatic - -/** - * Represents what type of property is being created - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -enum GraphQLPropertyType { - - /** - * For returning data - * @see {@link org.grails.gorm.graphql.types.output.ShowObjectTypeBuilder} - */ - OUTPUT(GraphQLOperationType.OUTPUT, false, false), - - /** - * For creating data - * @see {@link org.grails.gorm.graphql.types.input.CreateInputObjectTypeBuilder} - */ - CREATE(GraphQLOperationType.CREATE, false, false), - - /** - * For updating data (typically the same as create except nulls allowed) - * @see {@link org.grails.gorm.graphql.types.input.UpdateInputObjectTypeBuilder} - */ - UPDATE(GraphQLOperationType.UPDATE, false, false), - - /** - * For supplying association data during a create - * @see {@link org.grails.gorm.graphql.types.input.NestedInputObjectTypeBuilder} - */ - CREATE_NESTED(GraphQLOperationType.CREATE, false, true), - - /** - * For supplying association data during an update - * @see {@link org.grails.gorm.graphql.types.input.NestedInputObjectTypeBuilder} - */ - UPDATE_NESTED(GraphQLOperationType.UPDATE, false, true), - - /** - * For creating embedded properties - * @see {@link org.grails.gorm.graphql.types.input.EmbeddedInputObjectTypeBuilder} - */ - CREATE_EMBEDDED(GraphQLOperationType.CREATE, true, false), - - /** - * For updating embedded properties - * @see {@link org.grails.gorm.graphql.types.input.EmbeddedInputObjectTypeBuilder} - */ - UPDATE_EMBEDDED(GraphQLOperationType.UPDATE, true, false), - - /** - * For displaying embedded properties - * @see {@link org.grails.gorm.graphql.types.output.EmbeddedObjectTypeBuilder} - */ - OUTPUT_EMBEDDED(GraphQLOperationType.OUTPUT, true, false), - - /** - * For displaying a page of results - */ - OUTPUT_PAGED(GraphQLOperationType.OUTPUT, false, false) - - final GraphQLOperationType operationType - final boolean embedded - final boolean nested - - GraphQLPropertyType(GraphQLOperationType operationType, boolean embedded, boolean nested) { - this.operationType = operationType - this.embedded = embedded - this.nested = nested - } - - GraphQLPropertyType getEmbeddedType() { - switch (operationType) { - case GraphQLOperationType.OUTPUT: - OUTPUT_EMBEDDED - break - case GraphQLOperationType.CREATE: - CREATE_EMBEDDED - break - case GraphQLOperationType.UPDATE: - UPDATE_EMBEDDED - break - default: - throw new UnsupportedOperationException("No embedded type available for ${operationType.name()}") - } - } - - GraphQLPropertyType getNestedType() { - switch (operationType) { - case GraphQLOperationType.OUTPUT: - OUTPUT - break - case GraphQLOperationType.CREATE: - CREATE_NESTED - break - case GraphQLOperationType.UPDATE: - UPDATE_NESTED - break - default: - throw new UnsupportedOperationException("No nested type available for ${operationType.name()}") - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/GraphQLTypeManager.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/GraphQLTypeManager.groovy deleted file mode 100644 index 6442cd7e..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/GraphQLTypeManager.groovy +++ /dev/null @@ -1,109 +0,0 @@ -package org.grails.gorm.graphql.types - -import graphql.schema.GraphQLCodeRegistry -import graphql.schema.GraphQLInputType -import graphql.schema.GraphQLOutputType -import graphql.schema.GraphQLType -import graphql.schema.GraphQLTypeReference -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.entity.GraphQLEntityNamingConvention - -/** - * An interface for handling type conversion and creation with GraphQL. - * Implementations must handle circular query type creations. It is expected - * subsequent calls to {@link #getType}, {@link #getEnumType}, - * {@link #getMutationType}, and {@link #getQueryType} will return the same - * instance (cached). - * - * @author James Kleeh - * @since 1.0.0 - */ -interface GraphQLTypeManager { - - /** - * Retrieves the corresponding GraphQL type for the specified class. - * This method should typically return a {@link graphql.schema.GraphQLScalarType} - * - * Implementations must include support for converting primitive types to their - * respective class types (long -> Long, byte[] -> Byte[]). - * - * @param clazz The class to retrieve a type for - * @return The GraphQLType - */ - GraphQLType getType(Class clazz) throws TypeNotFoundException - - /** - * Retrieves whether or not a GraphQL type has been registered for the - * provided class - * - * @param clazz The class to search for a type for - * @return True if a type was found - */ - boolean hasType(Class clazz) - - /** - * Retrieves the corresponding GraphQL type for the specified class. - * This method should typically return a {@link graphql.schema.GraphQLScalarType} - * - * @param clazz The class to retrieve a type for - * @param nullable If true, wrap the normal result with a {@link graphql.schema.GraphQLNonNull} - * @return The GraphQLType - */ - GraphQLType getType(Class clazz, boolean nullable) - - /** - * Register a GraphQL type to represent the provided class - * - * @param clazz The class the type represents - * @param type The type - */ - void registerType(Class clazz, GraphQLType type) - - /** - * @return The naming convention used to name types - */ - GraphQLEntityNamingConvention getNamingConvention() - - /** - * Retrieves an enum type for the provided class - * - * @param clazz The clazz to create - * @param nullable True if the property allows nulls - * @return The type representing the provided enum - */ - GraphQLType getEnumType(Class clazz, boolean nullable) - - /** - * Creates a reference to domain type - * - * @param entity The entity to reference - * @param type The type of reference - * @return The domain reference - */ - GraphQLTypeReference createReference(PersistentEntity entity, GraphQLPropertyType type) - - /** - * Retrieves a GraphQL type used for mutations that represents the provided entity - * - * @param entity The persistent entity to retrieve the type for - * @param type The type of property to retrieve - * @param nullable True if the property allows nulls - * @return The type representing the provided entity - */ - GraphQLInputType getMutationType(PersistentEntity entity, GraphQLPropertyType type, boolean nullable) - - /** - * Retrieves a GraphQL type used for queries that represents the provided entity - * - * @param entity The persistent entity to retrieve the type for - * @param type The type of property to retrieve - * @return The type representing the provided entity - */ - GraphQLOutputType getQueryType(PersistentEntity entity, GraphQLPropertyType type) - - /** - * @return - */ - GraphQLCodeRegistry.Builder getCodeRegistry() - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/KeyClassQuery.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/KeyClassQuery.groovy deleted file mode 100644 index e92d740b..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/KeyClassQuery.groovy +++ /dev/null @@ -1,69 +0,0 @@ -package org.grails.gorm.graphql.types - -import groovy.transform.CompileStatic - -/** - * Generic class to help searching maps that have a class as their key - * - * @param The type of value to return - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -trait KeyClassQuery { - - /** - * Searches for exact matches first. If no exact match found, - * query the set of classes in reverse order and search for any class - * that is a super class of the class being searched. Return the first - * result found. - * - * @param map The map to search - * @param clazz The class to search for - * @param reverse Whether to search in reverse order (last in has priority) - * - * @return The result. If no result found, returns NULL. - */ - V searchMap(Map map, Class clazz, boolean reverse = true) { - if (map.containsKey(clazz)) { - return map.get(clazz) - } - List keys = map.keySet().toList() - if (reverse) { - keys.reverse(true) - } - for (Class key: keys) { - if (key.isAssignableFrom(clazz)) { - return map.get(key) - } - } - null - } - - /** - * Searches for any class that is a super class of the class being - * searched. Return all results found. - * - * @param map The map to search - * @param clazz The class to search for - * - * @return The result. If no results found, returns an empty list. - */ - List searchMapAll(Map map, Class clazz) { - List values = [] - List keys = map.keySet().toList() - for (Class key: keys) { - if (key.isAssignableFrom(clazz)) { - V value = map.get(key) - if (value instanceof Collection) { - values.addAll((Collection)value) - } - else { - values.add(value) - } - } - } - values - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/TypeNotFoundException.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/TypeNotFoundException.groovy deleted file mode 100644 index 252a0976..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/TypeNotFoundException.groovy +++ /dev/null @@ -1,12 +0,0 @@ -package org.grails.gorm.graphql.types - -/** - * @author James Kleeh - * @since 1.0.0 - */ -class TypeNotFoundException extends RuntimeException { - - TypeNotFoundException(Class clazz) { - super("A GraphQL type could not be found for ${clazz.name}") - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/input/AbstractInputObjectTypeBuilder.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/input/AbstractInputObjectTypeBuilder.groovy deleted file mode 100644 index 02dfef3d..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/input/AbstractInputObjectTypeBuilder.groovy +++ /dev/null @@ -1,74 +0,0 @@ -package org.grails.gorm.graphql.types.input - -import graphql.schema.GraphQLInputObjectField -import graphql.schema.GraphQLInputObjectType -import graphql.schema.GraphQLInputType -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.GraphQLEntityHelper -import org.grails.gorm.graphql.entity.property.GraphQLDomainProperty -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.entity.property.manager.GraphQLDomainPropertyManager -import org.grails.gorm.graphql.types.GraphQLTypeManager - -import static graphql.schema.GraphQLInputObjectField.newInputObjectField -import static graphql.schema.GraphQLInputObjectType.newInputObject - -/** - * The base class used to build an input object based on an entity - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -abstract class AbstractInputObjectTypeBuilder implements InputObjectTypeBuilder { - - protected Map objectTypeCache = [:] - protected GraphQLDomainPropertyManager propertyManager - protected GraphQLTypeManager typeManager - - AbstractInputObjectTypeBuilder(GraphQLDomainPropertyManager propertyManager, GraphQLTypeManager typeManager) { - this.typeManager = typeManager - this.propertyManager = propertyManager - } - - abstract GraphQLDomainPropertyManager.Builder getBuilder() - - abstract GraphQLPropertyType getType() - - protected GraphQLInputObjectField.Builder buildInputField(GraphQLDomainProperty prop, GraphQLPropertyType type) { - newInputObjectField() - .name(prop.name) - .description(prop.description) - .type((GraphQLInputType)prop.getGraphQLType(typeManager, type)) - } - - GraphQLInputObjectType build(PersistentEntity entity) { - - GraphQLInputObjectType inputObjectType - - if (objectTypeCache.containsKey(entity)) { - objectTypeCache.get(entity) - } - else { - final String description = GraphQLEntityHelper.getDescription(entity) - - List properties = builder.getProperties(entity) - - GraphQLInputObjectType.Builder inputObj = newInputObject() - .name(typeManager.namingConvention.getType(entity, type)) - .description(description) - - for (GraphQLDomainProperty prop: properties) { - if (prop.input) { - inputObj.field(buildInputField(prop, type)) - } - } - - inputObjectType = inputObj.build() - objectTypeCache.put(entity, inputObjectType) - inputObjectType - } - - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/input/CreateInputObjectTypeBuilder.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/input/CreateInputObjectTypeBuilder.groovy deleted file mode 100644 index 1b68267c..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/input/CreateInputObjectTypeBuilder.groovy +++ /dev/null @@ -1,25 +0,0 @@ -package org.grails.gorm.graphql.types.input - -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.entity.property.manager.GraphQLDomainPropertyManager - -/** - * The class used to define which properties are available - * when creating an entity - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@InheritConstructors -class CreateInputObjectTypeBuilder extends AbstractInputObjectTypeBuilder { - - GraphQLDomainPropertyManager.Builder builder = propertyManager.builder() - .excludeTimestamps() - .excludeVersion() - .excludeIdentifiers(true) - - GraphQLPropertyType type = GraphQLPropertyType.CREATE -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/input/EmbeddedInputObjectTypeBuilder.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/input/EmbeddedInputObjectTypeBuilder.groovy deleted file mode 100644 index c75f35b9..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/input/EmbeddedInputObjectTypeBuilder.groovy +++ /dev/null @@ -1,55 +0,0 @@ -package org.grails.gorm.graphql.types.input - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.mapping.model.types.Association -import org.grails.datastore.mapping.model.types.ManyToOne -import org.grails.gorm.graphql.types.GraphQLOperationType -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.entity.property.manager.GraphQLDomainPropertyManager -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * The class used to define which properties are available - * when providing an embedded object - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class EmbeddedInputObjectTypeBuilder extends AbstractInputObjectTypeBuilder { - - EmbeddedInputObjectTypeBuilder(GraphQLDomainPropertyManager propertyManager, GraphQLTypeManager typeManager, GraphQLPropertyType type) { - super(propertyManager, typeManager) - this.type = type - } - - GraphQLDomainPropertyManager.Builder builder - GraphQLPropertyType type - - { - builder = propertyManager.builder() - .excludeTimestamps() - .excludeVersion() - .excludeIdentifiers() - .condition { PersistentProperty prop -> - if (prop instanceof Association) { - Association association = (Association)prop - boolean owningSide - if (association instanceof ManyToOne) { - owningSide = false - } else { - owningSide = association.owningSide - } - owningSide || !association.bidirectional - } else { - true - } - } - - if (type.operationType == GraphQLOperationType.UPDATE) { - builder.alwaysNullable() - } - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/input/InputObjectTypeBuilder.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/input/InputObjectTypeBuilder.groovy deleted file mode 100644 index 8afe5db5..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/input/InputObjectTypeBuilder.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package org.grails.gorm.graphql.types.input - -import graphql.schema.GraphQLInputType -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.types.GraphQLPropertyType - -/** - * Definition of a builder that creates output types - * - * @author James Kleeh - * @since 1.0.0 - */ -interface InputObjectTypeBuilder { - - GraphQLInputType build(PersistentEntity entity) - - GraphQLPropertyType getType() -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/input/NestedInputObjectTypeBuilder.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/input/NestedInputObjectTypeBuilder.groovy deleted file mode 100644 index 8f5d4645..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/input/NestedInputObjectTypeBuilder.groovy +++ /dev/null @@ -1,50 +0,0 @@ -package org.grails.gorm.graphql.types.input - -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.mapping.model.types.Association -import org.grails.datastore.mapping.model.types.ManyToOne -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.entity.property.manager.GraphQLDomainPropertyManager -import org.grails.gorm.graphql.types.GraphQLTypeManager - -/** - * The class used to define which properties are available - * when providing an object as a part of a parent object - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class NestedInputObjectTypeBuilder extends AbstractInputObjectTypeBuilder { - - NestedInputObjectTypeBuilder(GraphQLDomainPropertyManager propertyManager, GraphQLTypeManager typeManager, GraphQLPropertyType type) { - super(propertyManager, typeManager) - this.type = type - } - - GraphQLDomainPropertyManager.Builder builder - GraphQLPropertyType type - - { - builder = propertyManager.builder() - .excludeTimestamps() - .excludeVersion() - .alwaysNullable() - .condition { PersistentProperty prop -> - if (prop instanceof Association) { - Association association = (Association)prop - boolean owningSide - if (association instanceof ManyToOne) { - owningSide = false - } else { - owningSide = association.owningSide - } - (owningSide || !association.bidirectional) - } else { - true - } - } - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/input/UpdateInputObjectTypeBuilder.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/input/UpdateInputObjectTypeBuilder.groovy deleted file mode 100644 index 53830e58..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/input/UpdateInputObjectTypeBuilder.groovy +++ /dev/null @@ -1,25 +0,0 @@ -package org.grails.gorm.graphql.types.input - -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.entity.property.manager.GraphQLDomainPropertyManager - -/** - * The class used to define which properties are available - * when updating an entity - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@InheritConstructors -class UpdateInputObjectTypeBuilder extends AbstractInputObjectTypeBuilder { - - GraphQLDomainPropertyManager.Builder builder = propertyManager.builder() - .excludeTimestamps() - .excludeIdentifiers() - .alwaysNullable() - - GraphQLPropertyType type = GraphQLPropertyType.UPDATE -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/output/AbstractObjectTypeBuilder.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/output/AbstractObjectTypeBuilder.groovy deleted file mode 100644 index ecd1b474..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/output/AbstractObjectTypeBuilder.groovy +++ /dev/null @@ -1,151 +0,0 @@ -package org.grails.gorm.graphql.types.output - -import graphql.TypeResolutionEnvironment -import graphql.schema.* -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.MappingContext -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.GraphQLEntityHelper -import org.grails.gorm.graphql.entity.dsl.helpers.Arguable -import org.grails.gorm.graphql.entity.property.GraphQLDomainProperty -import org.grails.gorm.graphql.entity.property.manager.GraphQLDomainPropertyManager -import org.grails.gorm.graphql.response.errors.GraphQLErrorsResponseHandler -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.types.GraphQLTypeManager - -import static graphql.schema.FieldCoordinates.coordinates -import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition -import static graphql.schema.GraphQLInterfaceType.newInterface -import static graphql.schema.GraphQLObjectType.newObject - -/** - * A base class used to create object types that represent an entity - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -abstract class AbstractObjectTypeBuilder implements ObjectTypeBuilder { - - protected Map objectTypeCache = [:] - protected GraphQLDomainPropertyManager propertyManager - protected GraphQLTypeManager typeManager - protected GraphQLErrorsResponseHandler errorsResponseHandler - protected final GraphQLCodeRegistry.Builder codeRegistry - - AbstractObjectTypeBuilder(GraphQLCodeRegistry.Builder codeRegistry, - GraphQLDomainPropertyManager propertyManager, - GraphQLTypeManager typeManager, - GraphQLErrorsResponseHandler errorsResponseHandler) { - this.typeManager = typeManager - this.propertyManager = propertyManager - this.errorsResponseHandler = errorsResponseHandler - this.codeRegistry = codeRegistry - } - - abstract GraphQLDomainPropertyManager.Builder getBuilder() - - abstract GraphQLPropertyType getType() - - protected GraphQLFieldDefinition.Builder buildField(GraphQLDomainProperty prop, String parentType) { - GraphQLFieldDefinition.Builder field = newFieldDefinition() - .name(prop.name) - .deprecate(prop.deprecationReason) - .description(prop.description) - - GraphQLOutputType type = (GraphQLOutputType) prop.getGraphQLType(typeManager, type) - if (prop.dataFetcher != null) { - codeRegistry.dataFetcher( - coordinates(parentType, prop.name), - prop.dataFetcher - ) - } - field.type(type) - - field - } - - protected GraphQLFieldDefinition.Builder addFieldArgs(GraphQLFieldDefinition.Builder field, GraphQLDomainProperty prop, MappingContext mapping) { - if (prop instanceof Arguable) { - List arguments = prop.getArguments(typeManager, mapping) - if (!arguments.empty) { - field.arguments(arguments) - } - } - field - } - - @Override - GraphQLOutputType build(PersistentEntity entity) { - - GraphQLOutputType objectType - - if (objectTypeCache.containsKey(entity)) { - objectTypeCache.get(entity) - } - else { - final String description = GraphQLEntityHelper.getDescription(entity) - final String name = typeManager.namingConvention.getType(entity, type) - - List fields = new ArrayList<>(properties.size() + 1) - - List properties = builder.getProperties(entity) - for (GraphQLDomainProperty prop: properties) { - if (prop.output) { - GraphQLFieldDefinition.Builder field = buildField(prop, name) - addFieldArgs(field, prop, entity.mappingContext) - fields.add(field.build()) - } - } - - if (errorsResponseHandler != null) { - GraphQLFieldDefinition fieldDefinition = errorsResponseHandler.getFieldDefinition(typeManager, name) - fields.add(fieldDefinition) - } - - boolean hasChildEntities = entity.root && !entity.mappingContext.getDirectChildEntities(entity).empty - - if (hasChildEntities && !type.embedded) { - objectType = buildInterfaceType(entity, name, description, fields) - } - else { - objectType = buildObjectType(entity, name, description, fields) - } - - objectTypeCache.put(entity, objectType) - objectType - } - } - - GraphQLObjectType buildObjectType(final PersistentEntity entity, final String name, final String description, final List fields) { - - GraphQLObjectType.Builder obj = newObject() - .name(name) - .description(description) - .fields(fields) - - if (!entity.root) { - obj.withInterface(typeManager.createReference(entity.rootEntity, GraphQLPropertyType.OUTPUT)) - } - - obj.build() - } - - GraphQLInterfaceType buildInterfaceType(final PersistentEntity entity, final String name, final String description, final List fields) { - - GraphQLInterfaceType.Builder obj = newInterface() - .name(name) - .description(description) - .fields(fields) - .typeResolver(new TypeResolver() { - @Override - GraphQLObjectType getType(TypeResolutionEnvironment env) { - final String typeName = typeManager.namingConvention.getType(env.object.class.simpleName, GraphQLPropertyType.OUTPUT) - (GraphQLObjectType)env.schema.getType(typeName) - } - }) - - obj.build() - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/output/EmbeddedObjectTypeBuilder.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/output/EmbeddedObjectTypeBuilder.groovy deleted file mode 100644 index 98c86dd4..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/output/EmbeddedObjectTypeBuilder.groovy +++ /dev/null @@ -1,25 +0,0 @@ -package org.grails.gorm.graphql.types.output - -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.entity.property.manager.GraphQLDomainPropertyManager - -/** - * The class used to define which properties are available - * when responding with an embedded entity - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@InheritConstructors -class EmbeddedObjectTypeBuilder extends AbstractObjectTypeBuilder { - - GraphQLDomainPropertyManager.Builder builder = propertyManager.builder() - .alwaysNullable() - .excludeIdentifiers() - .excludeVersion() - - GraphQLPropertyType type = GraphQLPropertyType.OUTPUT_EMBEDDED -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/output/ObjectTypeBuilder.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/output/ObjectTypeBuilder.groovy deleted file mode 100644 index 5c1781b3..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/output/ObjectTypeBuilder.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package org.grails.gorm.graphql.types.output - -import graphql.schema.GraphQLOutputType -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.types.GraphQLPropertyType - -/** - * Definition of a builder that creates output types - * - * @author James Kleeh - * @since 1.0.0 - */ -interface ObjectTypeBuilder { - - GraphQLOutputType build(PersistentEntity entity) - - GraphQLPropertyType getType() -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/output/PaginatedObjectTypeBuilder.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/output/PaginatedObjectTypeBuilder.groovy deleted file mode 100644 index a0a18aef..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/output/PaginatedObjectTypeBuilder.groovy +++ /dev/null @@ -1,43 +0,0 @@ -package org.grails.gorm.graphql.types.output - -import graphql.schema.GraphQLOutputType -import groovy.transform.CompileStatic -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.gorm.graphql.response.pagination.GraphQLPaginationResponseHandler -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.types.GraphQLTypeManager - -import static graphql.schema.GraphQLObjectType.newObject - -/** - * Builds a paginated output type - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class PaginatedObjectTypeBuilder implements ObjectTypeBuilder { - - GraphQLPaginationResponseHandler responseHandler - GraphQLTypeManager typeManager - - PaginatedObjectTypeBuilder(GraphQLPaginationResponseHandler responseHandler, GraphQLTypeManager typeManager) { - this.responseHandler = responseHandler - this.typeManager = typeManager - } - - @Override - GraphQLOutputType build(PersistentEntity entity) { - GraphQLOutputType resultsType = typeManager.getQueryType(entity, GraphQLPropertyType.OUTPUT) - newObject() - .name(typeManager.namingConvention.getPagination(entity)) - .description(responseHandler.getDescription(entity)) - .fields(responseHandler.getFields(resultsType, typeManager)) - .build() - } - - @Override - GraphQLPropertyType getType() { - GraphQLPropertyType.OUTPUT_PAGED - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/output/ShowObjectTypeBuilder.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/output/ShowObjectTypeBuilder.groovy deleted file mode 100644 index d53dc46d..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/output/ShowObjectTypeBuilder.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package org.grails.gorm.graphql.types.output - -import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors -import org.grails.gorm.graphql.types.GraphQLPropertyType -import org.grails.gorm.graphql.entity.property.manager.GraphQLDomainPropertyManager - -/** - * The class used to define which properties are available - * when responding with an entity - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -@InheritConstructors -class ShowObjectTypeBuilder extends AbstractObjectTypeBuilder { - - GraphQLDomainPropertyManager.Builder builder = propertyManager.builder() - .alwaysNullable() - - GraphQLPropertyType type = GraphQLPropertyType.OUTPUT -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/CustomScalars.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/CustomScalars.groovy deleted file mode 100644 index 0fc78c27..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/CustomScalars.groovy +++ /dev/null @@ -1,32 +0,0 @@ -package org.grails.gorm.graphql.types.scalars - -import graphql.schema.GraphQLScalarType -import org.grails.gorm.graphql.types.scalars.coercing.* - -/** - * Custom scalars - */ -class CustomScalars { - - public static final GraphQLScalarType GraphQLByteArray = GraphQLScalarType.newScalar() - .name('ByteArray').description('Built-in ByteArray').coercing(new ByteArrayCoercion()).build() - public static final GraphQLScalarType GraphQLCharacterArray = GraphQLScalarType.newScalar() - .name('CharacterArray').description('Built-in CharacterArray').coercing(new CharacterArrayCoercion()).build() - public static final GraphQLScalarType GraphQLCurrency = GraphQLScalarType.newScalar() - .name('Currency').description('Accepts a string currency code').coercing(new CurrencyCoercion()).build() - public static final GraphQLScalarType GraphQLSqlDate = GraphQLScalarType.newScalar() - .name('SqlDate').description('Accepts a number or a string in the format "yyyy-[m]m-[d]d"').coercing(new SqlDateCoercion()).build() - public static final GraphQLScalarType GraphQLTime = GraphQLScalarType.newScalar() - .name('Time').description('Accepts a number or string in the format "hh:mm:ss"').coercing(new TimeCoercion()).build() - public static final GraphQLScalarType GraphQLTimestamp = GraphQLScalarType.newScalar() - .name('Timestamp').description('Accepts a numer or a string in the format "yyyy-[m]m-[d]d hh:mm:ss[.f...]"').coercing(new TimestampCoercion()).build() - public static final GraphQLScalarType GraphQLTimeZone = GraphQLScalarType.newScalar() - .name('TimeZone').description('Accepts a string time zone id').coercing(new TimeZoneCoercion()).build() - public static final GraphQLScalarType GraphQLURI = GraphQLScalarType.newScalar() - .name('URI').description('Accepts a string in the form of a URI').coercing(new URICoercion()).build() - public static final GraphQLScalarType GraphQLURL = GraphQLScalarType.newScalar() - .name('URL').description('Accepts a string in the form of a URL').coercing(new URLCoercion()).build() - public static final GraphQLScalarType GraphQLUUID = GraphQLScalarType.newScalar() - .name('UUID').description('Accepts a string to be converted to a UUID').coercing(new UUIDCoercion()).build() - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/ByteArrayCoercion.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/ByteArrayCoercion.groovy deleted file mode 100644 index dff9a3da..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/ByteArrayCoercion.groovy +++ /dev/null @@ -1,91 +0,0 @@ -package org.grails.gorm.graphql.types.scalars.coercing - -import graphql.language.ArrayValue -import graphql.language.IntValue -import graphql.language.Value -import graphql.schema.Coercing -import graphql.schema.CoercingParseValueException -import graphql.schema.CoercingSerializeException -import groovy.transform.CompileStatic - -import java.lang.reflect.Array - -/** - * Coercion class for whole number arrays - * - * @param The type of the property - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class ByteArrayCoercion implements Coercing { - - private static final BigInteger BYTE_MIN = BigInteger.valueOf(Byte.MIN_VALUE) - private static final BigInteger BYTE_MAX = BigInteger.valueOf(Byte.MAX_VALUE) - - protected Optional convert(Object input) { - if (input instanceof Byte[]) { - Optional.of((Byte[]) input) - } - else if (input instanceof Collection) { - Collection c = (Collection) input - Byte[] converted = new Byte[c.size()] - for (int i = 0; i < c.size(); i++) { - converted[i] = (byte)c[i] - } - Optional.of(converted) - } - else if (input.class.array) { - Byte[] bytes = new Byte[Array.getLength(input)] - for (int i = 0; i < bytes.length; i++) { - bytes[i] = (byte)Array.get(input, i) - } - Optional.of(bytes) - } - else { - Optional.empty() - } - } - - @Override - Byte[] serialize(Object input) { - convert(input).orElseThrow { - throw new CoercingSerializeException("Could not convert ${input.class.name} to a Byte[]") - } - } - - @Override - Byte[] parseValue(Object input) { - convert(input).orElseThrow { - throw new CoercingParseValueException("Could not convert ${input.class.name} to a Byte[]") - } - } - - private Byte parse(Value input) { - if (!(input instanceof IntValue)) { - return null - } - BigInteger value = ((IntValue) input).value - if (value < BYTE_MIN || value > BYTE_MAX) { - null - } else { - value.byteValue() - } - } - - @Override - Byte[] parseLiteral(Object input) { - if (input instanceof ArrayValue) { - List returnList = [] - List values = ((ArrayValue) input).values - for (Value value: values) { - Byte parsedValue = parse(value) - returnList.add(parsedValue) - } - (Byte[])returnList.toArray() - } - else { - null - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/CharacterArrayCoercion.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/CharacterArrayCoercion.groovy deleted file mode 100644 index a7279d03..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/CharacterArrayCoercion.groovy +++ /dev/null @@ -1,85 +0,0 @@ -package org.grails.gorm.graphql.types.scalars.coercing - -import graphql.language.ArrayValue -import graphql.language.StringValue -import graphql.language.Value -import graphql.schema.Coercing -import graphql.schema.CoercingParseValueException -import graphql.schema.CoercingSerializeException -import groovy.transform.CompileStatic -import java.lang.reflect.Array - -/** - * Conversion class for string arrays - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class CharacterArrayCoercion implements Coercing { - - protected Optional convert(Object input) { - if (input instanceof Character[]) { - Optional.of((Character[]) input) - } - else if (input instanceof Collection) { - Collection c = (Collection) input - Character[] converted = new Character[c.size()] - for (int i = 0; i < c.size(); i++) { - converted[i] = new Character((char)c[i]) - } - Optional.of(converted) - } - else if (input.class.array) { - Character[] chars = new Character[Array.getLength(input)] - for (int i = 0; i < chars.length; i++) { - chars[i] = new Character((char)Array.get(input, i)) - } - Optional.of(chars) - } - else { - Optional.empty() - } - } - - @Override - Character[] serialize(Object input) { - convert(input).orElseThrow { - throw new CoercingSerializeException("Could not convert ${input.class.name} to a Character[]") - } - } - - @Override - Character[] parseValue(Object input) { - convert(input).orElseThrow { - throw new CoercingParseValueException("Could not convert ${input.class.name} to a Character[]") - } - } - - private Character convertValue(Value input) { - if (!(input instanceof StringValue)) { - return null - } - String value = ((StringValue) input).value - if (value.length() != 1) { - return null - } - new Character(value.charAt(0)) - } - - @Override - Character[] parseLiteral(Object input) { - if (input instanceof ArrayValue) { - List values = ((ArrayValue) input).values - Character[] returnArray = new Character[values.size()] - for (int i = 0; i < values.size(); i++) { - Character convertedValue = convertValue(values[i]) - returnArray[i] = convertedValue - } - returnArray - } - else { - null - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/CurrencyCoercion.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/CurrencyCoercion.groovy deleted file mode 100644 index 931c7d69..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/CurrencyCoercion.groovy +++ /dev/null @@ -1,53 +0,0 @@ -package org.grails.gorm.graphql.types.scalars.coercing - -import graphql.language.StringValue -import graphql.schema.Coercing -import graphql.schema.CoercingParseValueException -import graphql.schema.CoercingSerializeException -import groovy.transform.CompileStatic - -/** - * Default {@link Currency} coercion - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class CurrencyCoercion implements Coercing { - - protected Optional convert(Object input) { - if (input instanceof Currency) { - Optional.of((Currency) input) - } - else if (input instanceof String) { - Optional.of(Currency.getInstance((String) input)) - } - else { - Optional.empty() - } - } - - @Override - Currency serialize(Object input) { - convert(input).orElseThrow { - throw new CoercingSerializeException("Could not convert ${input.class.name} to a Currency") - } - } - - @Override - Currency parseValue(Object input) { - convert(input).orElseThrow { - throw new CoercingParseValueException("Could not convert ${input.class.name} to a Currency") - } - } - - @Override - Currency parseLiteral(Object input) { - if (input instanceof StringValue) { - Currency.getInstance(((StringValue)input).value) - } - else { - null - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/DateCoercion.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/DateCoercion.groovy deleted file mode 100644 index 986d95ff..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/DateCoercion.groovy +++ /dev/null @@ -1,95 +0,0 @@ -package org.grails.gorm.graphql.types.scalars.coercing - -import graphql.language.IntValue -import graphql.language.StringValue -import graphql.schema.Coercing -import graphql.schema.CoercingParseValueException -import graphql.schema.CoercingSerializeException -import groovy.transform.CompileStatic - -import java.text.DateFormat -import java.text.ParseException -import java.text.SimpleDateFormat - -/** - * Default {@link Date} coercion - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class DateCoercion implements Coercing { - - protected List formats - protected boolean lenient - - DateCoercion(List dateFormats, boolean lenient) { - this.formats = dateFormats - this.lenient = lenient - } - - protected Optional convert(Object input) { - if (input instanceof Date) { - Optional.of((Date) input) - } - else if (input instanceof String) { - parseDate((String) input) - } - else { - Optional.empty() - } - } - - @Override - Date serialize(Object input) { - convert(input).orElseThrow { - throw new CoercingSerializeException("Could not convert ${input.class.name} to a Date") - } - } - - @Override - Date parseValue(Object input) { - convert(input).orElseThrow { - throw new CoercingParseValueException("Could not convert ${input.class.name} to a Date") - } - } - - @Override - Date parseLiteral(Object input) { - if (input instanceof IntValue) { - new Date(((IntValue) input).value.longValue()) - } - else if (input instanceof StringValue) { - parseDate(((StringValue) input).value).orElse(null) - } - else { - null - } - } - - protected Optional parseDate(String value) { - Date dateValue - if (!value || !formats) { - return null - } - Exception firstException - for (String format: formats) { - if (dateValue == null) { - DateFormat formatter = new SimpleDateFormat(format) - try { - formatter.lenient = lenient - dateValue = formatter.parse((String)value) - } catch (ParseException e) { - firstException = firstException ?: e - } - } - } - if (dateValue == null) { - Optional.empty() - } - else { - Optional.of(dateValue) - } - } - -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/SqlDateCoercion.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/SqlDateCoercion.groovy deleted file mode 100644 index e98a816c..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/SqlDateCoercion.groovy +++ /dev/null @@ -1,70 +0,0 @@ -package org.grails.gorm.graphql.types.scalars.coercing - -import graphql.language.IntValue -import graphql.language.StringValue -import graphql.schema.Coercing -import graphql.schema.CoercingParseValueException -import graphql.schema.CoercingSerializeException -import groovy.transform.CompileStatic - -import java.sql.Date - -/** - * Default {@link java.sql.Date} coercion - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class SqlDateCoercion implements Coercing { - - protected Optional convert(Object input) { - if (input instanceof Date) { - Optional.of((Date) input) - } - else if (input instanceof String) { - parseDate((String) input) - } - else if (input instanceof Long) { - Optional.of(new Date((Long) input)) - } - else { - Optional.empty() - } - } - - @Override - Date serialize(Object input) { - convert(input).orElseThrow { - throw new CoercingSerializeException("Could not convert ${input.class.name} to a java.sql.Date") - } - } - - @Override - Date parseValue(Object input) { - convert(input).orElseThrow { - throw new CoercingParseValueException("Could not convert ${input.class.name} to a java.sql.Date") - } - } - - @Override - Date parseLiteral(Object input) { - if (input instanceof IntValue) { - new Date(((IntValue) input).value.longValue()) - } - else if (input instanceof StringValue) { - parseDate(((StringValue) input).value).orElse(null) - } - else { - null - } - } - - protected Optional parseDate(String value) { - try { - Optional.of(Date.valueOf(value)) - } catch (Exception e) { - Optional.empty() - } - } -} diff --git a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/TimeCoercion.groovy b/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/TimeCoercion.groovy deleted file mode 100644 index b8820b8b..00000000 --- a/core/src/main/groovy/org/grails/gorm/graphql/types/scalars/coercing/TimeCoercion.groovy +++ /dev/null @@ -1,67 +0,0 @@ -package org.grails.gorm.graphql.types.scalars.coercing - -import graphql.language.IntValue -import graphql.language.StringValue -import graphql.schema.Coercing -import graphql.schema.CoercingParseValueException -import graphql.schema.CoercingSerializeException -import groovy.transform.CompileStatic - -import java.sql.Time - -/** - * Default {@link java.sql.Time} coercion - * - * @author James Kleeh - * @since 1.0.0 - */ -@CompileStatic -class TimeCoercion implements Coercing { - - protected Optional