Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 64 additions & 10 deletions src/main/java/graphql/normalized/NormalizedInputValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

import java.util.Objects;

import static graphql.Assert.assertNotNull;
import static graphql.Assert.assertTrue;
import static graphql.Assert.assertValidName;
import static graphql.language.AstPrinter.printAst;

/**
Expand All @@ -14,10 +17,23 @@ public class NormalizedInputValue {
private final Object value;

public NormalizedInputValue(String typeName, Object value) {
this.typeName = typeName;
this.typeName = assertValidTypeName(typeName);
this.value = value;
}

private String assertValidTypeName(String typeName) {
assertValidName(unwrapAll(typeName));
return typeName;
}

private String unwrapAll(String typeName) {
String result = unwrapOne(typeName);
while (isWrapped(result)) {
result = unwrapOne(result);
}
return result;
}

/**
* This can be a wrapped type: e.g. [String!]!
*
Expand All @@ -27,6 +43,13 @@ public String getTypeName() {
return typeName;
}

/**
* @return the type name unwrapped of all list and non-null type wrapping
*/
public String getUnwrappedTypeName() {
return unwrapAll(typeName);
}

/**
* Depending on the type it returns:
* Scalar or Enum: the ast literal of the Scalar.
Expand All @@ -40,21 +63,52 @@ public Object getValue() {
}


public boolean isList() {
/**
* @return true if the input value type is a list or a non-nullable list
*/
public boolean isListLike() {
return typeName.startsWith("[");
}

public String getUnwrappedTypeName() {
String result = unwrapNonNull(typeName);
while (result.startsWith("[")) {
result = result.substring(1, result.length() - 2);
result = unwrapNonNull(result);
/**
* @return true if the input value type is non-nullable
*/
public boolean isNonNullable() {
return typeName.endsWith("!");
}

/**
* @return true if the input value type is nullable
*/
public boolean isNullable() {
return !isNonNullable();
}

private boolean isWrapped(String typeName) {
return typeName.endsWith("!") || isListOnly(typeName);
}

private boolean isListOnly(String typeName) {
if (typeName.endsWith("!")) {
return false;
}
return result;
return typeName.startsWith("[") || typeName.endsWith("]");
}

private String unwrapNonNull(String string) {
return string.endsWith("!") ? string.substring(0, string.length() - 2) : string;
private String unwrapOne(String typeName) {
assertNotNull(typeName);
assertTrue(typeName.trim().length() > 0, () -> "We have an empty type name unwrapped");
if (typeName.endsWith("!")) {
return typeName.substring(0, typeName.length() - 1);
}
if (isListOnly(typeName)) {
// nominally this will never be true - but better to be safe than sorry
assertTrue(typeName.startsWith("["), () -> String.format("We have a unbalanced list type string '%s'", typeName));
assertTrue(typeName.endsWith("]"), () -> String.format("We have a unbalanced list type string '%s'", typeName));

return typeName.substring(1, typeName.length() - 1);
}
return typeName;
}

@Override
Expand Down
87 changes: 87 additions & 0 deletions src/test/java/graphql/normalized/NormalizedInputValueTest.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package graphql.normalized

import graphql.AssertException
import spock.lang.Specification
import spock.lang.Unroll

class NormalizedInputValueTest extends Specification {

@Unroll
def "can get unwrapped type name - #typename"() {
expect:

def value = new NormalizedInputValue(typename, 1)
value.getTypeName() == typename
value.getUnwrappedTypeName() == unwrappedTypeName

where:
typename | unwrappedTypeName
"[TypeName!]!" | "TypeName"
"[TypeName!]" | "TypeName"
"[TypeName]" | "TypeName"
"TypeName!" | "TypeName"
"TypeName!" | "TypeName"
"TypeName" | "TypeName"
}

@Unroll
def "is list like- #typename"() {
expect:

def value = new NormalizedInputValue(typename, 1)
value.isListLike() == expected

where:
typename | expected
"[TypeName!]!" | true
"[TypeName!]" | true
"[TypeName]" | true
"TypeName!" | false
"TypeName" | false
}

@Unroll
def "is nullable - #typename"() {
expect:

def value = new NormalizedInputValue(typename, 1)
value.isNonNullable() == expectedNonNullable
value.isNullable() == !expectedNonNullable

where:
typename | expectedNonNullable
"[TypeName!]!" | true
"[TypeName!]" | false
"[TypeName]" | false
"TypeName!" | true
"TypeName" | false
}

@Unroll
def "bad input will be rejected = #typename"() {
expect:

try {
new NormalizedInputValue(typename, 1)
assert valid, "This should have thrown an assert"
} catch (AssertException ignored) {
assert !valid, "This should have been valid"
}

where:
typename | valid
" !" | false
"" | false
" " | false
" Name" | false
"Name " | false
"[]!" | false
"!!" | false
"[Name" | false
"Name]" | false
null | false
"[Valid]" | true
"[Valid]!" | true
"[Valid!]!" | true
}
}