@Test
  public void testNoId()
      throws CatalogTransformerException, IOException, XpathException, SAXException {

    // given
    XmlResponseQueueTransformer transformer = new XmlResponseQueueTransformer();

    SourceResponse response = givenSourceResponse(DEFAULT_SOURCE_ID, null);

    // when
    BinaryContent binaryContent = transformer.transform(response, null);

    // then
    assertThat(binaryContent.getMimeType(), is(XmlResponseQueueTransformer.MIME_TYPE));

    byte[] bytes = binaryContent.getByteArray();

    String output = new String(bytes);

    print(output, verboseDebug);

    assertXpathEvaluatesTo(DEFAULT_SOURCE_ID, "/mc:metacards/mc:metacard/mc:source", output);

    assertXpathNotExists("/mc:metacards/mc:metacard/@gml:id", output);

    verifyDefaults("1", output);
  }
  @Test
  public void testMultiple()
      throws CatalogTransformerException, IOException, XpathException, SAXException {

    // given
    XmlResponseQueueTransformer transformer = new XmlResponseQueueTransformer();

    SourceResponse response =
        givenSourceResponse(new MetacardStub("source1", "id1"), new MetacardStub("source2", "id2"));

    // when
    BinaryContent binaryContent = transformer.transform(response, null);

    // then
    assertThat(binaryContent.getMimeType(), is(XmlResponseQueueTransformer.MIME_TYPE));

    byte[] bytes = binaryContent.getByteArray();

    String output = new String(bytes);

    print(output, verboseDebug);

    assertXpathEvaluatesTo("source1", "/mc:metacards/mc:metacard[1]/mc:source", output);

    assertXpathEvaluatesTo("id1", "/mc:metacards/mc:metacard[1]/@gml:id", output);

    assertXpathEvaluatesTo("source2", "/mc:metacards/mc:metacard[2]/mc:source", output);

    assertXpathEvaluatesTo("id2", "/mc:metacards/mc:metacard[2]/@gml:id", output);

    verifyDefaults("1", output);
    verifyDefaults("2", output);
  }
  /**
   * Tests that proper JSON output is received when no {@link Metacard#GEOGRAPHY} is found.
   *
   * @throws CatalogTransformerException
   * @throws IOException
   * @throws ParseException
   */
  @Test
  public void testNoGeo() throws CatalogTransformerException, IOException, ParseException {

    Date now = new Date();

    MetacardImpl metacard = new MetacardImpl();

    setupBasicMetacard(now, metacard);

    GeoJsonMetacardTransformer transformer = new GeoJsonMetacardTransformer();

    BinaryContent content = transformer.transform(metacard, null);

    assertEquals(
        content.getMimeTypeValue(), GeoJsonMetacardTransformer.DEFAULT_MIME_TYPE.getBaseType());

    String jsonText = new String(content.getByteArray());
    LOGGER.debug(jsonText);
    Object object = PARSER.parse(jsonText);

    JSONObject obj2 = (JSONObject) object;

    assertThat(obj2.get("geometry"), nullValue());
    verifyBasicMetacardJson(now, obj2);
  }
  @Test
  public void testWithGeometryCollection()
      throws CatalogTransformerException, IOException, ParseException {

    Date now = new Date();

    MetacardImpl metacard = new MetacardImpl();

    metacard.setLocation("GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))");

    setupBasicMetacard(now, metacard);

    GeoJsonMetacardTransformer transformer = new GeoJsonMetacardTransformer();

    BinaryContent content = transformer.transform(metacard, null);

    assertEquals(
        content.getMimeTypeValue(), GeoJsonMetacardTransformer.DEFAULT_MIME_TYPE.getBaseType());

    String jsonText = new String(content.getByteArray());
    LOGGER.debug(jsonText);
    Object object = PARSER.parse(jsonText);

    JSONObject obj2 = (JSONObject) object;

    Map geometryMap = (Map) obj2.get("geometry");
    assertThat(geometryMap.get(CompositeGeometry.TYPE_KEY).toString(), is(GeometryCollection.TYPE));

    assertThat(geometryMap.get(CompositeGeometry.GEOMETRIES_KEY), notNullValue());

    verifyBasicMetacardJson(now, obj2);
  }
  /**
   * Tests that a POINT Geography can be returned in JSON
   *
   * @throws CatalogTransformerException
   * @throws IOException
   * @throws ParseException
   */
  @Test
  public void testwithPointGeo() throws CatalogTransformerException, IOException, ParseException {

    Date now = new Date();

    MetacardImpl metacard = new MetacardImpl();

    metacard.setLocation(DEFAULT_LOCATION);
    setupBasicMetacard(now, metacard);

    GeoJsonMetacardTransformer transformer = new GeoJsonMetacardTransformer();

    BinaryContent content = transformer.transform(metacard, null);

    assertEquals(
        content.getMimeTypeValue(), GeoJsonMetacardTransformer.DEFAULT_MIME_TYPE.getBaseType());

    String jsonText = new String(content.getByteArray());
    LOGGER.debug(jsonText);
    Object object = PARSER.parse(jsonText);

    JSONObject obj2 = (JSONObject) object;

    Map geometryMap = (Map) obj2.get("geometry");
    assertThat(geometryMap.get(CompositeGeometry.TYPE_KEY).toString(), is(Point.TYPE));
    List<Double> coords = (List<Double>) geometryMap.get(CompositeGeometry.COORDINATES_KEY);
    assertThat(coords.size(), is(2));
    assertThat(coords.get(0), equalTo(1.0));
    assertThat(coords.get(1), equalTo(0.0));

    verifyBasicMetacardJson(now, obj2);
  }
  @Test
  public void testwithPolygonGeoWithHole()
      throws CatalogTransformerException, IOException, ParseException {

    Date now = new Date();

    MetacardImpl metacard = new MetacardImpl();

    metacard.setLocation(
        "POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10),(20 30, 35 35, 30 20, 20 30))");

    setupBasicMetacard(now, metacard);

    GeoJsonMetacardTransformer transformer = new GeoJsonMetacardTransformer();

    BinaryContent content = transformer.transform(metacard, null);

    assertEquals(
        content.getMimeTypeValue(), GeoJsonMetacardTransformer.DEFAULT_MIME_TYPE.getBaseType());

    String jsonText = new String(content.getByteArray());
    LOGGER.debug(jsonText);
    Object object = PARSER.parse(jsonText);

    JSONObject obj2 = (JSONObject) object;

    Map geometryMap = (Map) obj2.get("geometry");
    assertThat(geometryMap.get(CompositeGeometry.TYPE_KEY).toString(), is(Polygon.TYPE));
    List<List> listOfRings = (List<List>) geometryMap.get(CompositeGeometry.COORDINATES_KEY);
    assertThat(listOfRings.size(), is(2));

    List<List> exteriorRing = listOfRings.get(0);
    List<List> interiorRing = listOfRings.get(1);

    testPopularPolygon(exteriorRing);

    List<Double> interiorlist1 = interiorRing.get(0);
    List<Double> interiorlist2 = interiorRing.get(1);
    List<Double> interiorlist3 = interiorRing.get(2);
    List<Double> interiorlist4 = interiorRing.get(3);

    assertThat(interiorlist1.get(0), equalTo(20.0));
    assertThat(interiorlist1.get(1), equalTo(30.0));
    assertThat(interiorlist2.get(0), equalTo(35.0));
    assertThat(interiorlist2.get(1), equalTo(35.0));
    assertThat(interiorlist3.get(0), equalTo(30.0));
    assertThat(interiorlist3.get(1), equalTo(20.0));
    assertThat(interiorlist4.get(0), equalTo(20.0));
    assertThat(interiorlist4.get(1), equalTo(30.0));

    verifyBasicMetacardJson(now, obj2);
  }
  @Test
  public void testwithMultiLineStringGeo()
      throws CatalogTransformerException, IOException, ParseException {

    Date now = new Date();

    MetacardImpl metacard = new MetacardImpl();

    metacard.setLocation("MULTILINESTRING ((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10))");
    setupBasicMetacard(now, metacard);

    GeoJsonMetacardTransformer transformer = new GeoJsonMetacardTransformer();

    BinaryContent content = transformer.transform(metacard, null);

    assertEquals(
        content.getMimeTypeValue(), GeoJsonMetacardTransformer.DEFAULT_MIME_TYPE.getBaseType());

    String jsonText = new String(content.getByteArray());
    LOGGER.debug(jsonText);
    Object object = PARSER.parse(jsonText);

    JSONObject obj2 = (JSONObject) object;

    Map geometryMap = (Map) obj2.get("geometry");
    assertThat(geometryMap.get(CompositeGeometry.TYPE_KEY).toString(), is(MultiLineString.TYPE));
    List<List<List<Double>>> coordsList =
        (List<List<List<Double>>>) geometryMap.get(CompositeGeometry.COORDINATES_KEY);
    assertThat(coordsList.size(), is(2));
    List<List<Double>> list1 = coordsList.get(0);
    List<List<Double>> list2 = coordsList.get(1);
    assertThat(list1.get(0).get(0), equalTo(10.0));
    assertThat(list1.get(0).get(1), equalTo(10.0));
    assertThat(list1.get(1).get(0), equalTo(20.0));
    assertThat(list1.get(1).get(1), equalTo(20.0));
    assertThat(list1.get(2).get(0), equalTo(10.0));
    assertThat(list1.get(2).get(1), equalTo(40.0));

    assertThat(list2.get(0).get(0), equalTo(40.0));
    assertThat(list2.get(0).get(1), equalTo(40.0));
    assertThat(list2.get(1).get(0), equalTo(30.0));
    assertThat(list2.get(1).get(1), equalTo(30.0));
    assertThat(list2.get(2).get(0), equalTo(40.0));
    assertThat(list2.get(2).get(1), equalTo(20.0));
    assertThat(list2.get(3).get(0), equalTo(30.0));
    assertThat(list2.get(3).get(1), equalTo(10.0));

    verifyBasicMetacardJson(now, obj2);
  }
Beispiel #8
0
  private Response sendEvent(String operation, Metacard... metacards) {
    try {
      List<Result> results =
          Arrays.asList(metacards).stream().map(ResultImpl::new).collect(Collectors.toList());

      SourceResponse queryResponse = new QueryResponseImpl(query, results, true, metacards.length);

      LOGGER.debug(
          "Attempting to transform an Event with mime-type: {} & outputSchema: {}",
          mimeType,
          outputSchema);

      QueryResponseTransformer transformer;
      Map<String, Serializable> arguments = new HashMap<>();
      if (StringUtils.isBlank(outputSchema)
          && StringUtils.isNotBlank(mimeType)
          && !XML_MIME_TYPES.contains(mimeType)) {
        transformer = transformerManager.getTransformerByMimeType(mimeType);
      } else {
        transformer = transformerManager.getTransformerBySchema(CswConstants.CSW_OUTPUT_SCHEMA);
        if (elementName != null) {
          arguments.put(CswConstants.ELEMENT_NAMES, elementName.toArray());
        }
        arguments.put(CswConstants.OUTPUT_SCHEMA_PARAMETER, outputSchema);
        arguments.put(CswConstants.ELEMENT_SET_TYPE, elementSetType);
        arguments.put(CswConstants.IS_BY_ID_QUERY, false);
        arguments.put(CswConstants.GET_RECORDS, request);
        arguments.put(CswConstants.RESULT_TYPE_PARAMETER, resultType);
        arguments.put(CswConstants.WRITE_NAMESPACES, false);
      }
      if (transformer == null) {
        throw new WebApplicationException(
            new CatalogTransformerException("Unable to locate Transformer."));
      }

      BinaryContent binaryContent = transformer.transform(queryResponse, arguments);

      if (binaryContent == null) {
        throw new WebApplicationException(
            new CatalogTransformerException("Transformer returned null."));
      }

      return webClient.invoke(operation, binaryContent.getByteArray());
    } catch (IOException | CatalogTransformerException | RuntimeException e) {
      LOGGER.error("Error sending event to {}.", callbackUrl, e);
    }
    return null;
  }
Beispiel #9
0
  @Before
  public void setup() {
    // given
    plugin = new RestReplicatorPlugin(ENDPOINT_ADDRESS);
    transformer = mock(MetacardTransformer.class);
    BinaryContent bc = mock(BinaryContent.class);
    byte[] bytes = {86};
    try {
      when(bc.getByteArray()).thenReturn(bytes);
      when(transformer.transform(isA(Metacard.class), isNull(Map.class))).thenReturn(bc);
    } catch (Exception e) {
      Assert.fail(e.getLocalizedMessage());
    }

    plugin.setTransformer(transformer);
    metacard = getMockMetacard();
  }
  @Test
  public void testWithMultiPolygonGeo()
      throws CatalogTransformerException, IOException, ParseException {

    Date now = new Date();

    MetacardImpl metacard = new MetacardImpl();

    metacard.setLocation(
        "MULTIPOLYGON (((30 10, 10 20, 20 40, 40 40, 30 10)),((15 5, 40 10, 10 20, 5 10, 15 5)))");

    setupBasicMetacard(now, metacard);

    GeoJsonMetacardTransformer transformer = new GeoJsonMetacardTransformer();

    BinaryContent content = transformer.transform(metacard, null);

    assertEquals(
        content.getMimeTypeValue(), GeoJsonMetacardTransformer.DEFAULT_MIME_TYPE.getBaseType());

    String jsonText = new String(content.getByteArray());
    LOGGER.debug(jsonText);
    Object object = PARSER.parse(jsonText);

    JSONObject obj2 = (JSONObject) object;

    Map geometryMap = (Map) obj2.get("geometry");
    assertThat(geometryMap.get(CompositeGeometry.TYPE_KEY).toString(), is(MultiPolygon.TYPE));

    List<List> listOfPolygons = (List<List>) geometryMap.get(CompositeGeometry.COORDINATES_KEY);
    assertThat(listOfPolygons.size(), is(2));

    List<List> polygon1 = listOfPolygons.get(0);
    List<List> polygon2 = listOfPolygons.get(1);

    List<List> polygon1FirstRing = polygon1.get(0);
    List<List> polygon2FirstRing = polygon2.get(0);

    testPopularPolygon(polygon1FirstRing);

    testSecondPolygon(polygon2FirstRing);

    verifyBasicMetacardJson(now, obj2);
  }
  /**
   * No {@link MetacardType} name should use the default name.
   *
   * @throws CatalogTransformerException
   * @throws IOException
   * @throws SAXException
   * @throws XpathException
   */
  @Test
  public void testMetacardTypeName_Empty()
      throws CatalogTransformerException, IOException, XpathException, SAXException {

    // given
    XmlResponseQueueTransformer transformer = new XmlResponseQueueTransformer();

    SourceResponse response = givenMetacardTypeName("");

    // when
    BinaryContent binaryContent = transformer.transform(response, null);

    // then
    assertThat(binaryContent.getMimeType(), is(XmlResponseQueueTransformer.MIME_TYPE));

    byte[] bytes = binaryContent.getByteArray();

    String output = new String(bytes);

    print(output, verboseDebug);

    assertXpathEvaluatesTo(DEFAULT_TYPE_NAME, "/mc:metacards/mc:metacard/mc:type", output);
  }
Beispiel #12
0
  @Before
  public void setUp() throws Exception {
    System.setProperty("ddf.home", ".");
    callbackURI = new URL("https://localhost:12345/services/csw/subscription/event");
    ObjectFactory objectFactory = new ObjectFactory();
    request = new GetRecordsType();
    request.setOutputSchema(CswConstants.CSW_OUTPUT_SCHEMA);
    request.setResultType(ResultType.RESULTS);
    request.getResponseHandler().add(callbackURI.toString());
    queryType = new QueryType();
    elementSetNameType = new ElementSetNameType();
    elementSetNameType.setValue(ElementSetType.BRIEF);
    queryType.setElementSetName(elementSetNameType);
    request.setAbstractQuery(objectFactory.createAbstractQuery(queryType));
    transformerManager = mock(TransformerManager.class);
    transformer = mock(QueryResponseTransformer.class);
    binaryContent = mock(BinaryContent.class);
    when(transformerManager.getTransformerBySchema(
            Matchers.contains(CswConstants.CSW_OUTPUT_SCHEMA)))
        .thenReturn(transformer);
    when(transformer.transform(any(SourceResponse.class), anyMap())).thenReturn(binaryContent);
    when(binaryContent.getByteArray()).thenReturn("byte array with message contents".getBytes());
    query = mock(QueryRequest.class);

    metacard = mock(Metacard.class);
    webclient = mock(WebClient.class);
    mockCxfClientFactory = mock(SecureCxfClientFactory.class);
    response = mock(Response.class);
    subject = mock(Subject.class);

    mockSecurity = mock(Security.class);
    headers.put(Subject.class.toString(), Arrays.asList(new Subject[] {subject}));
    AccessPlugin accessPlugin = mock(AccessPlugin.class);
    accessPlugins.add(accessPlugin);
    when(mockCxfClientFactory.getWebClient()).thenReturn(webclient);
    //        when(webclient.head()).thenReturn(response);
    when(webclient.invoke(anyString(), any(QueryResponse.class))).thenReturn(response);
    when(response.getHeaders()).thenReturn(headers);
    when(accessPlugin.processPostQuery(any(QueryResponse.class)))
        .thenAnswer(
            new Answer<QueryResponse>() {
              @Override
              public QueryResponse answer(InvocationOnMock invocationOnMock) throws Throwable {
                return (QueryResponse) invocationOnMock.getArguments()[0];
              }
            });

    sendEvent = new SendEventExtension(transformerManager, request, query, mockCxfClientFactory);
    sendEvent.setSubject(subject);
  }
  /**
   * Test method for {@link
   * org.codice.ddf.endpoints.OpenSearchEndpoint#processQuery(java.lang.String, java.lang.String,
   * java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String,
   * java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String,
   * java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String,
   * java.lang.String, javax.ws.rs.core.UriInfo, java.lang.String, java.lang.String)} .
   *
   * <p>This test will verify that the string "local" in the sources passed to
   * OpenSearchEndpoint.processQuery is replaced with the local site name (in this case the mocked
   * name "TestSiteName"). The QueryRequest object is checked when the framework.query is called to
   * retrieve the OpenSearchQuery, which contains the Set of sites. An assertion within the Answer
   * object for the call framework.query checks that the sites Set is contains the TEST_SITE_NAME.
   *
   * @throws URISyntaxException
   * @throws FederationException
   * @throws SourceUnavailableException
   * @throws UnsupportedQueryException
   * @throws UnsupportedEncodingException
   * @throws CatalogTransformerException
   */
  @SuppressWarnings("unchecked")
  @Test
  public void testProcessQueryForProperHandlingOfSiteNameLOCAL()
      throws URISyntaxException, UnsupportedQueryException, SourceUnavailableException,
          FederationException, UnsupportedEncodingException, CatalogTransformerException {

    // ***Test setup***
    final String TEST_SITE_NAME = "TestSiteName";

    CatalogFramework mockFramework = mock(CatalogFramework.class);
    FilterBuilder mockFilterBuilder = mock(FilterBuilder.class);

    AttributeBuilder mockAB = mock(AttributeBuilder.class);
    ExpressionBuilder mockEB = mock(ExpressionBuilder.class);
    ContextualExpressionBuilder mockCEB = mock(ContextualExpressionBuilder.class);
    Filter mockFilter = mock(Filter.class);

    when(mockFilterBuilder.attribute(anyString())).thenReturn(mockAB);
    when(mockAB.is()).thenReturn(mockEB);
    when(mockEB.like()).thenReturn(mockCEB);
    when(mockCEB.text(anyString())).thenReturn(mockFilter);

    String searchTerms = "searchForThis";

    // "local" MUST be included
    String sources = "test, local";
    String count = "200";

    // dummy UriInfo, not really used functionally
    UriInfo mockUriInfo = mock(UriInfo.class);
    URI uri = new URI("test");
    when(mockUriInfo.getRequestUri()).thenReturn(uri);

    MultivaluedMap<String, String> mockMVMap = mock(MultivaluedMap.class);
    when(mockMVMap.get("subscription")).thenReturn(null);
    when(mockMVMap.get("interval")).thenReturn(null);
    when(mockUriInfo.getQueryParameters()).thenReturn(mockMVMap);

    @SuppressWarnings("unused")
    BinaryContent mockByteContent = mock(BinaryContent.class);

    // Check on the sites passed in to framework.query
    when(mockFramework.query(any(QueryRequest.class)))
        .thenAnswer(
            new Answer<Object>() {
              public Object answer(InvocationOnMock invocation) {
                QueryRequest queryRequest = (QueryRequest) invocation.getArguments()[0];

                // ***Test verification***
                // This assert is the whole point of this unit test
                Assert.assertTrue(
                    ((OpenSearchQuery) queryRequest.getQuery())
                        .getSiteIds()
                        .contains(TEST_SITE_NAME));

                return new QueryResponseImpl(queryRequest);
              }
            });

    // setup the BinaryContent for the call to Response.ok(...)
    // This is just needed to get the method to complete, the
    BinaryContent mockBinaryContent = mock(BinaryContent.class);
    InputStream is = new ByteArrayInputStream("Test String From InputStream".getBytes("UTF-8"));
    when(mockBinaryContent.getInputStream()).thenReturn(is);
    when(mockBinaryContent.getMimeTypeValue()).thenReturn("text/plain");

    when(mockFramework.transform(any(QueryResponse.class), anyString(), anyMap()))
        .thenReturn(mockBinaryContent);

    OpenSearchEndpoint osEndPoint = new OpenSearchEndpoint(mockFramework, mockFilterBuilder);

    // Call ddfConfigurationUpdated to set the id values to the site name we want
    // local to be replaced with
    Map<String, String> ddfProperties = new HashMap<String, String>();
    ddfProperties.put("id", TEST_SITE_NAME);
    osEndPoint.configurationUpdateCallback(ddfProperties);

    // ***Test Execution***
    osEndPoint.processQuery(
        searchTerms,
        null,
        sources,
        null,
        null,
        count,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        mockUriInfo,
        null,
        null,
        null);
  }
  @Test
  public void testXmlResponseQueueTransformer() throws Exception {

    MetacardImpl mc = new MetacardImpl();

    final String testId = "1234567890987654321";
    final String testSource = "FooBarSource";
    final String testTitle = "Title!";
    final Date testDate = new Date();
    final String testLocation =
        "POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))";
    final byte[] testThumbnail = {
      0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1,
      0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1
    };

    mc.setId(testId);
    mc.setSourceId(testSource);
    mc.setTitle(testTitle);
    mc.setExpirationDate(testDate);
    mc.setLocation(testLocation);
    mc.setThumbnail(testThumbnail);

    String metadata = null;
    FileInputStream stream =
        new FileInputStream(new File("src/test/resources/extensibleMetacard.xml"));
    try {
      FileChannel fc = stream.getChannel();
      MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
      /* Instead of using default, pass in a decoder. */
      metadata = Charset.defaultCharset().decode(bb).toString();
    } finally {
      stream.close();
    }

    mc.setMetadata(metadata);

    Metacard mci = (Metacard) mc;

    XmlResponseQueueTransformer transformer = new XmlResponseQueueTransformer();

    SourceResponse response =
        new SourceResponseImpl(null, Arrays.asList((Result) new ResultImpl(mci)));
    BinaryContent bc = transformer.transform(response, null);

    if (bc == null) {
      fail("Binary Content is null.");
    }

    String outputXml = new String(bc.getByteArray());

    LOGGER.debug(outputXml);

    assertXpathEvaluatesTo(testId, "/mc:metacards/mc:metacard/@gml:id", outputXml);
    assertXpathEvaluatesTo(testSource, "/mc:metacards/mc:metacard/mc:source", outputXml);
    assertXpathEvaluatesTo(
        testTitle, "/mc:metacards/mc:metacard/mc:string[@name='title']/mc:value", outputXml);

    // TODO convert GML representation?
    // outputXml);
    assertXpathExists(
        "/mc:metacards/mc:metacard/mc:geometry[@name='location']/mc:value", outputXml);

    assertXpathExists(
        "/mc:metacards/mc:metacard/mc:base64Binary[@name='thumbnail']/mc:value", outputXml);

    // TODO XML Date representation?
    assertXpathExists(
        "/mc:metacards/mc:metacard/mc:dateTime[@name='expiration']/mc:value", outputXml);
  }