public static DataMap processProjections(DataMap dataMap, Map<String, List<String>> result)
  {
    //We send this through the pipeline and migrate from the dataMap into the result
    for (final String parameterName : RestConstants.PROJECTION_PARAMETERS)
    {
      if (dataMap.containsKey(parameterName))
      {
        processIndividualProjection(dataMap, result, parameterName);
      }
    }

    //If there were no projection parameters, we simply return the unmodified dataMap
    return dataMap;
  }
@Test
  public void testProcessProjections()
  {
    //Construct a MaskTree from a series of PathSpecs. Extract the subsequent Datamap representation.
    final MaskTree rootObjectsMask = MaskCreator
        .createPositiveMask(new PathSpec("foo", PathSpec.WILDCARD, "bar"));

    final MaskTree metadataMask = MaskCreator
        .createPositiveMask(new PathSpec("foo", "bar"), new PathSpec("bar", "baz"), new PathSpec("qux"));

    final MaskTree pagingMask = MaskCreator
        .createPositiveMask(new PathSpec("total"), new PathSpec("count"), new PathSpec("links", PathSpec.WILDCARD, "rel"));

    final DataMap resultMap = new DataMap(4); //For each type of projection, plus one query string parameter
    resultMap.put(RestConstants.FIELDS_PARAM, rootObjectsMask.getDataMap());
    resultMap.put(RestConstants.METADATA_FIELDS_PARAM, metadataMask.getDataMap());
    resultMap.put(RestConstants.PAGING_FIELDS_PARAM, pagingMask.getDataMap());
    resultMap.put("someQueryString", "someValue");

    final Map<String, List<String>> processedProjections = new LinkedHashMap<>();
    final DataMap processedDataMap = QueryParamsDataMap.processProjections(resultMap, processedProjections);
    Assert.assertTrue(processedDataMap.size() == 1, "Processed datamap should only have one item left!");

    final Map<String, Set<String>> expectedProcessedProjections = new LinkedHashMap<>();
    //"{fields=[foo:($*:(bar))], metadataFields=[foo:(bar),bar:(baz),qux], pagingFields=[total,count,links:($*:(rel))]}"
    expectedProcessedProjections.put(RestConstants.FIELDS_PARAM, Collections.singleton("foo:($*:(bar))"));
    expectedProcessedProjections.put(RestConstants.METADATA_FIELDS_PARAM,
        new HashSet<>(Arrays.asList("foo:(bar)", "bar:(baz)", "qux")));
    expectedProcessedProjections.put(RestConstants.PAGING_FIELDS_PARAM,
        new HashSet<>(Arrays.asList("total", "count", "links:($*:(rel))")));

    Assert.assertEquals(processedProjections.size(), expectedProcessedProjections.size(), "We must have the correct number of" +
        " expected projections!");
    for (final Map.Entry<String, List<String>> entry : processedProjections.entrySet())
    {
      //Acceptable because these are always comma delimited
      final Set<String> actualProjectionValueSet = new HashSet<>(Arrays.asList(entry.getValue().get(0).split(",")));
      Assert.assertEquals(actualProjectionValueSet, expectedProcessedProjections.get(entry.getKey()), "The individual projection " +
          "for " + entry.getKey() + " does not match what is expected!");
    }
  }