static List<FieldDefinition> parseField( Map<com.palantir.conjure.parser.types.names.FieldName, com.palantir.conjure.parser.types.complex.FieldDefinition> def, ConjureTypeParserVisitor.ReferenceTypeResolver typeResolver) { return def.entrySet().stream().map(entry -> { FieldDefinition fieldDefinition = FieldDefinition.builder() .fieldName(parseFieldName(entry.getKey())) .type(entry.getValue().type().visit(new ConjureTypeParserVisitor(typeResolver))) .docs(entry.getValue().docs().map(Documentation::of)).build(); FieldDefinitionValidator.validate(fieldDefinition); return fieldDefinition; }).collect(Collectors.toList()); }
@Override public void validate(UnionDefinition definition) { definition.getUnion().stream().forEach(fieldDef -> { Preconditions.checkArgument(!fieldDef.getFieldName().get().endsWith("_"), "Union member key must not end with an underscore: %s", fieldDef.getFieldName().get()); }); }
private static void validateErrorDefinition(ErrorDefinition errorDef, Map<TypeName, TypeDefinition> definitionMap) { Stream.concat(errorDef.getSafeArgs().stream(), errorDef.getUnsafeArgs().stream()) .filter(arg -> recursivelyFindNestedOptionals(arg.getType(), definitionMap, false)) .findAny() .ifPresent(arg -> { throw new IllegalStateException( "Illegal nested optionals found in one of arguments of error " + errorDef.getErrorName().getName()); }); }
private FieldDefinition field(FieldName name, String type) { return FieldDefinition.of(name, Type.reference(TypeName.of(type, PACKAGE)), DOCS); } }
@Test public void testNoSelfRecursiveType() { ConjureDefinition conjureDef = ConjureDefinition.builder() .version(1) .types(ImmutableList.of(TypeDefinition.object( ObjectDefinition.builder() .typeName(FOO) .fields(FieldDefinition.of(FieldName.of("self"), Type.reference(FOO), DOCS)) .build()))) .build(); assertThatThrownBy(() -> ConjureDefinitionValidator.NO_RECURSIVE_TYPES.validate(conjureDef)) .isInstanceOf(IllegalStateException.class) .hasMessage("Illegal recursive data type: Foo -> Foo"); }
private void testUniqueFieldNameValidator(String fieldName1, String fieldName2) { FieldDefinition field1 = FieldDefinition.builder() .fieldName(FieldName.of(fieldName1)) .type(Type.primitive(PrimitiveType.STRING)) .build(); FieldDefinition field2 = FieldDefinition.builder() .fieldName(FieldName.of(fieldName2)) .type(Type.primitive(PrimitiveType.STRING)) .build(); TypeName name = TypeName.of("Foo", "package"); ObjectDefinition definition = ObjectDefinition.builder() .typeName(name) .fields(field1) .fields(field2) .build(); assertThatThrownBy(() -> ObjectDefinitionValidator.validate(definition)) .isInstanceOf(IllegalArgumentException.class) .hasMessage(String.format("ObjectDefinition must not contain duplicate field names " + "(modulo case normalization): %s vs %s", fieldName2, fieldName1)); } }
@Test public void testRecursiveTypeOkInReference() { Type referenceType = Type.reference(FOO); TypeDefinition objectDefinition = TypeDefinition.object( ObjectDefinition.builder() .typeName(TypeName.of("Foo", "bar")) .addAllFields(ImmutableList.of( FieldDefinition.of(FieldName.of("selfOptional"), Type.optional(OptionalType.of(Type.reference(FOO))), DOCS), FieldDefinition.of(FieldName.of("selfMap"), Type.map(MapType.of(referenceType, referenceType)), DOCS), FieldDefinition.of(FieldName.of("selfSet"), Type.set(SetType.of(referenceType)), DOCS), FieldDefinition.of(FieldName.of("selfList"), Type.list(ListType.of(referenceType)), DOCS))) .build()); ConjureDefinition conjureDef = ConjureDefinition.builder() .version(1) .types(ImmutableList.of(objectDefinition)) .build(); ConjureDefinitionValidator.NO_RECURSIVE_TYPES.validate(conjureDef); }
private static void checkForComplexType(FieldDefinition typeDef) { if (typeDef.getType().accept(TypeVisitor.IS_MAP)) { MapType mapType = typeDef.getType().accept(TypeVisitor.MAP); if (!mapType.getKeyType().accept(TypeVisitor.IS_PRIMITIVE_OR_REFERENCE)) { throw new IllegalStateException( String.format("Complex type '%s' not allowed in map key: %s.", mapType.getKeyType(), typeDef)); } } } }
@Override public void validate(UnionDefinition definition) { definition.getUnion().stream().forEach(fieldDef -> { Preconditions.checkArgument(!Strings.isNullOrEmpty(fieldDef.getFieldName().get()), "Union member key must not be empty"); Preconditions.checkArgument(isValidJavaIdentifier(fieldDef.getFieldName().get()), "Union member key must be a valid Java identifier: %s", fieldDef.getFieldName().get()); } ); } }
@Test public void testUnionMemberKeyMustNotBeIllegalJavaIdentifier() { ImmutableList.of("%foo", "foo@").forEach(key -> { FieldDefinition fieldDefinition = FieldDefinition.builder() .fieldName(FieldName.of(key)) .type(Type.primitive(PrimitiveType.STRING)) .build(); assertThatThrownBy(() -> UnionDefinitionValidator.validateAll(UnionDefinition.builder() .union(fieldDefinition) .typeName(TypeName.of("string", "")) .build())) .isInstanceOf(IllegalArgumentException.class) .hasMessageStartingWith( String.format("Union member key must be a valid Java identifier: %s", key)); }); }
@Test public void testNoComplexKeysInMaps() { String illegalFieldName = "asdf"; Type complexKeyType = Type.list(ListType.of(Type.primitive(PrimitiveType.STRING))); FieldDefinition fieldDefinition = FieldDefinition.of( FieldName.of(illegalFieldName), Type.map(MapType.of(complexKeyType, Type.primitive(PrimitiveType.STRING))), Documentation.of("docs")); assertThatThrownBy(() -> FieldDefinitionValidator.validate(fieldDefinition)) .isInstanceOf(IllegalStateException.class) .hasMessageContaining(illegalFieldName) .hasMessageContaining(complexKeyType.toString()); } }
private static Optional<TypeName> getReferenceType(TypeDefinition typeDef) { if (typeDef.accept(TypeDefinitionVisitor.IS_OBJECT)) { ObjectDefinition objectDef = typeDef.accept(TypeDefinitionVisitor.OBJECT); for (FieldDefinition currField : objectDef.getFields()) { Optional<TypeName> referenceType = resolveReferenceType(currField.getType()); if (referenceType.isPresent()) { return referenceType; } } } else if (typeDef.accept(TypeDefinitionVisitor.IS_ALIAS)) { AliasDefinition aliasDef = typeDef.accept(TypeDefinitionVisitor.ALIAS); return resolveReferenceType(aliasDef.getAlias()); } return Optional.empty(); }
@Test public void testUnionMemberKeyMustNotBeEmpty() { FieldDefinition fieldDefinition = FieldDefinition.builder() .fieldName(FieldName.of("")) .type(Type.primitive(PrimitiveType.STRING)) .build(); assertThatThrownBy(() -> UnionDefinitionValidator.validateAll(UnionDefinition.builder() .union(fieldDefinition) .typeName(TypeName.of("string", "")) .build())) .isInstanceOf(IllegalArgumentException.class) .hasMessageStartingWith("Union member key must not be empty"); }
@Test public void testUnionMemberKeyMustNotHaveTrailingUnderscore() { FieldDefinition fieldDefinition = FieldDefinition.builder() .fieldName(FieldName.of("foo_")) .type(Type.primitive(PrimitiveType.STRING)) .build(); assertThatThrownBy(() -> UnionDefinitionValidator.validateAll(UnionDefinition.builder() .union(fieldDefinition) .typeName(TypeName.of("string", "")) .build())) .isInstanceOf(IllegalArgumentException.class) .hasMessageStartingWith("Union member key must not end with an underscore: foo_"); } }
@Test public void testUniqueArgNamesValidator() { FieldDefinition safeArg1 = FieldDefinition.builder() .fieldName(FieldName.of("fooBar")) .type(Type.primitive(PrimitiveType.STRING)) .build(); FieldDefinition unsafeArg1 = FieldDefinition.builder() .fieldName(FieldName.of("foo-bar")) .type(Type.primitive(PrimitiveType.STRING)) + "foo-bar vs fooBar"); FieldDefinition safeArg2 = FieldDefinition.builder() .fieldName(FieldName.of("foo-bar")) .type(Type.primitive(PrimitiveType.STRING)) .build(); FieldDefinition unsafeArg2 = FieldDefinition.builder() .fieldName(FieldName.of("foo_bar")) .type(Type.primitive(PrimitiveType.STRING))