Skip to content

Commit fe582bd

Browse files
committed
Added alias support
1 parent e0a8385 commit fe582bd

File tree

5 files changed

+194
-1
lines changed

5 files changed

+194
-1
lines changed

readme.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,36 @@ For example, imagine a `phoneNumber` scalar like this :
180180
```
181181

182182

183+
## Alias Scalars
184+
185+
You can create aliases for existing scalars to add more semantic meaning to them.
186+
187+
For example a link to a social media post could be representing by a `String` but the name `SocialMediaLink` is a
188+
more semantically meaningful name for that scalar type.
189+
190+
For example, you would build it like this:
191+
192+
```java
193+
194+
AliasedScalar socialMediaLink = ExtendedScalars.newAliasedScalar("SocialMediaLink")
195+
.aliasedScalar(Scalars.GraphQLString)
196+
.build()
197+
198+
```
199+
200+
And use it in a SDL schema like this :
201+
202+
```graphql
203+
204+
type Customer {
205+
name : String
206+
socialMediaLink : SocialMediaLink
207+
}
208+
209+
```
210+
211+
Note: A future version of the graphql specification may add this capability but in the meantime you can use this facility.
212+
183213
## Other Scalars
184214

185215
* `Url`

src/main/java/graphql/scalars/ExtendedScalars.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package graphql.scalars;
22

33
import graphql.PublicApi;
4+
import graphql.scalars.alias.AliasedScalar;
45
import graphql.scalars.datetime.DateScalar;
56
import graphql.scalars.datetime.DateTimeScalar;
67
import graphql.scalars.datetime.TimeScalar;
@@ -173,4 +174,28 @@ public class ExtendedScalars {
173174
public static RegexScalar.Builder newRegexScalar(String name) {
174175
return new RegexScalar.Builder().name(name);
175176
}
177+
178+
/**
179+
* This allows an existing scalar to be wrapped and aliased with a new name.
180+
* <p>
181+
* For example you may take a `String` scalar and alias it as `SocialMediaLink` if that helps introduce
182+
* more semantic meaning to your type system.
183+
* <p>
184+
* <pre>
185+
* {@code
186+
*
187+
* type Customer {
188+
* name : String
189+
* socialMediaLink : SocialMediaLink
190+
* }
191+
* }
192+
* </pre>
193+
* <p>
194+
* A future version of the graphql specification may add this capability but in the meantime you can use this facility.
195+
*
196+
* @return a builder of a aliased scalar
197+
*/
198+
public static AliasedScalar.Builder newAliasedScalar(String name) {
199+
return new AliasedScalar.Builder().name(name);
200+
}
176201
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package graphql.scalars.alias;
2+
3+
import graphql.Assert;
4+
import graphql.Internal;
5+
import graphql.schema.Coercing;
6+
import graphql.schema.CoercingParseLiteralException;
7+
import graphql.schema.CoercingParseValueException;
8+
import graphql.schema.CoercingSerializeException;
9+
import graphql.schema.GraphQLScalarType;
10+
11+
import java.util.Map;
12+
13+
/**
14+
* Access this via {@link graphql.scalars.ExtendedScalars#newAliasedScalar(String)}
15+
*/
16+
@Internal
17+
public class AliasedScalar extends GraphQLScalarType {
18+
19+
/**
20+
* A builder for {@link graphql.scalars.alias.AliasedScalar}
21+
*/
22+
public static class Builder {
23+
private String name;
24+
private String description;
25+
private GraphQLScalarType aliasedScalar;
26+
27+
/**
28+
* Sets the name of the aliased scalar
29+
*
30+
* @param name the name of the aliased scalar
31+
*
32+
* @return this builder
33+
*/
34+
public Builder name(String name) {
35+
this.name = name;
36+
return this;
37+
}
38+
39+
/**
40+
* Sets the description of the aliased scalar
41+
*
42+
* @param description the description of the aliased scalar
43+
*
44+
* @return this builder
45+
*/
46+
public Builder description(String description) {
47+
this.description = description;
48+
return this;
49+
}
50+
51+
/**
52+
* Sets the scalar that is to be aliased
53+
*
54+
* @param aliasedScalar the scalar that is to be aliased
55+
*
56+
* @return this builder
57+
*/
58+
public Builder aliasedScalar(GraphQLScalarType aliasedScalar) {
59+
this.aliasedScalar = aliasedScalar;
60+
return this;
61+
}
62+
63+
/**
64+
* @return the built {@link AliasedScalar}
65+
*/
66+
public AliasedScalar build() {
67+
Assert.assertNotNull(name);
68+
return aliasedScalarImpl(name, description, aliasedScalar);
69+
}
70+
}
71+
72+
73+
private AliasedScalar(String name, String description, Coercing coercing) {
74+
super(name, description, coercing);
75+
}
76+
77+
private static AliasedScalar aliasedScalarImpl(String name, String description, GraphQLScalarType aliasedScalar) {
78+
Assert.assertNotNull(aliasedScalar);
79+
return new AliasedScalar(name, description, new Coercing<Object, Object>() {
80+
@Override
81+
public Object serialize(Object input) throws CoercingSerializeException {
82+
return aliasedScalar.getCoercing().serialize(input);
83+
}
84+
85+
@Override
86+
public Object parseValue(Object input) throws CoercingParseValueException {
87+
return aliasedScalar.getCoercing().parseValue(input);
88+
}
89+
90+
@Override
91+
public Object parseLiteral(Object input) throws CoercingParseLiteralException {
92+
return aliasedScalar.getCoercing().parseLiteral(input);
93+
}
94+
95+
@Override
96+
public Object parseLiteral(Object input, Map<String, Object> variables) throws CoercingParseLiteralException {
97+
return aliasedScalar.getCoercing().parseLiteral(input, variables);
98+
}
99+
});
100+
}
101+
}

src/main/java/graphql/scalars/regex/RegexScalar.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public Builder name(String name) {
4646
}
4747

4848
/**
49-
* Sets the name of the regex scalar
49+
* Sets the description of the regex scalar
5050
*
5151
* @param description the description of the regex scalar
5252
*
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package graphql.scalars.alias
2+
3+
import graphql.Scalars
4+
import graphql.language.StringValue
5+
import graphql.scalars.ExtendedScalars
6+
import spock.lang.Specification
7+
8+
class AliasedScalarTest extends Specification {
9+
10+
AliasedScalar socialMediaLink = ExtendedScalars.newAliasedScalar("SocialMediaLink")
11+
.aliasedScalar(Scalars.GraphQLString)
12+
.build()
13+
14+
def "basic wrapping"() {
15+
16+
when:
17+
def result = socialMediaLink.coercing.serialize("ABC")
18+
then:
19+
result == "ABC"
20+
21+
when:
22+
result = socialMediaLink.coercing.parseValue("ABC")
23+
then:
24+
result == "ABC"
25+
26+
when:
27+
result = socialMediaLink.coercing.parseLiteral(new StringValue("ABC"))
28+
then:
29+
result == "ABC"
30+
31+
when:
32+
result = socialMediaLink.coercing.parseLiteral(new StringValue("ABC"), [:])
33+
then:
34+
result == "ABC"
35+
36+
}
37+
}

0 commit comments

Comments
 (0)