Skip to content

Commit

Permalink
Fix doc generation for action methods with custom parameter types.
Browse files Browse the repository at this point in the history
RB=710508
BUG=SI-2067
G=si-dev
R=kjin,kvidhani
A=kvidhani
  • Loading branch information
Karthik Balasubramanian committed Apr 26, 2016
1 parent 2eaa9d7 commit 0ace10a
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG
@@ -1,5 +1,8 @@
6.0.2
------
(RB=710508)
Fix doc generation for action methods with custom parameter types.

(RB=701756)
Added cookies to isEquals/hashCode/toString in Request.java

Expand Down
Expand Up @@ -20,7 +20,9 @@
import com.linkedin.data.ByteString;
import com.linkedin.data.DataMap;
import com.linkedin.data.schema.RecordDataSchema;

import java.util.ArrayList;

import org.testng.Assert;
import org.testng.annotations.Test;

Expand All @@ -46,7 +48,8 @@ public class TestDynamicRecordTemplate
"{ \"name\" : \"enumArray\", \"type\" : { \"type\" : \"array\", \"items\" : \"EnumType\" } }, \n" +
"{ \"name\" : \"fixed\", \"type\" : { \"type\" : \"fixed\", \"name\" : \"fixedType\", \"size\" : 4 } }, \n" +
"{ \"name\" : \"fixedArray\", \"type\" : { \"type\" : \"array\", \"items\" : \"fixedType\" } }, \n" +
"{ \"name\" : \"record\", \"type\" : { \"type\" : \"record\", \"name\" : \"Bar\", \"fields\" : [ { \"name\" : \"int\", \"type\" : \"int\" } ] } } \n" +
"{ \"name\" : \"record\", \"type\" : { \"type\" : \"record\", \"name\" : \"Bar\", \"fields\" : [ { \"name\" : \"int\", \"type\" : \"int\" } ] } }, \n" +
"{ \"name\" : \"typeRef\", \"type\" : { \"type\" : \"typeref\", \"name\" : \"CustomNumber\", \"ref\" : \"int\", \"java\" : { \"class\" : \"com.linkedin.data.template.TestDynamicRecordTemplate.CustomNumber\" } } } \n" +
"] }"
);

Expand Down Expand Up @@ -81,6 +84,8 @@ public class TestDynamicRecordTemplate
new FieldDef<TestRecordAndUnionTemplate.EnumType[]>("enumArray", TestRecordAndUnionTemplate.EnumType[].class, SCHEMA.getField("enumArray").getType());
public static final FieldDef<IntegerArray> FIELD_intArrayTemplate =
new FieldDef<IntegerArray>("intArrayTemplate", IntegerArray.class, SCHEMA.getField("intArray").getType());
public static final FieldDef<CustomNumber> FIELD_typeRef =
new FieldDef<CustomNumber>("typeRef", CustomNumber.class, SCHEMA.getField("typeRef").getType());
public static DynamicRecordMetadata METADATA;

static
Expand All @@ -101,6 +106,7 @@ public class TestDynamicRecordTemplate
fieldDefs.add(FIELD_record);
fieldDefs.add(FIELD_recordArray);
fieldDefs.add(FIELD_string);
fieldDefs.add(FIELD_typeRef);
METADATA = new DynamicRecordMetadata("dynamic", fieldDefs);
}

Expand Down Expand Up @@ -260,6 +266,53 @@ public void setFixedArray(TestRecordAndUnionTemplate.FixedType[] value)
{
setValue(FIELD_fixedArray, value);
}

public CustomNumber getTypeRef()
{
return getValue(FIELD_typeRef);
}

public void setTypeRef(CustomNumber value)
{
setValue(FIELD_typeRef, value);
}
}

public static class CustomNumber
{
private int _num;

public CustomNumber(int n)
{
_num = n * 100;
}

public int getNum()
{
return _num;
}

public static class CustomNumberCoercer implements DirectCoercer<CustomNumber>
{
public Object coerceInput(CustomNumber object) throws ClassCastException
{
return object.getNum() / 100;
}

public CustomNumber coerceOutput(Object object) throws TemplateOutputCastException
{
if (object instanceof Integer == false)
{
throw new TemplateOutputCastException("Output " + object + " is not a integer, and cannot be coerced to " + CustomNumber.class.getName());
}
return new CustomNumber((Integer) object);
}
}

static
{
Custom.registerCoercer(new CustomNumberCoercer(), CustomNumber.class);
}
}

@Test
Expand Down Expand Up @@ -300,6 +353,15 @@ public void TestComplexTypeFieldsOnDynamicRecord()
Assert.assertEquals(fixed, foo.getFixed());
}

@Test
public void TestTypeRefOnDynamicRecord()
{
DynamicFoo foo = new DynamicFoo();

foo.setTypeRef(new CustomNumber(5));
Assert.assertEquals(500, foo.getTypeRef().getNum());
}

@Test
public void TestArrayFieldsOnDynamicRecord()
{
Expand Down
Expand Up @@ -21,6 +21,7 @@
import com.linkedin.data.DataMap;
import com.linkedin.data.schema.ArrayDataSchema;
import com.linkedin.data.schema.DataSchema;
import com.linkedin.data.schema.DataSchema.Type;
import com.linkedin.data.schema.DataSchemaResolver;
import com.linkedin.data.schema.EnumDataSchema;
import com.linkedin.data.schema.FixedDataSchema;
Expand Down Expand Up @@ -115,6 +116,7 @@
import com.linkedin.restli.server.ResourceLevel;
import com.linkedin.restli.server.RestLiServiceException;
import com.linkedin.restli.server.UpdateResponse;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
Expand Down Expand Up @@ -771,6 +773,14 @@ private void addParams(ActionRequestBuilder<?, ?> request, DynamicRecordMetadata
{
FieldDef<?> fieldDef = requestMetadata.getFieldDef(parameter.getName());
Object value = generateFieldDefValue(fieldDef);
// For custom types(TypeRefs) we generate the example values using the dereferenced type. Changing the field-def
// to the dereferenced type so the example values can be set on the request without coercing.
if (fieldDef.getDataSchema().getType() == Type.TYPEREF)
{
FieldDef<?> deRefFieldDef = new FieldDef<>(fieldDef.getName(), fieldDef.getDataClass(), fieldDef.getDataSchema().getDereferencedDataSchema());
deRefFieldDef.getField().setRecord(fieldDef.getField().getRecord());
fieldDef = deRefFieldDef;
}
request.setParam(fieldDef, value);
}
}
Expand Down
Expand Up @@ -41,6 +41,7 @@
import com.linkedin.restli.examples.greetings.api.Greeting;
import com.linkedin.restli.examples.greetings.server.ActionsResource;
import com.linkedin.restli.examples.greetings.server.CollectionUnderSimpleResource;
import com.linkedin.restli.examples.greetings.server.CustomTypesResource;
import com.linkedin.restli.examples.greetings.server.GreetingsResource;
import com.linkedin.restli.examples.greetings.server.RootSimpleResource;
import com.linkedin.restli.examples.greetings.server.SimpleResourceUnderCollectionResource;
Expand All @@ -65,6 +66,7 @@
import com.linkedin.restli.restspec.RestMethodSchemaArray;
import com.linkedin.restli.restspec.SimpleSchema;
import com.linkedin.restli.server.ResourceLevel;

import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
Expand All @@ -73,6 +75,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.testng.Assert;
import org.testng.annotations.Test;

Expand All @@ -93,7 +96,8 @@ public void testExamples() throws IOException
GroupMembershipsResource2.class,
RootSimpleResource.class,
CollectionUnderSimpleResource.class,
SimpleResourceUnderCollectionResource.class);
SimpleResourceUnderCollectionResource.class,
CustomTypesResource.class);
final ResourceSchemaCollection resourceSchemas = ResourceSchemaCollection.loadOrCreateResourceSchema(resources);
final DataSchemaResolver schemaResolver = new ClassNameDataSchemaResolver();
final ValidationOptions valOptions = new ValidationOptions(RequiredMode.MUST_BE_PRESENT);
Expand All @@ -115,6 +119,9 @@ public void testExamples() throws IOException
final ResourceSchema actions = resourceSchemas.getResource("actions");
ExampleRequestResponseGenerator actionsGenerator = new ExampleRequestResponseGenerator(actions, schemaResolver);

final ResourceSchema customTypes = resourceSchemas.getResource("customTypes");
ExampleRequestResponseGenerator customTypesGenerator = new ExampleRequestResponseGenerator(customTypes, schemaResolver);

List<ResourceSchema> subResources = resourceSchemas.getSubResources(greeting);
final ResourceSchema subgreetings = subResources.get(0);
ExampleRequestResponseGenerator subgreetingsGenerator = new ExampleRequestResponseGenerator(Collections.singletonList(greeting), subgreetings, schemaResolver);
Expand Down Expand Up @@ -251,6 +258,14 @@ public void testExamples() throws IOException
capture = actionsGenerator.action("echoStringArray", ResourceLevel.COLLECTION);
final DataMap echoStringArrayResponse = DataMapUtils.readMap(capture.getResponse());
Assert.assertTrue(echoStringArrayResponse.containsKey("value"));

capture = customTypesGenerator.action("action", ResourceLevel.COLLECTION);
DataMap requestMap = _codec.bytesToMap(capture.getRequest().getEntity().copyBytes());
Assert.assertTrue(requestMap.containsKey("l"));
Assert.assertEquals(requestMap.size(), 1);
final DataMap customTypesActionResponse = DataMapUtils.readMap(capture.getResponse());
Assert.assertTrue(customTypesActionResponse.containsKey("value"));
Assert.assertEquals(customTypesActionResponse.size(), 1);
}

private static void checkPatchMap(DataMap patchMap)
Expand Down

0 comments on commit 0ace10a

Please sign in to comment.