private static String getResourcePath(String rawPath)
  {
    if (rawPath.charAt(0) == '/')
    {
      return rawPath.substring(1);
    }
    return rawPath;
  }
@Test
  public void testCollectionResource() throws Exception
  {
    String idl = moduleDir + FS + IDLS_DIR + FS + "testCollection.restspec.json";
    Set<BuilderSpec> builderSpecs = generateBuilderSpec(new String[] {idl});
    Assert.assertNotNull(builderSpecs);
    Assert.assertTrue(builderSpecs.size() == 15);
    List<String> expectedMethods = Arrays.asList("actionAnotherAction", "actionSomeAction", "actionVoidAction", "batchGet", "create", "delete", "findBySearch", "get", "getAll", "partialUpdate", "update");
    List<String> actualMethods = new ArrayList<>();
    CollectionRootBuilderSpec rootBuilder = null;
    CollectionRootBuilderSpec subRootBuilder = null;
    FinderBuilderSpec finderBuilder = null;
    List<ActionBuilderSpec> actionBuilders = new ArrayList<>();
    List<RestMethodBuilderSpec> basicMethodBuilders = new ArrayList<>();

    for (BuilderSpec spec : builderSpecs)
    {
      if (spec instanceof RootBuilderSpec)
      {
        Assert.assertTrue(spec instanceof CollectionRootBuilderSpec);
        CollectionRootBuilderSpec collSpec = (CollectionRootBuilderSpec)spec;
        if (collSpec.getResourcePath().indexOf('/') >= 0 )
        {
          subRootBuilder = collSpec;
        }
        else
        {
          rootBuilder = collSpec;
        }
      }
      else if (spec instanceof FinderBuilderSpec)
      {
        finderBuilder = (FinderBuilderSpec) spec;
      }
      else if (spec instanceof ActionBuilderSpec)
      {
        actionBuilders.add((ActionBuilderSpec) spec);
      }
      else if (spec instanceof RestMethodBuilderSpec)
      {
        basicMethodBuilders.add((RestMethodBuilderSpec) spec);
      }
      else
      {
        Assert.fail("There should not be any other builder spec generated!");
      }
    }

    // assert sub resource root builder spec
    Assert.assertNotNull(subRootBuilder);
    Assert.assertEquals(subRootBuilder.getSourceIdlName(), idl);
    Assert.assertEquals(subRootBuilder.getResourcePath(), "testCollection/{testCollectionId}/testCollectionSub");
    Assert.assertEquals(subRootBuilder.getParentRootBuilder(), rootBuilder);
    Assert.assertNotNull(subRootBuilder.getRestMethods());
    Assert.assertTrue(subRootBuilder.getRestMethods().size() == 2);
    Assert.assertTrue(subRootBuilder.getFinders().isEmpty());
    Assert.assertTrue(subRootBuilder.getResourceActions().isEmpty());
    Assert.assertTrue(subRootBuilder.getEntityActions().isEmpty());
    Assert.assertTrue(subRootBuilder.getSubresources().isEmpty());

    // assert root builder spec
    Assert.assertNotNull(rootBuilder);
    Assert.assertEquals(rootBuilder.getSourceIdlName(), idl);
    Assert.assertEquals(rootBuilder.getResourcePath(), "testCollection");
    Assert.assertNotNull(rootBuilder.getRestMethods());
    Assert.assertTrue(rootBuilder.getRestMethods().size() == 7);
    for (RootBuilderMethodSpec method : rootBuilder.getRestMethods())
    {
      actualMethods.add(method.getName());
      Assert.assertEquals(method.getReturn().getRootBuilderMethod(), method);
    }
    Assert.assertNotNull(rootBuilder.getFinders());
    Assert.assertTrue(rootBuilder.getFinders().size() == 1);
    actualMethods.add(rootBuilder.getFinders().get(0).getName());
    Assert.assertNotNull(rootBuilder.getResourceActions());
    Assert.assertTrue(rootBuilder.getResourceActions().size() == 1);
    actualMethods.add(rootBuilder.getResourceActions().get(0).getName());
    Assert.assertNotNull(rootBuilder.getEntityActions());
    Assert.assertTrue(rootBuilder.getEntityActions().size() == 2);
    actualMethods.add(rootBuilder.getEntityActions().get(0).getName());
    actualMethods.add(rootBuilder.getEntityActions().get(1).getName());
    Assert.assertNotNull(rootBuilder.getSubresources());
    Assert.assertTrue(rootBuilder.getSubresources().size() == 1);
    Collections.sort(actualMethods);
    Assert.assertEquals(actualMethods, expectedMethods);

    // assert finder builder spec
    Assert.assertNotNull(finderBuilder);
    Assert.assertEquals("search", finderBuilder.getFinderName());
    Assert.assertNotNull(finderBuilder.getQueryParamMethods());
    Assert.assertTrue(finderBuilder.hasBindingMethods());
    Assert.assertEquals(finderBuilder.getMetadataType().getFullName(),
                        "com.linkedin.restli.tools.test.TestRecord");
    Assert.assertTrue(finderBuilder.getQueryParamMethods().size() == 1);
    QueryParamBindingMethodSpec finderQuery = finderBuilder.getQueryParamMethods().get(0);
    Assert.assertEquals(finderQuery.getParamName(), "tone");
    Assert.assertEquals(finderQuery.getMethodName(), "toneParam");
    Assert.assertEquals(finderQuery.getArgType().getFullName(), "com.linkedin.restli.tools.test.TestEnum");
    Assert.assertFalse(finderQuery.isNeedAddParamMethod());
    Assert.assertTrue(finderQuery.isOptional());

    // assert action builder spec
    Assert.assertNotNull(actionBuilders);
    Assert.assertTrue(actionBuilders.size() == 3);
    for (ActionBuilderSpec spec : actionBuilders)
    {
      Assert.assertTrue(spec.getActionName().equals("someAction") || spec.getActionName().equals("anotherAction") || spec.getActionName().equals("voidAction"));
      if (spec.getActionName().equals("voidAction"))
      {
        Assert.assertFalse(spec.hasBindingMethods());
      }
      else
      {
        Assert.assertTrue(spec.hasBindingMethods());
      }
    }

    // assert get method builder query method
    Assert.assertNotNull(basicMethodBuilders);
    Assert.assertTrue(basicMethodBuilders.size() == 9); // 7 for root resource, 2 for sub resource
    for (RestMethodBuilderSpec spec : basicMethodBuilders)
    {
      if (spec.getResourceMethod() == ResourceMethod.GET)
      {
        Assert.assertNotNull(spec.getQueryParamMethods());
        Assert.assertTrue(spec.getQueryParamMethods().size() == 1);
        Assert.assertTrue(spec.hasBindingMethods());
        QueryParamBindingMethodSpec getQuery = spec.getQueryParamMethods().get(0);
        Assert.assertEquals(getQuery.getParamName(), "message");
        Assert.assertEquals(getQuery.getMethodName(), "messageParam");
        Assert.assertEquals(getQuery.getArgType().getSchema().getType(), DataSchema.Type.STRING);
        Assert.assertFalse(getQuery.isNeedAddParamMethod());
        Assert.assertTrue(getQuery.isOptional());
        if (spec.getResource().getName().equals("testCollection"))
        {
          DataMap expected = new DataMap();
          expected.put("someAnnotation", new DataMap());
          Assert.assertEquals(spec.getAnnotations(), expected);
        }
      }
      else if (spec.getResourceMethod() == ResourceMethod.DELETE && spec.getClassName().startsWith("TestCollectionSub"))
      {
        // sub resource delete method should have path keys
        List<PathKeyBindingMethodSpec> pathKeys = spec.getPathKeyMethods();
        Assert.assertNotNull(pathKeys);
        Assert.assertTrue(pathKeys.size() == 1);
        Assert.assertTrue(spec.hasBindingMethods());
        PathKeyBindingMethodSpec pathKeyMethod = pathKeys.get(0);
        Assert.assertEquals(pathKeyMethod.getPathKey(), "testCollectionId");
        Assert.assertEquals(pathKeyMethod.getMethodName(), "testCollectionIdKey");
        Assert.assertEquals(pathKeyMethod.getArgType().getSchema().getType(), DataSchema.Type.LONG);
      }
      else if (spec.getResourceMethod() == ResourceMethod.CREATE)
      {
        Assert.assertEquals(spec.getQueryParamMethods().size(), 1);
        Assert.assertTrue(spec.hasBindingMethods());
        QueryParamBindingMethodSpec queryParam = spec.getQueryParamMethods().get(0);
        Assert.assertEquals(queryParam.getParamName(), "isNullId");
        Assert.assertEquals(queryParam.isOptional(), true);
        DataMap expected = new DataMap();
        expected.put("someOtherAnnotation", new DataMap());
        Assert.assertEquals(spec.getAnnotations(), expected);
      }
    }
  }