private static void validateTypeDefinition(TypeDefinition typeDef, Map<TypeName, TypeDefinition> definitionMap) { typeDef.accept(new TypeDefinition.Visitor<Void>() { @Override public Void visitAlias(AliasDefinition value) {
@Override public Either<TypeDefinition, Type> visitReference(TypeName value) { TypeDefinition typeDefinition = objects.get(value); Preconditions.checkState( typeDefinition != null, "Referenced TypeDefinition not found in map of types for TypeName: %s", value); return typeDefinition.accept(new TypeDefinition.Visitor<Either<TypeDefinition, Type>>() { @Override public Either<TypeDefinition, Type> visitAlias(AliasDefinition value) { // Recursively visit target of alias return value.getAlias().accept(DealiasingTypeVisitor.this); } @Override public Either<TypeDefinition, Type> visitEnum(EnumDefinition value) { return Either.left(TypeDefinition.enum_(value)); } @Override public Either<TypeDefinition, Type> visitObject(ObjectDefinition value) { return Either.left(TypeDefinition.object(value)); } @Override public Either<TypeDefinition, Type> visitUnion(UnionDefinition value) { return Either.left(TypeDefinition.union(value)); } @Override public Either<TypeDefinition, Type> visitUnknown(String unknownType) { throw new IllegalStateException("Unsupported type: " + unknownType); } }); }
@Override public Either<TypeDefinition, Type> visitReference(TypeName value) { TypeDefinition typeDefinition = objects.get(value); Preconditions.checkState( typeDefinition != null, "Referenced TypeDefinition not found in map of types for TypeName: %s", value); return typeDefinition.accept(new TypeDefinition.Visitor<Either<TypeDefinition, Type>>() { @Override public Either<TypeDefinition, Type> visitAlias(AliasDefinition value) { // Recursively visit target of alias return value.getAlias().accept(DealiasingTypeVisitor.this); } @Override public Either<TypeDefinition, Type> visitEnum(EnumDefinition value) { return Either.left(TypeDefinition.enum_(value)); } @Override public Either<TypeDefinition, Type> visitObject(ObjectDefinition value) { return Either.left(TypeDefinition.object(value)); } @Override public Either<TypeDefinition, Type> visitUnion(UnionDefinition value) { return Either.left(TypeDefinition.union(value)); } @Override public Either<TypeDefinition, Type> visitUnknown(String unknownType) { throw new IllegalStateException("Unsupported type: " + unknownType); } }); }
@Override public void validate(ConjureDefinition definition) { // create mapping from object type name -> names of reference types that are fields of that type Multimap<TypeName, TypeName> typeToRefFields = HashMultimap.create(); definition.getTypes().stream().forEach(type -> getReferenceType(type) .ifPresent(entry -> typeToRefFields.put( type.accept(TypeDefinitionVisitor.TYPE_NAME), entry))); for (TypeName name : typeToRefFields.keySet()) { verifyTypeHasNoRecursiveDefinitions(name, typeToRefFields, new ArrayList<>()); } }
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(); }
static Map<TypeName, TypeDefinition> parseObjects( com.palantir.conjure.parser.types.TypesDefinition parsed, ConjureTypeParserVisitor.ReferenceTypeResolver typeResolver) { Optional<String> defaultPackage = parsed.definitions().defaultConjurePackage().map(ConjurePackage::name); // no need to use validator here since TypeDefinitionParserVisitor calls each TypeDefinition parser that // validates its type. return parsed.definitions().objects().entrySet().stream() .map(entry -> entry.getValue().visit( new TypeDefinitionParserVisitor(entry.getKey().name(), defaultPackage, typeResolver))) .collect(Collectors.toMap(td -> td.accept(TypeDefinitionVisitor.TYPE_NAME), td -> td)); }
@Override public void validate(ConjureDefinition definition) { // create mapping for resolving reference types during validation Map<TypeName, TypeDefinition> definitionMap = definition.getTypes().stream().collect( Collectors.toMap(entry -> entry.accept(TypeDefinitionVisitor.TYPE_NAME), entry -> entry)); definition.getTypes().stream().forEach(def -> validateTypeDefinition(def, definitionMap)); definition.getErrors().forEach(def -> validateErrorDefinition(def, definitionMap)); definition.getServices().forEach(def -> validateServiceDefinition(def, definitionMap)); }
@Override public void validate(ConjureDefinition definition) { Set<TypeName> seenNames = new HashSet<>(); definition.getTypes().forEach(typeDef -> verifyNameIsUnique(seenNames, typeDef.accept(TypeDefinitionVisitor.TYPE_NAME))); definition.getErrors().forEach(errorDef -> verifyNameIsUnique(seenNames, errorDef.getErrorName())); definition.getServices().forEach(serviceDef -> verifyNameIsUnique(seenNames, serviceDef.getServiceName())); }
@Override public void validate(EndpointDefinition definition, DealiasingTypeVisitor dealiasingTypeVisitor) { definition.getArgs().stream() .filter(entry -> entry.getParamType().accept(ParameterTypeVisitor.IS_PATH)) .forEach(entry -> { Either<TypeDefinition, Type> resolvedType = dealiasingTypeVisitor.dealias(entry.getType()); Boolean isValid = resolvedType.fold( typeDefinition -> typeDefinition.accept(TypeDefinitionVisitor.IS_ENUM), type -> type.accept(TypeVisitor.IS_PRIMITIVE)); Preconditions.checkState(isValid, "Path parameters must be primitives or aliases: \"%s\" is not allowed", entry.getArgName()); }); } }
private static boolean recursivelyFindNestedOptionals( Type type, Map<TypeName, TypeDefinition> definitionMap, boolean isOptionalSeen) { if (type.accept(TypeVisitor.IS_REFERENCE)) { TypeDefinition referenceDefinition = definitionMap.get(type.accept(TypeVisitor.REFERENCE)); // we only care about reference of alias type if (referenceDefinition != null && referenceDefinition.accept(TypeDefinitionVisitor.IS_ALIAS)) { AliasDefinition aliasDef = referenceDefinition.accept(TypeDefinitionVisitor.ALIAS); return recursivelyFindNestedOptionals(aliasDef.getAlias(), definitionMap, isOptionalSeen); } } else if (type.accept(TypeVisitor.IS_OPTIONAL)) { if (isOptionalSeen) { return true; } return recursivelyFindNestedOptionals(type.accept(TypeVisitor.OPTIONAL).getItemType(), definitionMap, true); } return false; } }
private static Boolean recursivelyValidate(Type type, DealiasingTypeVisitor visitor) { return visitor.dealias(type).fold( typeDefinition -> typeDefinition.accept(TypeDefinitionVisitor.IS_ENUM), subType -> subType.accept(new Type.Visitor<Boolean>() { @Override
private static Boolean recursivelyValidate(Type type, DealiasingTypeVisitor visitor) { return visitor.dealias(type).fold( typeDefinition -> typeDefinition.accept(TypeDefinitionVisitor.IS_ENUM), subType -> { boolean definedPrimitive = subType.accept(TypeVisitor.IS_PRIMITIVE); boolean optionalPrimitive = subType.accept(TypeVisitor.IS_OPTIONAL) && recursivelyValidate(subType.accept(TypeVisitor.OPTIONAL).getItemType(), visitor); return definedPrimitive || optionalPrimitive; }); } }