Tutorial #3: Escape

Escape is a tool that traverses multiple DDMS Resource files and then exposes various statistics about them through the Google Visualization API. Charts in this sample application are non-interactive, but provide the foundation for more complex cases: for example, it would be possible to plot Temporal Coverage on an Annotated Timeline, or Geospatial Coverage on Google Maps.

This application would be better suited as a web application, but I have implemented it with Swing, to minimize the amount of overhead required to run it.

Getting Started

You do not need to have any experience with Google Visualization to use this application -- just be aware that it is a web-based tool which accepts a formatted URL and renders some sort of chart.

Escape can be run from the command line with the class, buri.ddmsence.samples.Escape. The application does not accept any command line parameters. A network connection is needed to connect to Google (which also means that this application will not run in a SIPRNET environment).

Please see the "Getting Started" section for classpath details and command line syntax.

Walkthrough

When the application first opens, it will search the data/sample/ directory for any XML files and try to convert them all into Resource objects (DDMSence can currently handle DDMS 2.0 through 5.0). You might see an error message appear in your console, because I have included an invalid metacard file (aptly named 3.0-invalidResourceExample.xml) in the directory, which is used in the Essentials application. Escape will ignore any files it could not convert, so you can safely ignore this message.

With a collection of Resources in hand, Escape examines the data in each Resource and builds frequency distribution charts based on various metrics. The chart that appears initially shows the distribution of MIME Types in the metacards (the ddms:mimeType element nested inside of ddms:Media).

Figure 1. The MIME Types Distribution

The text field below the chart contains the URL used to generate it. You can paste this URL into your web browser to view the same graph.

Now, let's take a look at the source code in /src/samples/buri/ddmsence/samples/Escape.java to see how this was accomplished. The important lines are found in the buildMimeTypeGraph() method:

Distribution distribution = new Distribution();
for (Resource resource : getResources()) {
   // Check any records that have a format (mimeType is required if format is present)
   if (resource.getFormat() != null) {
      String mimeType = resource.getFormat().getMimeType();
      distribution.incrementCount(mimeType);
   }			
}
return (buildPieGraphURL("DDMS%20MimeType%20Distribution", distribution, PIE_GRAPH_3D));

Figure 2. MIME Type source code

The code traverses all of the Format components to maintain a count of each MIME Type. (A simple data class, called Distribution, is used to encapsulate the counts). Once the counts are generated, the data is sent to the buildPieGraphURL() method to render as a Pie Chart in Google-specific terms.

As you can see from the code, a DDMS Resource object can be traversed in a standard way. Each of the top-level components in a Resource record (as well as its attributes) has a getter method, and deeper components can be extracted from those top-level components. If the DDMS schema allows 0 or 1 elements to appear, the getter will return a single DDMS component. If the DDMS schema allows 0 to many elements appear, the getter will return a List of DDMS components. The name of the getter will be a capitalized version of the DDMS element name (such as getVirtualCoverage for ddms:virtualCoverage).

Next, let's click on the "Keywords" tab to see a pie graph of keyword usage.

Figure 3. The Keyword Distribution

Distribution distribution = new Distribution();
for (Resource resource : getResources()) {
   // Check any records that have a keyword (subjectCoverage is required)
   for (SubjectCoverage subjectCoverage : resource.getSubjectCoverages()) {
      if (!subjectCoverage.getKeywords().isEmpty()) {
         List<Keyword> keywords = subjectCoverage.getKeywords();
         // Record the counts for each keyword's usage
         for (Keyword keyword : keywords) {
            // Split multiword keywords.
            String[] splitValues = keyword.getValue().split(" ");
            for (int i = 0; i < splitValues.length; i++) {
               distribution.incrementCount(splitValues[i]);
            }
         }
      }
   }
}
return (buildPieGraphURL("DDMS%20Keyword%20Distribution", distribution, PIE_GRAPH));

Figure 4. Keyword source code

The source code for this statistic is functionally identical to the source code for MIME Types. We are locating the Subject Coverage component in the Resource and then traversing its complete list of Keywords. The only minor difference here is that multi-word Keyword values are being split up into single words (to make the visualization more exciting).

The next visualization can be seen in the "Dates" tab.

Figure 5. The Dates Distribution

The source code for this visualization can be found in the buildDateGraph() method. Dates can appear in a DDMS Resource in multiple locations:

Distribution distribution = new Distribution();
for (Resource resource : getResources()) {
   // Examine the ddms:dates element (optional field with optional attributes)
   // Ignores ddms:DateHourMinType dates, which were introduced in DDMS 4.1, to simplify example
   Dates dates = resource.getDates();
   if (dates != null) {
      if (dates.getCreated() != null)
         distribution.incrementCount(String.valueOf(dates.getCreated().getYear()));
      if (dates.getPosted() != null)
         distribution.incrementCount(String.valueOf(dates.getPosted().getYear()));
      if (dates.getValidTil() != null)
         distribution.incrementCount(String.valueOf(dates.getValidTil().getYear()));
      if (dates.getInfoCutOff() != null)
         distribution.incrementCount(String.valueOf(dates.getInfoCutOff().getYear()));
      if (dates.getApprovedOn() != null)
         distribution.incrementCount(String.valueOf(dates.getApprovedOn().getYear()));
      if (dates.getReceivedOn() != null)
         distribution.incrementCount(String.valueOf(dates.getReceivedOn().getYear()));
   }
   
   // Resource createDate (required field in 3.0, 4.0.1, and 4.1, optional in 2.0)
   if (resource.getCreateDate() != null)
      distribution.incrementCount(String.valueOf(resource.getCreateDate().getYear()));
   
   // ddms:temporalCoverage (optional field)
   // getStart() returns the date if present. getStartString() returns the XML format or
   // the two allowed strings, Not Applicable, and Unknown.
   List<TemporalCoverage> timePeriods = resource.getTemporalCoverages();
   for (TemporalCoverage timePeriod : timePeriods) {
      if (timePeriod.getStart() != null)
         distribution.incrementCount(String.valueOf(timePeriod.getStart().getYear()));
      if (timePeriod.getEnd() != null)
         distribution.incrementCount(String.valueOf(timePeriod.getEnd().getYear()));
   }   
}
return (buildPieGraphURL("DDMS%20Date%20Distribution", distribution, PIE_GRAPH));

Figure 6. Date source code

For this visualization, all date locations are checked, and then transformed into xs:year values (the Java pattern "YYYY"). The distribution is then tracked as it was in the previous two examples. A more useful graph might show just expiration dates or time periods -- I added the additional dates to provide more examples of traversing a Resource, and to make the visualization more exciting.

The final distribution in the "DDMS Versions" tab shows the DDMS versions of the loaded Resources, based on the XML namespaces in the files. Notice that DDMS 4.0.1 instances are grouped together with DDMS 4.1 instances as "4.1", since both version share the same XML namespace.

Figure 6. The Version Distribution

If you would like to add new Resources to the dataset, simply copy your XML files into the data/samples/ directory, or use the Escort wizard application to generate Resources. When you open up Escape again, your new files will be included in the metrics.

Conclusion

In this tutorial, you have seen how to traverse a valid DDMS Resource in Java, and how the Java representations can be used as a gateway to apply DDMS concepts in unexpected contexts.

This is the final tutorial. If you have any suggestions for additional tutorials or sample applications, please contact me in one of the ways mentioned under Feedback!

Tutorial #1: Essentials
Tutorial #2: Escort
Tutorial #3: Escape (you are here)
Back to Samples Documentation