private ThriftStructMetadata extractThriftStructMetadata(Type structType) { Preconditions.checkNotNull(structType, "structType is null"); Deque<Type> stack = this.stack.get(); if (stack.contains(structType)) { String path = Joiner.on("->").join(transform(concat(stack, ImmutableList.of(structType)), new Function<Type, Object>() { @Override public Object apply(Type input) { return TypeToken.of(input).getRawType().getName(); } })); throw new IllegalArgumentException("Circular references are not allowed: " + path); } stack.push(structType); try { ThriftStructMetadataBuilder builder = new ThriftStructMetadataBuilder(this, structType); ThriftStructMetadata structMetadata = builder.build(); return structMetadata; } finally { Type top = stack.pop(); checkState(structType.equals(top), "ThriftCatalog circularity detection stack is corrupt: expected %s, but got %s", structType, top); } }
@Override public ThriftStructMetadata build() { // this code assumes that metadata is clean metadataErrors.throwIfHasErrors(); // builder constructor injection ThriftMethodInjection builderMethodInjection = buildBuilderConstructorInjections(); // constructor injection (or factory method for builder) ThriftConstructorInjection constructorInjections = buildConstructorInjection(); // fields injections Iterable<ThriftFieldMetadata> fieldsMetadata = buildFieldInjections(); // methods injections List<ThriftMethodInjection> methodInjections = buildMethodInjections(); return new ThriftStructMetadata( structName, extractStructIdlAnnotations(), structType, builderType, MetadataType.STRUCT, Optional.fromNullable(builderMethodInjection), ImmutableList.copyOf(documentation), ImmutableList.copyOf(fieldsMetadata), Optional.of(constructorInjections), methodInjections ); }
@Override protected String extractName() { ThriftStruct annotation = getStructClass().getAnnotation(ThriftStruct.class); if (annotation == null) { return getStructClass().getSimpleName(); } else if (!annotation.value().isEmpty()) { return annotation.value(); } else { return getStructClass().getSimpleName(); } }
public ThriftStructMetadataBuilder(ThriftCatalog catalog, Type structType) { super(catalog, structType); // verify the class is public and has the correct annotations verifyClass(ThriftStruct.class); // finally normalize the field metadata using things like normalizeThriftFields(catalog); }
@Test public void testUnsupportedType() throws Exception { ThriftStructMetadataBuilder builder = new ThriftStructMetadataBuilder(new ThriftCatalog(), UnsupportedJavaType.class); MetadataErrors metadataErrors = builder.getMetadataErrors(); assertThat(metadataErrors.getErrors()) .as("metadata errors") .hasSize(1); assertThat(metadataErrors.getWarnings()) .as("metadata warnings") .isEmpty(); assertThat(metadataErrors.getErrors().get(0).getMessage()) .as("error message") .containsIgnoringCase("not a supported Java type"); }
@Test public void testLegacyIdCorrectlyAnnotatedWhitebox() ThriftStructMetadataBuilder builder = new ThriftStructMetadataBuilder(new ThriftCatalog(), LegacyIdCorrect.class);
@Override public ThriftConstructorInjection apply(ConstructorInjection injection) { return new ThriftConstructorInjection(injection.getConstructor(), buildParameterInjections(injection.getParameters())); } }));
@Test public void testMulitpleRequiredness() { ThriftStructMetadataBuilder builder = new ThriftStructMetadataBuilder(new ThriftCatalog(), MultipleRequiredness.class); MetadataErrors metadataErrors = builder.getMetadataErrors(); assertThat(metadataErrors.getErrors()) .as("metadata errors") .hasSize(1); assertThat(metadataErrors.getWarnings()) .as("metadata warnings") .isEmpty(); assertThat(metadataErrors.getErrors().get(0).getMessage()) .as("error message") .containsIgnoringCase("multiple requiredness"); }
public ThriftStructMetadataBuilder(ThriftCatalog catalog, Type structType) { super(catalog, structType); // verify the class is public and has the correct annotations verifyClass(ThriftStruct.class); // finally normalize the field metadata using things like normalizeThriftFields(catalog); }
@Override public ThriftConstructorInjection apply(ConstructorInjection injection) { return new ThriftConstructorInjection(injection.getConstructor(), buildParameterInjections(injection.getParameters())); } }));
ThriftStructMetadataBuilder builder = new ThriftStructMetadataBuilder(this, structType); ThriftStructMetadata structMetadata = builder.build(); return structMetadata;
@Override public ThriftStructMetadata build() { // this code assumes that metadata is clean metadataErrors.throwIfHasErrors(); // builder constructor injection ThriftMethodInjection builderMethodInjection = buildBuilderConstructorInjections(); // constructor injection (or factory method for builder) ThriftConstructorInjection constructorInjections = buildConstructorInjection(); // fields injections Iterable<ThriftFieldMetadata> fieldsMetadata = buildFieldInjections(); // methods injections List<ThriftMethodInjection> methodInjections = buildMethodInjections(); return new ThriftStructMetadata( structName, structType, builderType, MetadataType.STRUCT, Optional.fromNullable(builderMethodInjection), ImmutableList.copyOf(documentation), ImmutableList.copyOf(fieldsMetadata), Optional.of(constructorInjections), methodInjections ); }
@Test public void testNoId() throws Exception { ThriftStructMetadataBuilder builder = new ThriftStructMetadataBuilder(new ThriftCatalog(), NoId.class); MetadataErrors metadataErrors = builder.getMetadataErrors(); assertThat(metadataErrors.getErrors()) .as("metadata errors") .hasSize(1); assertThat(metadataErrors.getWarnings()) .as("metadata warnings") .isEmpty(); assertThat(metadataErrors.getErrors().get(0).getMessage()) .as("error message") .containsIgnoringCase("not have an id"); }
@Override protected String extractName() { ThriftStruct annotation = getStructClass().getAnnotation(ThriftStruct.class); if (annotation == null) { return getStructClass().getSimpleName(); } else if (!annotation.value().isEmpty()) { return annotation.value(); } else { return getStructClass().getSimpleName(); } }
@Test public void testNonFinalStructsOk() { ThriftStructMetadataBuilder builder = new ThriftStructMetadataBuilder(new ThriftCatalog(), NotFinalStruct.class); builder.build(); }
@Test public void testMultipleTypes() throws Exception { ThriftStructMetadataBuilder builder = new ThriftStructMetadataBuilder(new ThriftCatalog(), MultipleTypes.class); MetadataErrors metadataErrors = builder.getMetadataErrors(); assertThat(metadataErrors.getErrors()) .as("metadata errors") .hasSize(1); assertThat(metadataErrors.getWarnings()) .as("metadata warnings") .isEmpty(); assertThat(metadataErrors.getErrors().get(0).getMessage()) .as("error message") .containsIgnoringCase("multiple types"); }
@Override protected Class<?> extractBuilderClass() { ThriftStruct annotation = getStructClass().getAnnotation(ThriftStruct.class); if (annotation != null && !annotation.builder().equals(void.class)) { return annotation.builder(); } else { return null; } }
@Test public void testGenericBuilder() { Type structType = new TypeToken<GenericStruct<String>>() {}.getType(); ThriftStructMetadataBuilder builder = new ThriftStructMetadataBuilder(new ThriftCatalog(), structType); builder.build(); }
@Test public void testMultipleIds() throws Exception { ThriftStructMetadataBuilder builder = new ThriftStructMetadataBuilder(new ThriftCatalog(), MultipleIds.class); MetadataErrors metadataErrors = builder.getMetadataErrors(); assertThat(metadataErrors.getErrors()) .as("metadata errors") .hasSize(1); assertThat(metadataErrors.getWarnings()) .as("metadata warnings") .isEmpty(); assertThat(metadataErrors.getErrors().get(0).getMessage()) .as("error message") .containsIgnoringCase("multiple ids"); }
@Override protected Class<?> extractBuilderClass() { ThriftStruct annotation = getStructClass().getAnnotation(ThriftStruct.class); if (annotation != null && !annotation.builder().equals(void.class)) { return annotation.builder(); } else { return null; } }