use of com.palantir.conjure.spec.ObjectDefinition in project conjure-java by palantir.
the class BeanGenerator method generateBeanType.
@SuppressWarnings("CyclomaticComplexity")
public static JavaFile generateBeanType(TypeMapper typeMapper, ObjectDefinition typeDef, Map<com.palantir.conjure.spec.TypeName, TypeDefinition> typesMap, Options options) {
ImmutableList<EnrichedField> fields = createFields(typeMapper, typeDef.getFields());
ImmutableList<FieldSpec> poetFields = EnrichedField.toPoetSpecs(fields);
ImmutableList<EnrichedField> nonPrimitiveEnrichedFields = fields.stream().filter(field -> !field.isPrimitive()).collect(ImmutableList.toImmutableList());
com.palantir.conjure.spec.TypeName prefixedName = Packages.getPrefixedName(typeDef.getTypeName(), options.packagePrefix());
ClassName objectClass = ClassName.get(prefixedName.getPackage(), prefixedName.getName());
ClassName builderClass = ClassName.get(objectClass.packageName(), objectClass.simpleName(), "Builder");
ClassName builderImplementation = options.useStagedBuilders() && fields.stream().anyMatch(field -> !fieldShouldBeInFinalStage(field)) ? ClassName.get(objectClass.packageName(), objectClass.simpleName(), "DefaultBuilder") : builderClass;
TypeSpec.Builder typeBuilder = TypeSpec.classBuilder(prefixedName.getName()).addModifiers(Modifier.PUBLIC, Modifier.FINAL).addFields(poetFields).addMethod(createConstructor(fields, poetFields)).addMethods(createGetters(fields, typesMap, options));
if (!poetFields.isEmpty()) {
typeBuilder.addMethod(MethodSpecs.createEquals(objectClass)).addMethod(MethodSpecs.createEqualTo(objectClass, poetFields));
if (useCachedHashCode(fields)) {
MethodSpecs.addCachedHashCode(typeBuilder, poetFields);
} else {
typeBuilder.addMethod(MethodSpecs.createHashCode(poetFields));
}
}
typeBuilder.addMethod(MethodSpecs.createToString(prefixedName.getName(), fields.stream().map(EnrichedField::fieldName).collect(Collectors.toList())));
if (poetFields.size() <= MAX_NUM_PARAMS_FOR_FACTORY) {
typeBuilder.addMethod(createStaticFactoryMethod(fields, objectClass));
}
if (!nonPrimitiveEnrichedFields.isEmpty()) {
typeBuilder.addMethod(createValidateFields(nonPrimitiveEnrichedFields)).addMethod(createAddFieldIfMissing(nonPrimitiveEnrichedFields.size()));
}
if (poetFields.isEmpty()) {
// Need to add JsonSerialize annotation which indicates that the empty bean serializer should be used to
// serialize this class. Without this annotation no serializer will be set for this class, thus preventing
// serialization.
typeBuilder.addAnnotation(JsonSerialize.class).addField(createSingletonField(objectClass));
if (!options.strictObjects()) {
typeBuilder.addAnnotation(AnnotationSpec.builder(JsonIgnoreProperties.class).addMember("ignoreUnknown", "$L", true).build());
}
} else {
ImmutableList<EnrichedField> fieldsNeedingBuilderStage = fields.stream().filter(field -> !fieldShouldBeInFinalStage(field)).collect(ImmutableList.toImmutableList());
typeBuilder.addAnnotation(AnnotationSpec.builder(JsonDeserialize.class).addMember("builder", "$T.class", builderImplementation).build());
if (!options.useStagedBuilders() || fieldsNeedingBuilderStage.isEmpty()) {
typeBuilder.addMethod(createBuilder(builderClass)).addType(BeanBuilderGenerator.generate(typeMapper, objectClass, builderClass, typeDef, typesMap, options, Optional.empty()));
} else {
List<TypeSpec> interfaces = generateStageInterfaces(objectClass, builderClass, typeMapper, fieldsNeedingBuilderStage, fields.stream().filter(BeanGenerator::fieldShouldBeInFinalStage).collect(ImmutableList.toImmutableList()));
List<ClassName> interfacesAsClasses = interfaces.stream().map(stageInterface -> ClassName.get(objectClass.packageName(), objectClass.simpleName(), stageInterface.name)).collect(Collectors.toList());
TypeSpec builderInterface = TypeSpec.interfaceBuilder("Builder").addModifiers(Modifier.PUBLIC).addMethods(interfaces.stream().map(stageInterface -> stageInterface.methodSpecs).flatMap(List::stream).map(method -> method.toBuilder().addAnnotation(Override.class).returns(method.name.equals("build") ? method.returnType : ClassName.get(objectClass.packageName(), objectClass.simpleName(), "Builder")).build()).collect(Collectors.toSet())).addSuperinterfaces(interfacesAsClasses.stream().map(ClassName::box).collect(Collectors.toList())).build();
typeBuilder.addTypes(interfaces).addType(builderInterface).addMethod(MethodSpec.methodBuilder("builder").addModifiers(Modifier.PUBLIC, Modifier.STATIC).returns(interfacesAsClasses.get(0)).addStatement("return new DefaultBuilder()").build()).addType(BeanBuilderGenerator.generate(typeMapper, objectClass, builderClass, typeDef, typesMap, options, Optional.of(ClassName.get(objectClass.packageName(), objectClass.simpleName(), builderInterface.name))));
}
}
typeBuilder.addAnnotation(ConjureAnnotations.getConjureGeneratedAnnotation(BeanGenerator.class));
typeDef.getDocs().ifPresent(docs -> typeBuilder.addJavadoc("$L", Javadoc.render(docs)));
return JavaFile.builder(prefixedName.getPackage(), typeBuilder.build()).skipJavaLangImports(true).indent(" ").build();
}
use of com.palantir.conjure.spec.ObjectDefinition in project conjure by palantir.
the class ConjureParserUtils method parseObjectType.
public static TypeDefinition parseObjectType(TypeName name, com.palantir.conjure.parser.types.complex.ObjectTypeDefinition def, ConjureTypeParserVisitor.ReferenceTypeResolver typeResolver) {
ObjectDefinition objectType = ObjectDefinition.builder().typeName(name).fields(parseField(def.fields(), typeResolver)).docs(def.docs().map(Documentation::of)).build();
ObjectDefinitionValidator.validate(objectType);
return TypeDefinition.object(objectType);
}
use of com.palantir.conjure.spec.ObjectDefinition in project conjure by palantir.
the class ObjectDefinitionValidatorTest method testUniqueFieldNameValidator.
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));
}
use of com.palantir.conjure.spec.ObjectDefinition in project conjure-postman by palantir.
the class TemplateTypeVisitor method visitReference.
@SuppressWarnings("PreferSafeLoggingPreconditions")
@Override
public JsonNode visitReference(TypeName value) {
TypeDefinition definition = types.get(value);
TemplateTypeVisitor visitor = this;
return definition.accept(new TypeDefinition.Visitor<JsonNode>() {
@Override
public JsonNode visitAlias(AliasDefinition value) {
JsonNode wrapped = value.getAlias().accept(visitor);
if (wrapped instanceof TextNode) {
return new TextNode(String.format("{{ %s(%s) }}", value.getTypeName().getName(), wrapped.toString().replaceAll("[\"{}]", "")));
}
return wrapped;
}
@Override
public JsonNode visitEnum(EnumDefinition value) {
return new TextNode(value.getValues().stream().map(EnumValueDefinition::getValue).collect(Collectors.joining("|")));
}
@Override
public JsonNode visitObject(ObjectDefinition value) {
if (seenTypeStack.contains(value.getTypeName())) {
return new TextNode(String.format("{{%s}}", value.getTypeName().getName()));
}
seenTypeStack.push(value.getTypeName());
ObjectNode node = objectMapper.createObjectNode();
value.getFields().forEach(fieldDefinition -> node.set(fieldDefinition.getFieldName().get(), fieldDefinition.getType().accept(visitor)));
Preconditions.checkState(seenTypeStack.pop().equals(value.getTypeName()));
return node;
}
@Override
public JsonNode visitUnion(UnionDefinition value) {
if (value.getUnion().isEmpty()) {
return null;
} else {
if (seenTypeStack.contains(value.getTypeName())) {
return new TextNode(String.format("{{%s}}", value.getTypeName().getName()));
}
seenTypeStack.push(value.getTypeName());
String unionTypes = value.getUnion().stream().map(FieldDefinition::getFieldName).map(FieldName::get).collect(Collectors.joining("|"));
ObjectNode templates = objectMapper.createObjectNode();
value.getUnion().forEach(field -> templates.set(field.getFieldName().get(), field.getType().accept(visitor)));
JsonNode union = objectMapper.createObjectNode().put("type", unionTypes).set("oneOf", templates);
Preconditions.checkState(seenTypeStack.pop().equals(value.getTypeName()));
return union;
}
}
@Override
public JsonNode visitUnknown(String _unknownType) {
return new TextNode("{{UNKNOWN}}");
}
});
}
use of com.palantir.conjure.spec.ObjectDefinition in project conjure-postman by palantir.
the class TypeNameFormatterVisitor method visitReference.
@Override
public String visitReference(TypeName value) {
TypeDefinition definition = types.get(value);
TypeNameFormatterVisitor visitor = this;
return definition.accept(new TypeDefinition.Visitor<String>() {
@Override
public String visitAlias(AliasDefinition value) {
return String.format("%s(%s)", value.getTypeName().getName(), value.getAlias().accept(visitor));
}
@Override
public String visitEnum(EnumDefinition value) {
return value.getTypeName().getName();
}
@Override
public String visitObject(ObjectDefinition value) {
return value.getTypeName().getName();
}
@Override
public String visitUnion(UnionDefinition value) {
return value.getTypeName().getName();
}
@Override
public String visitUnknown(String _unknownType) {
return "UNKNOWN";
}
});
}
Aggregations