Author: [log in to unmask]
Date: Wed Sep 16 17:31:20 2015
New Revision: 3620
Log:
Updates to datacat client.
Modified:
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatClient.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatClientFactory.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatClientImpl.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatConstants.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/Dataset.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetDataType.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetFileFormat.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetImpl.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetLocation.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetLocationImpl.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetMetadata.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetSite.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetUtilities.java
java/trunk/datacat-client/src/main/java/org/hps/datacat/client/HttpUtilities.java
java/trunk/datacat-client/src/test/java/org/hps/datacat/client/DatacatClientTest.java
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatClient.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatClient.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatClient.java Wed Sep 16 17:31:20 2015
@@ -6,89 +6,102 @@
/**
* Interface to the SLAC SRS datacat system via HTTP/REST calls.
- *
+ *
* @author Jeremy McCormick, SLAC
*/
public interface DatacatClient {
/**
* Add a dataset to the data catalog.
- *
+ *
* @param folder the folder which must already exist
* @param dataType the data type
* @param resource the resource (path)
- * @param site the site of the file
+ * @param site the site of the file
* @param fileFormat the file format
* @param name the name of the dataset
* @param metadata metadata to assign to the dataset
* @return the HTTP status code from the request
*/
- int addDataset(String folder,
- DatasetDataType dataType,
- String resource,
- DatasetSite site,
- DatasetFileFormat fileFormat,
- String name,
- Map<String, Object> metadata);
-
- /**
- * Create a folder in the data catalog.
- *
- * @param folder the folder's path
- * @return the HTTP status code from the request
- */
- int makeFolder(String folder);
-
+ int addDataset(String folder, DatasetDataType dataType, String resource, DatasetSite site,
+ DatasetFileFormat fileFormat, String name, Map<String, Object> metadata);
+
/**
* Add metadata to an existing dataset.
- *
+ *
* @param folder the folder
* @param datasetName the name of the dataset
- * @param metaData the map of metadata where values can be <code>String</code>, <code>Integer</code> or <code>Float</code>
+ * @param metaData the map of metadata where values can be <code>String</code>, <code>Integer</code> or
+ * <code>Float</code>
* @return the HTTP status code from the request
*/
int addMetadata(String folder, String datasetName, Map<String, Object> metaData);
-
- /**
- * Remove a folder from the catalog.
- * <p>
- * It must be empty or an error will occur.
- *
- * @param folder the folder path
- * @return the HHTP status code from the request
- */
- int removeFolder(String folder);
-
+
/**
* Delete a dataset from the catalog.
* <p>
* This has no affect on the underlying resource (file).
- *
+ *
* @param path the path of the dataset
* @return the HTTP status code from the reqest
*/
int deleteDataset(String path);
-
+
+ /**
+ * Return <code>true</code> if the path exists in the datacat.
+ *
+ * @param path the path in the datacat
+ * @return <code>true</code> if the path exists
+ */
+ boolean exists(String path);
+
/**
* Find datasets in the catalog.
* <p>
* See <a href="http://docs.datacatalog.apiary.io/#search">Search Doc</a> for more details.
- *
+ *
* @param folder the folder path
* @param query the query to execute
* @return the HTTP status code from the request
*/
List<Dataset> findDatasets(String folder, String query, Set<String> showMetadata);
-
- // TODO: method to get dataset from path
- // to get all metadata need the site in query
- // http://localhost:8080/datacat-v0.4-SNAPSHOT/r/path.json/HPS/derp/herp01;s=SLAC
- // use HTTP GET
- // Dataset getDataSet(String path);
-
- // TODO: method to determine if folder or dataset exists
- // http://localhost:8080/datacat-v0.4-SNAPSHOT/r/path.json/HPS/derp/derp
- // will return
- // {"message":"File doesn't exist","type":"NoSuchFileException","cause":"Unable to resolve /HPS/derp/derp in parent Name: derp\tPath: /HPS/derp\t"}
- // boolean exists(String path);
+
+ /**
+ * Get a dataset from its path.
+ * <p>
+ * Example URL:
+ *
+ * <pre>
+ * http://localhost:8080/datacat-v0.4-SNAPSHOT/r/path.json/HPS/data/hps_005772.evio.0;s=SLAC
+ * </pre>
+ *
+ * @param path the path in the data catalog
+ * @return the dataset
+ */
+ Dataset getDataSet(String path, DatasetSite site);
+
+ /**
+ * Return <code>true</code> if path is a folder in the data catalog.
+ *
+ * @return <code>true</code> if path is a folder in the data catalog
+ */
+ boolean isFolder(String path);
+
+ /**
+ * Create a folder in the data catalog.
+ *
+ * @param folder the folder's path
+ * @return the HTTP status code from the request
+ */
+ int makeFolder(String folder);
+
+ /**
+ * Remove a folder from the catalog.
+ * <p>
+ * It must be empty or an error will occur.
+ *
+ * @param folder the folder path
+ * @return the HHTP status code from the request
+ */
+ int removeFolder(String folder);
}
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatClientFactory.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatClientFactory.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatClientFactory.java Wed Sep 16 17:31:20 2015
@@ -1,11 +1,11 @@
package org.hps.datacat.client;
/**
- * Factory class for providing user access to interfaces with protected implementation classes.
+ * Factory class for providing user access to interfaces that have protected implementations.
*
* @author Jeremy McCormick, SLAC
*/
-public class DatacatClientFactory {
+public final class DatacatClientFactory {
/**
* Create a datacat client.
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatClientImpl.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatClientImpl.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatClientImpl.java Wed Sep 16 17:31:20 2015
@@ -13,54 +13,54 @@
import java.util.logging.Logger;
import org.json.JSONObject;
+import org.lcsim.util.log.DefaultLogFormatter;
import org.lcsim.util.log.LogUtil;
-import org.lcsim.util.log.MessageOnlyLogFormatter;
/**
* Implementation of {@link DatacatClient} interface for working with SRS datacat REST API.
- *
+ *
* @author Jeremy McCormick, SLAC
*/
final class DatacatClientImpl implements DatacatClient {
-
+
/**
* Setup class logging.
*/
- private static Logger LOGGER = LogUtil.create(DatacatClientImpl.class, new MessageOnlyLogFormatter(), Level.ALL);
+ private static Logger LOGGER = LogUtil.create(DatacatClientImpl.class, new DefaultLogFormatter(), Level.ALL);
+
+ /**
+ * The root directory (e.g. should be 'HPS').
+ */
+ private final String rootDir;
+
+ /**
+ * The site (SLAC or JLAB).
+ */
+ private final DatasetSite site;
/**
* The base URL of the datacat server.
*/
private URL url;
-
- /**
- * The site (SLAC or JLAB).
- */
- private DatasetSite site;
-
- /**
- * The root directory (e.g. should be 'HPS').
- */
- private String rootDir;
-
+
/**
* Create client with default parameters.
*/
- DatacatClientImpl() {
+ DatacatClientImpl() {
this(DatacatConstants.BASE_URL, DatasetSite.SLAC, DatacatConstants.ROOT_DIR);
}
-
+
/**
* Create client.
- *
- * @param baseUrl
- * @param site
- * @param rootDir
- */
- DatacatClientImpl(String url, DatasetSite site, String rootDir) {
+ *
+ * @param baseUrl the base URL of the data catalog application
+ * @param site the default site where physical files are located
+ * @param rootDir the root directory in the data catalog
+ */
+ DatacatClientImpl(final String url, final DatasetSite site, final String rootDir) {
try {
this.url = new URL(url);
- } catch (MalformedURLException e) {
+ } catch (final MalformedURLException e) {
throw new IllegalArgumentException("The URL is bad.", e);
}
if (site == null) {
@@ -71,147 +71,227 @@
throw new IllegalArgumentException("The root dir argument is null.");
}
this.rootDir = rootDir;
- LOGGER.config("url: " + url);
- LOGGER.config("site: " + site);
- LOGGER.config("rootDir: " + rootDir);
- }
-
- /**
- * Remove a folder from the catalog.
- * <p>
- * It must be empty or an error will occur.
- *
- * @param folder the folder path
- * @return the HHTP status code from the request
- */
- @Override
- public int removeFolder(String folder) {
- String fullUrl = url.toString() + "/r/folders.json/" + this.rootDir + folder;
- LOGGER.info("removing folder: " + fullUrl);
- return HttpUtilities.doDelete(fullUrl);
+ LOGGER.config("url: " + url + "; site: " + site + "rootDir: " + rootDir);
+ }
+
+ /**
+ * Add a dataset to the data catalog.
+ *
+ * @param folder the logical folder in the datacat, which must already exist
+ * @param dataType the data type
+ * @param resource the resource (path on the file system)
+ * @param site the site of the file
+ * @param fileFormat the file format
+ * @param name the name of the dataset
+ * @param metadata metadata to assign to the dataset
+ * @return the HTTP status code from the request
+ */
+ @Override
+ public int addDataset(final String folder, final DatasetDataType dataType, final String resource,
+ final DatasetSite site, final DatasetFileFormat fileFormat, final String name,
+ final Map<String, Object> metadata) {
+ final Map<String, Object> parameters = new HashMap<String, Object>();
+ parameters.put("dataType", dataType.toString());
+ parameters.put("resource", resource);
+ parameters.put("site", DatasetSite.SLAC.name());
+ parameters.put("fileFormat", fileFormat.toString());
+ parameters.put("name", name);
+ final JSONObject jsonDataset = JSONUtilities.createJSONDataset(parameters, metadata);
+ final String urlLocation = url + "/r/datasets.json/" + this.rootDir + "/" + folder;
+ LOGGER.info("addDataset: " + urlLocation);
+ LOGGER.info("dataset JSON: " + jsonDataset.toString());
+ return HttpUtilities.doPost(urlLocation, jsonDataset.toString());
+ }
+
+ /**
+ * Add metadata to an existing dataset.
+ *
+ * @param folder the folder
+ * @param datasetName the name of the dataset
+ * @param metaData the map of metadata where values can be <code>String</code>, <code>Integer</code> or
+ * <code>Float</code>
+ * @return the HTTP status code from the request
+ */
+ @Override
+ public int addMetadata(final String folder, final String name, final Map<String, Object> metaData) {
+ final JSONObject object = new JSONObject();
+ object.put("versionMetadata", JSONUtilities.createJSONMetadataArray(metaData));
+ final String patchUrl = this.url.toString() + "/r/datasets.json/" + this.rootDir + "/" + folder + "/" + name
+ + ";v=current;s=" + this.site;
+ LOGGER.info("addMetadata: " + patchUrl);
+ return HttpUtilities.doPatch(patchUrl, object.toString());
}
/**
* Delete a dataset from the catalog.
* <p>
- * This has no affect on the underlying resource (file).
- *
+ * This has no affect on the underlying resource (file on disk).
+ *
* @param path the path of the dataset
* @return the HTTP status code from the reqest
*/
@Override
- public int deleteDataset(String path) {
- String urlLocation = url.toString() + "/r/datasets.json/" + this.rootDir + path;
+ public int deleteDataset(final String path) {
+ final String urlLocation = url.toString() + "/r/datasets.json/" + this.rootDir + path;
LOGGER.info("deleting dataset: " + urlLocation);
return HttpUtilities.doDelete(urlLocation);
}
-
+
+ /**
+ * Return <code>true</code> if the path exists.
+ *
+ * @param path the path in the data catalog
+ */
+ @Override
+ public boolean exists(final String path) {
+ if (path == null) {
+ throw new IllegalArgumentException("The path is null.");
+ }
+ if (path.length() == 0) {
+ throw new IllegalArgumentException("The path is a blank string.");
+ }
+ final String urlLocation = this.url + "/r/path.json/" + this.rootDir + "/" + path;
+ final StringBuffer output = new StringBuffer();
+ final int status = HttpUtilities.doGet(urlLocation, output);
+ if (status > 400) {
+ throw new RuntimeException("HTTP GET returned error status: " + status);
+ }
+ final JSONObject jsonObject = new JSONObject(output.toString());
+ return jsonObject.has("_type");
+ }
+
+ /**
+ * Find datasets in the catalog.
+ * <p>
+ * See <a href="http://docs.datacatalog.apiary.io/#search">Search Doc</a> for more details
+ * on search syntax.
+ *
+ * @param folder the folder path
+ * @param query the query statement to execute
+ * @return the HTTP status code from the request
+ */
+ @Override
+ public List<Dataset> findDatasets(final String directory, final String query, final Set<String> showMetadata) {
+
+ String urlLocation = this.url.toString() + "/r/search.json/" + this.rootDir + "/";
+ if (directory != null) {
+ urlLocation += directory;
+ }
+ urlLocation += ";s=" + this.site.name() + "?";
+
+ // Encode query string so it will be a valid URL.
+ if (query != null) {
+ String encoded = null;
+ try {
+ encoded = URLEncoder.encode(query, "UTF-8");
+ } catch (final UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ urlLocation += "filter=" + encoded;
+ }
+
+ // Metadata fields to show.
+ if (showMetadata != null) {
+ for (final String metadataField : showMetadata) {
+ urlLocation += "&show=" + metadataField;
+ }
+ }
+
+ LOGGER.info("findDatasets: " + urlLocation);
+ final StringBuffer outputBuffer = new StringBuffer();
+ final int response = HttpUtilities.doGet(urlLocation, outputBuffer);
+ if (response >= 400) {
+ throw new RuntimeException("HTTP GET returned error code: " + response);
+ }
+
+ // Build and return dataset list
+ final JSONObject searchResults = new JSONObject(outputBuffer.toString());
+ LOGGER.info("returning search results: " + searchResults.toString());
+ return DatasetUtilities.getDatasetsFromSearch(searchResults);
+ }
+
+ /**
+ * Get a dataset from its path.
+ *
+ * @param path the path in the data catalog
+ * @return the dataset
+ */
+ @Override
+ public Dataset getDataSet(final String path, final DatasetSite site) {
+ if (path == null) {
+ throw new IllegalArgumentException("The path is null.");
+ }
+ if (path.length() == 0) {
+ throw new IllegalArgumentException("The path is a blank string.");
+ }
+ if (site == null) {
+ throw new IllegalArgumentException("The site is null.");
+ }
+ String urlLocation = this.url + "/r/path.json/" + this.rootDir;
+ if (!path.startsWith("/")) {
+ urlLocation += "/";
+ }
+ urlLocation += path + ";s=" + site.name();
+ final StringBuffer output = new StringBuffer();
+ HttpUtilities.doGet(urlLocation, output);
+ return new DatasetImpl(new JSONObject(output.toString()));
+ }
+
+ /**
+ * Return <code>true</code> if path is a folder in the data catalog.
+ *
+ * @return <code>true</code> if path is a folder in the data catalog
+ */
+ @Override
+ public boolean isFolder(final String path) {
+ if (path == null) {
+ throw new IllegalArgumentException("The path is null.");
+ }
+ if (path.length() == 0) {
+ throw new IllegalArgumentException("The path is a blank string.");
+ }
+ final String urlLocation = this.url + "/r/path.json/" + this.rootDir + "/" + path;
+ final StringBuffer output = new StringBuffer();
+ final int status = HttpUtilities.doGet(urlLocation, output);
+ if (status > 400) {
+ throw new RuntimeException("HTTP GET query returned error status: " + status);
+ }
+ final JSONObject jsonObject = new JSONObject(output.toString());
+ return jsonObject.has("_type") ? "folder".equals(jsonObject.getString("_type")) : false;
+ }
+
/**
* Create a folder in the data catalog.
- *
+ *
* @param folder the folder's path
* @return the HTTP status code from the request
*/
@Override
- public int makeFolder(String path) {
- Map<String, Object> parameters = new HashMap<String, Object>();
+ public int makeFolder(final String path) {
+ final Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("path", "/" + DatacatConstants.ROOT_DIR + "/" + path);
- String name = new File(path).getName();
+ final String name = new File(path).getName();
parameters.put("name", name);
parameters.put("_type", "folder");
- JSONObject object = JSONUtilities.createJSONFromMap(parameters);
- String urlLocation = url + "/r/folders.json/" + this.rootDir;
+ final JSONObject object = JSONUtilities.createJSONFromMap(parameters);
+ final String urlLocation = url + "/r/folders.json/" + this.rootDir;
LOGGER.info("making folder: " + urlLocation);
LOGGER.info("folder JSON: " + object.toString());
return HttpUtilities.doPost(urlLocation, object.toString());
}
-
- /**
- * Add metadata to an existing dataset.
- *
- * @param folder the folder
- * @param datasetName the name of the dataset
- * @param metaData the map of metadata where values can be <code>String</code>, <code>Integer</code> or <code>Float</code>
- * @return the HTTP status code from the request
- */
- @Override
- public int addMetadata(String folder, String name, Map<String, Object> metaData) {
- JSONObject object = new JSONObject();
- object.put("versionMetadata", JSONUtilities.createJSONMetadataArray(metaData));
- String patchUrl = this.url.toString() + "/r/datasets.json/" + this.rootDir + "/" + folder + "/" + name + ";v=current;s=" + this.site;
- LOGGER.info("addMetadata: " + patchUrl);
- return HttpUtilities.doPatch(patchUrl, object.toString());
- }
-
- /**
- * Find datasets in the catalog.
+
+ /**
+ * Remove a folder from the catalog.
* <p>
- * See <a href="http://docs.datacatalog.apiary.io/#search">Search Doc</a> for more details.
- *
+ * It must be empty or an error will occur.
+ *
* @param folder the folder path
- * @param query the query to execute
- * @return the HTTP status code from the request
- */
- @Override
- public List<Dataset> findDatasets(String directory, String query, Set<String> showMetadata) {
-
- String urlLocation = this.url.toString() + "/r/search.json/" + this.rootDir + "/";
- if (directory != null) {
- urlLocation += directory;
- }
- urlLocation += ";s=" + this.site.name() + "?";
- if (query != null) {
- String encoded = null;
- try {
- encoded = URLEncoder.encode(query, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
- urlLocation += "filter=" + encoded;
- }
- if (showMetadata != null) {
- for (String metadataField : showMetadata) {
- urlLocation += "&show=" + metadataField;
- }
- }
- LOGGER.info("findDatasets: " + urlLocation);
- StringBuffer outputBuffer = new StringBuffer();
- int response = HttpUtilities.doGet(urlLocation, outputBuffer);
- if (response >= 400) {
- throw new RuntimeException("HTTP GET failed with code: " + response);
- }
-
- // Build and return dataset list
- JSONObject searchResults = new JSONObject(outputBuffer.toString());
- LOGGER.info("returning search results: " + searchResults.toString());
- return DatasetUtilities.getDatasetsFromSearch(searchResults);
- }
-
- /**
- * Add a dataset to the data catalog.
- *
- * @param folder the folder which must already exist
- * @param dataType the data type
- * @param resource the resource (path)
- * @param site the site of the file
- * @param fileFormat the file format
- * @param name the name of the dataset
- * @param metadata metadata to assign to the dataset
- * @return the HTTP status code from the request
- */
- @Override
- public int addDataset(String folder, DatasetDataType dataType, String resource, DatasetSite site,
- DatasetFileFormat fileFormat, String name, Map<String, Object> metadata) {
- Map<String, Object> parameters = new HashMap<String, Object>();
- parameters.put("dataType", dataType.toString());
- parameters.put("resource", resource);
- parameters.put("site", DatasetSite.SLAC.name());
- parameters.put("fileFormat", fileFormat.toString());
- parameters.put("name", name);
- JSONObject jsonDataset = JSONUtilities.createJSONDataset(parameters, metadata);
- String urlLocation = url + "/r/datasets.json/" + this.rootDir + "/" + folder;
- LOGGER.info("addDataset: " + urlLocation);
- LOGGER.info("dataset JSON: " + jsonDataset.toString());
- return HttpUtilities.doPost(urlLocation, jsonDataset.toString());
+ * @return the HHTP status code from the request
+ */
+ @Override
+ public int removeFolder(final String folder) {
+ final String fullUrl = url.toString() + "/r/folders.json/" + this.rootDir + folder;
+ LOGGER.info("removing folder: " + fullUrl);
+ return HttpUtilities.doDelete(fullUrl);
}
}
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatConstants.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatConstants.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatacatConstants.java Wed Sep 16 17:31:20 2015
@@ -15,6 +15,6 @@
/**
* The base URL of the datacat server.
*/
- // FIXME: This needs to be more easily configurable and not hard-coded.
+ // FIXME: Development server location.
public static final String BASE_URL = "http://localhost:8080/datacat-v0.4-SNAPSHOT";
}
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/Dataset.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/Dataset.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/Dataset.java Wed Sep 16 17:31:20 2015
@@ -4,9 +4,10 @@
import java.util.List;
/**
+ * Representation of a dataset in the data catalog.
+ *
*
* @author Jeremy McCormick, SLAC
- *
*/
public interface Dataset {
@@ -18,7 +19,7 @@
String getName();
/**
- * Get the path of the dataset e.g. "/HPS/folder/dataset01".
+ * Get the logical path of the dataset e.g. "/HPS/folder/dataset01".
*
* @return the path of the dataset
*/
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetDataType.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetDataType.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetDataType.java Wed Sep 16 17:31:20 2015
@@ -1,14 +1,29 @@
package org.hps.datacat.client;
/**
+ * Dataset types for HPS.
*
* @author Jeremy McCormick, SLAC
- *
*/
public enum DatasetDataType {
+ /**
+ * Data quality management plots.
+ */
DQM,
+ /**
+ * Raw data (EVIO).
+ */
RAW,
+ /**
+ * Reconstructed data (usually LCIO).
+ */
RECON,
+ /**
+ * Digital Summary Tape files (ROOT).
+ */
DST,
+ /**
+ * Test type (don't use in production).
+ */
TEST;
}
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetFileFormat.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetFileFormat.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetFileFormat.java Wed Sep 16 17:31:20 2015
@@ -1,14 +1,61 @@
package org.hps.datacat.client;
+
/**
+ * Dataset file formats for HPS.
*
* @author Jeremy McCormick, SLAC
- *
*/
public enum DatasetFileFormat {
- EVIO,
- LCIO,
- ROOT,
- AIDA,
- TEST;
+
+ /**
+ * EVIO data format.
+ */
+ EVIO(),
+ /**
+ * LCIO data format (note custom file extension).
+ */
+ LCIO("slcio"),
+ /**
+ * ROOT files.
+ */
+ ROOT(),
+ /**
+ * AIDA files.
+ */
+ AIDA(),
+ /**
+ * Testing only (do not use in production).
+ */
+ TEST(null);
+
+ /**
+ * The file extension of the format.
+ */
+ private String extension;
+
+ /**
+ * Create a file format with an extension.
+ *
+ * @param extension the file's extension
+ */
+ private DatasetFileFormat(String extension) {
+ this.extension = extension;
+ }
+
+ /**
+ * Create a file format with default extension (lower case of enum name).
+ */
+ private DatasetFileFormat() {
+ this.extension = this.name().toLowerCase();
+ }
+
+ /**
+ * Get the format's file extension.
+ *
+ * @return the format file extension
+ */
+ public String extension() {
+ return extension;
+ }
}
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetImpl.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetImpl.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetImpl.java Wed Sep 16 17:31:20 2015
@@ -11,27 +11,106 @@
import org.json.JSONObject;
/**
+ * Implementation of the {@link Dataset} interface.
*
* @author Jeremy McCormick, SLAC
- *
*/
final class DatasetImpl implements Dataset {
+ /**
+ * The name of the dataset.
+ */
private String name;
+
+ /**
+ * The path in the datacatalog which is folder + name.
+ */
private String path;
+
+ /**
+ * The data type of the file.
+ */
private DatasetDataType dataType;
+
+ /**
+ * The format of the file.
+ */
private DatasetFileFormat fileFormat;
+
+ /**
+ * The list of file locations.
+ */
private List<DatasetLocation> locations = new ArrayList<DatasetLocation>();
+
+ /**
+ * The creation date.
+ */
private Date created;
+
+ /**
+ * The dataset's metadata.
+ */
private DatasetMetadata metadata;
+ /**
+ * Parser for reading in dates from JSON.
+ */
private static final SimpleDateFormat DATE_PARSER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+ /**
+ * Create a new dataset from JSON.
+ *
+ * @param jsonObject the JSON data
+ */
DatasetImpl(JSONObject jsonObject) {
- parse(jsonObject);
- }
+ if (!jsonObject.has("_type")) {
+ throw new IllegalArgumentException("JSON object is missing _type field.");
+ }
+ if (!jsonObject.getString("_type").startsWith("dataset")) {
+ throw new IllegalArgumentException("JSON _type field is not a dataset: " + jsonObject.getString("_type"));
+ }
- private void parse(JSONObject jsonObject) {
+ if (jsonObject.getString("_type").equals("dataset#flat")) {
+ parseFlat(jsonObject);
+ } else if (jsonObject.getString("_type").equals("dataset#full")) {
+ parseFull(jsonObject);
+ } else {
+ throw new IllegalArgumentException("Unknown dataset type: " + jsonObject.getString("_type"));
+ }
+ }
+
+ /**
+ * Parse the flat JSON representation.
+ *
+ * @param jsonObject the JSON object
+ */
+ private void parseFlat(JSONObject jsonObject) {
+ name = jsonObject.getString("name");
+ path = jsonObject.getString("path");
+ DatasetLocationImpl location = new DatasetLocationImpl(
+ DatasetSite.valueOf(jsonObject.getString("site")),
+ jsonObject.getString("resource"),
+ jsonObject.getInt("size"),
+ ScanStatus.valueOf(jsonObject.getString("scanStatus")));
+ location.setEventCount(jsonObject.getInt("eventCount"));
+ location.setRunMin(jsonObject.getInt("runMin"));
+ location.setRunMax(jsonObject.getInt("runMax"));
+ locations.add(location);
+ dataType = DatasetDataType.valueOf(jsonObject.getString("dataType"));
+ fileFormat = DatasetFileFormat.valueOf(jsonObject.getString("fileFormat"));
+ try {
+ created = DATE_PARSER.parse(jsonObject.getString("created"));
+ } catch (ParseException e) {
+ throw new IllegalArgumentException("Bad created value: " + jsonObject.getString("created"), e);
+ }
+ }
+
+ /**
+ * Parse the full JSON representation.
+ *
+ * @param jsonObject the JSON object
+ */
+ private void parseFull(JSONObject jsonObject) {
if (!jsonObject.getString("_type").equals("dataset#full")) {
throw new IllegalArgumentException("Wrong _type in JSON data: " + jsonObject.getString("_type"));
}
@@ -53,41 +132,81 @@
}
}
+ /**
+ * Get the name of the dataset without the path component e.g. "dataset01".
+ *
+ * @return the name of the dataset
+ */
@Override
public String getName() {
return this.name;
}
+ /**
+ * Get the logical path of the dataset e.g. "/HPS/folder/dataset01".
+ *
+ * @return the path of the dataset
+ */
@Override
public String getPath() {
return this.path;
}
+ /**
+ * Get the dataset locations.
+ *
+ * @return the dataset locations
+ */
@Override
public List<DatasetLocation> getLocations() {
return Collections.unmodifiableList(this.locations);
}
+ /**
+ * Get the file format e.g. EVIO, LCIO, etc.
+ *
+ * @return the dataset file format
+ */
@Override
public DatasetFileFormat getFileFormat() {
return this.fileFormat;
}
+ /**
+ * Get the data type e.g. RAW, RECON, etc.
+ *
+ * @return the data type
+ */
@Override
public DatasetDataType getDataType() {
return this.dataType;
}
+ /**
+ * Get the creation date.
+ *
+ * @return the creation date
+ */
@Override
public Date getCreated() {
return this.created;
}
+ /**
+ * Get the dataset's metadata.
+ *
+ * @return the dataset's metadata
+ */
@Override
public DatasetMetadata getMetadata() {
return this.metadata;
}
+ /**
+ * Convert this object to a string.
+ *
+ * @return this object converted to a string
+ */
public String toString() {
return "Dataset { name: " + name + ", path:" + path + ", " + "dataType: " + dataType.name() + "fileFormat: " + fileFormat.name() + ", created: " + created + " }";
}
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetLocation.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetLocation.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetLocation.java Wed Sep 16 17:31:20 2015
@@ -1,23 +1,61 @@
package org.hps.datacat.client;
/**
+ * Representation of a dataset location in the data catalog.
*
* @author Jeremy McCormick, SLAC
- *
*/
public interface DatasetLocation {
+ /**
+ * Get the site of the dataset (JLAB or SLAC).
+ *
+ * @return the dataset site
+ */
DatasetSite getSite();
+ /**
+ * Get the resource of the dataset location (file system path).
+ *
+ * @return the resource of the dataset location
+ */
String getResource();
+ /**
+ * Get the scan status of the dataset location.
+ *
+ * @return the scan status
+ */
ScanStatus getScanStatus();
+ /**
+ * The size of the file in bytes.
+ *
+ * @return the size of the file in bytes
+ */
long getSize();
+ /**
+ * Get the minimum run number.
+ *
+ * @return the minimum run number
+ */
+ // FIXME: Belongs in dataset metadata.
int getRunMin();
+ /**
+ * Get the maximum run number.
+ *
+ * @return the maximum run number
+ */
+ // FIXME: Belongs in dataset metadata.
int getRunMax();
+ /**
+ * Get the event count.
+ *
+ * @return the event count
+ */
+ // FIXME: Belongs in dataset metadata.
int getEventCount();
}
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetLocationImpl.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetLocationImpl.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetLocationImpl.java Wed Sep 16 17:31:20 2015
@@ -3,23 +3,76 @@
import org.json.JSONObject;
/**
+ * Implementation of {@link DatasetLocation} interface.
*
* @author Jeremy McCormick, SLAC
*/
final class DatasetLocationImpl implements DatasetLocation {
+ /**
+ * The dataset's site.
+ */
private DatasetSite site;
+
+ /**
+ * The resource on the file system.
+ */
private String resource;
+
+ /**
+ * The scan status.
+ */
private ScanStatus scanStatus = ScanStatus.UNKNOWN;
+
+ /**
+ * The size of the file in bytes.
+ */
private long size;
+
+ /**
+ * The minimum run number.
+ */
private int runMin;
+
+ /**
+ * The maximum run number.
+ */
private int runMax;
+
+ /**
+ * The event count.
+ */
private int eventCount;
+ /**
+ * Create a dataset location.
+ *
+ * @param site the site of the dataset location
+ * @param resource the source on disk
+ * @param size the size of the file
+ * @param scanStatus the scan status
+ */
+ DatasetLocationImpl(DatasetSite site, String resource, long size, ScanStatus scanStatus) {
+ this.site = site;
+ this.resource = resource;
+ this.scanStatus = scanStatus;
+ this.size = size;
+ }
+
+ /**
+ * Create a dataset location from JSON.
+ *
+ * @param jsonObject the JSON object
+ */
DatasetLocationImpl(JSONObject jsonObject) {
parse(jsonObject);
}
+ /**
+ * Parse JSON data into this object.
+ *
+ * @param jsonObject the JSON data
+ */
private void parse(JSONObject jsonObject) {
if (!jsonObject.getString("_type").equals("location")) {
throw new IllegalArgumentException("Wrong _type in JSON data: " + jsonObject.getString("_type"));
@@ -35,39 +88,100 @@
this.eventCount = jsonObject.getInt("eventCount");
}
+ /**
+ * Get the site of the dataset (JLAB or SLAC).
+ *
+ * @return the dataset site
+ */
@Override
public DatasetSite getSite() {
return this.site;
}
+ /**
+ * Get the resource of the dataset location (file system path).
+ *
+ * @return the resource of the dataset location
+ */
@Override
public String getResource() {
return resource;
}
+ /**
+ * Get the scan status of the dataset location.
+ *
+ * @return the scan status
+ */
@Override
public ScanStatus getScanStatus() {
return scanStatus;
}
+ /**
+ * The size of the file in bytes.
+ *
+ * @return the size of the file in bytes
+ */
@Override
public long getSize() {
return this.size;
}
+ /**
+ * Get the minimum run number.
+ *
+ * @return the minimum run number
+ */
@Override
public int getRunMin() {
return this.runMin;
}
+ /**
+ * Get the maximum run number.
+ *
+ * @return the maximum run number
+ */
@Override
public int getRunMax() {
return this.runMax;
}
-
+
+ /**
+ * Get the event count.
+ *
+ * @return the event count
+ */
@Override
public int getEventCount() {
return this.eventCount;
}
-
+
+ /**
+ * Set the minimum run number.
+ *
+ * @param runMin the minimum run number
+ */
+ void setRunMin(int runMin) {
+ this.runMin = runMin;
+ }
+
+ /**
+ * Set the maximum run number.
+ *
+ * @param runMax the maximum run number
+ */
+ void setRunMax(int runMax) {
+ this.runMax = runMax;
+ }
+
+ /**
+ * Set the event count.
+ *
+ * @param eventCount the event count
+ */
+ void setEventCount(int eventCount) {
+ this.eventCount = eventCount;
+ }
}
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetMetadata.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetMetadata.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetMetadata.java Wed Sep 16 17:31:20 2015
@@ -1,8 +1,7 @@
package org.hps.datacat.client;
-
/**
- * Dataset metadata which is keys and values that are double, integer or string.
+ * Dataset metadata which is string keys and values that are double, integer or string.
*
* @author Jeremy McCormick, SLAC
*/
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetSite.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetSite.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetSite.java Wed Sep 16 17:31:20 2015
@@ -1,9 +1,9 @@
package org.hps.datacat.client;
/**
+ * Site of a dataset (SLAC or JLAB).
*
* @author Jeremy McCormick, SLAC
- *
*/
public enum DatasetSite {
/**
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetUtilities.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetUtilities.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/DatasetUtilities.java Wed Sep 16 17:31:20 2015
@@ -7,7 +7,7 @@
import org.json.JSONObject;
/**
- * Dataset utilities.
+ * Dataset utilities for the crawler.
*
* @author Jeremy McCormick, SLAC
*/
Modified: java/trunk/datacat-client/src/main/java/org/hps/datacat/client/HttpUtilities.java
=============================================================================
--- java/trunk/datacat-client/src/main/java/org/hps/datacat/client/HttpUtilities.java (original)
+++ java/trunk/datacat-client/src/main/java/org/hps/datacat/client/HttpUtilities.java Wed Sep 16 17:31:20 2015
@@ -4,7 +4,6 @@
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
@@ -19,50 +18,39 @@
import org.apache.http.util.EntityUtils;
/**
- *
* @author Jeremy McCormick, SLAC
*/
final class HttpUtilities {
/**
- * Do an HTTP POST.
- *
+ * Do an HTTP DELETE.
+ *
* @param urlLocation the URL location
- * @param data the data to stream to the server
* @return the HTTP response code
*/
- static int doPost(String urlLocation, String data) {
+ static int doDelete(final String urlLocation) {
int responseCode = 0;
try {
- URL url = new URL(urlLocation);
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- connection.setRequestMethod("POST");
- connection.setRequestProperty("Content-Type", "application/json");
+ final URL url = new URL(urlLocation);
+ final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
- if (data != null) {
- OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
- out.write(data);
- out.close();
- }
- System.out.println("url: " + urlLocation);
- System.out.println("data: " + data);
- System.out.println("response: " + connection.getResponseCode());
- System.out.println("message: " + connection.getResponseMessage());
+ connection.setRequestMethod("DELETE");
+ connection.connect();
responseCode = connection.getResponseCode();
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new RuntimeException(e);
}
return responseCode;
}
-
+
/**
* Do an HTTP get and return the output from the server in a <code>StringBuffer</code>.
- *
+ *
* @param urlLocation the URL location
* @param stringBuffer the string buffer with the server output
* @return the HTTP response
*/
- static int doGet(String urlLocation, StringBuffer stringBuffer) {
+ static int doGet(final String urlLocation, final StringBuffer stringBuffer) {
HttpURLConnection connection = null;
int response = 0;
try {
@@ -73,94 +61,83 @@
connection.setDoInput(true);
connection.connect();
if (stringBuffer != null) {
- String output = IOUtils.toString(connection.getInputStream(), "UTF-8");
+ final String output = IOUtils.toString(connection.getInputStream(), "UTF-8");
stringBuffer.append(output);
}
response = connection.getResponseCode();
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new RuntimeException(e);
} finally {
connection.disconnect();
}
return response;
- }
-
+ }
+
/**
* Do an HTTP patch.
- *
+ *
* @param urlLocation the URL location
* @param data the data to stream to the server
* @return the HTTP response code
*/
- static int doPatch(String urlLocation, String data) {
- int responseCode = 0;
- CloseableHttpClient httpClient = HttpClients.createDefault();
+ static int doPatch(final String urlLocation, final String data) {
+ int responseCode = 0;
+ final CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPatch httpPatch = null;
try {
- httpPatch = new HttpPatch(new URI(urlLocation));
- InputStreamEntity entity =
- new InputStreamEntity(
- new ByteArrayInputStream(
- data.getBytes("UTF-8")),
- -1,
- ContentType.APPLICATION_JSON);
- httpPatch.setEntity(entity);
- CloseableHttpResponse response = httpClient.execute(httpPatch);
+ httpPatch = new HttpPatch(new URI(urlLocation));
+ final InputStreamEntity entity = new InputStreamEntity(new ByteArrayInputStream(data.getBytes("UTF-8")),
+ -1, ContentType.APPLICATION_JSON);
+ httpPatch.setEntity(entity);
+ final CloseableHttpResponse response = httpClient.execute(httpPatch);
try {
EntityUtils.consume(response.getEntity());
} finally {
response.close();
}
responseCode = response.getStatusLine().getStatusCode();
- } catch (URISyntaxException e) {
+ } catch (final URISyntaxException e) {
throw new IllegalArgumentException(e);
- } catch(IOException e) {
+ } catch (final IOException e) {
throw new RuntimeException(e);
} finally {
try {
httpClient.close();
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new RuntimeException(e);
}
- }
+ }
return responseCode;
- }
-
+ }
+
/**
- * Do an HTTP DELETE.
- *
+ * Do an HTTP POST.
+ *
* @param urlLocation the URL location
+ * @param data the data to stream to the server
* @return the HTTP response code
*/
- static int doDelete(String urlLocation) {
+ static int doPost(final String urlLocation, final String data) {
int responseCode = 0;
try {
- URL url = new URL(urlLocation);
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ final URL url = new URL(urlLocation);
+ final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("POST");
+ connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
- connection.setRequestMethod("DELETE");
- connection.connect();
+ if (data != null) {
+ final OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
+ out.write(data);
+ out.close();
+ }
+ System.out.println("url: " + urlLocation);
+ System.out.println("data: " + data);
+ System.out.println("response: " + connection.getResponseCode());
+ System.out.println("message: " + connection.getResponseMessage());
responseCode = connection.getResponseCode();
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new RuntimeException(e);
}
return responseCode;
- }
-
- /*
- static URL createURL(String... chunks) {
- if (chunks.length == 0) {
- throw new IllegalArgumentException("No arguments provided.");
- }
- String urlString = "";
- for (String chunk : chunks) {
- urlString += chunk;
- }
- try {
- return new URL(urlString);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException("Bad URL string: " + urlString);
- }
- }
- */
+ }
}
Modified: java/trunk/datacat-client/src/test/java/org/hps/datacat/client/DatacatClientTest.java
=============================================================================
--- java/trunk/datacat-client/src/test/java/org/hps/datacat/client/DatacatClientTest.java (original)
+++ java/trunk/datacat-client/src/test/java/org/hps/datacat/client/DatacatClientTest.java Wed Sep 16 17:31:20 2015
@@ -9,68 +9,68 @@
import junit.framework.TestCase;
/**
- *
* @author Jeremy McCormick, SLAC
- *
*/
public class DatacatClientTest extends TestCase {
-
+
private static final String DATASET_NAME = "dummyDataset";
private static final String FOLDER = "dummyFolder";
private static final String RESOURCE = "/path/to/dummyDataset.ds";
-
+
public void testDatacat() throws Exception {
// Datacat client with default parameters.
- DatacatClient client = new DatacatClientImpl();
-
+ final DatacatClient client = new DatacatClientImpl();
+
// Stores response from HTTP operations
int response = -1;
-
+
// Create dummy folder.
response = client.makeFolder("dummyFolder");
-
+
+ // TODO: check that folder exists
+ assertTrue(client.isFolder("dummyFolder"));
+
// Add dummy dataset.
- Map<String, Object> dsMetadata = new HashMap<String, Object>();
+ final Map<String, Object> dsMetadata = new HashMap<String, Object>();
dsMetadata.put("testInt", 1);
dsMetadata.put("testFloat", 1.1f);
dsMetadata.put("testDouble", 1.2d);
dsMetadata.put("testString", "herpderp");
- response = client.addDataset(FOLDER, DatasetDataType.TEST, RESOURCE, DatasetSite.SLAC, DatasetFileFormat.TEST, DATASET_NAME, dsMetadata);
-
+ response = client.addDataset(FOLDER, DatasetDataType.TEST, RESOURCE, DatasetSite.SLAC, DatasetFileFormat.TEST,
+ DATASET_NAME, dsMetadata);
+
// Patch the dataset with some meta data.
- Map<String, Object> metaData = new HashMap<String, Object>();
+ final Map<String, Object> metaData = new HashMap<String, Object>();
metaData.put("testInt2", 1234);
response = client.addMetadata(FOLDER, DATASET_NAME, metaData);
-
- // TODO: check that folder exists
-
- // TODO: check that dataset exists
-
+
// TODO: get the full folder info
-
- // TODO: get the full dataset info
-
+
+ // Get the dataset info back.
+ final Dataset gimmeDataset = client.getDataSet(FOLDER + "/" + DATASET_NAME, DatasetSite.SLAC);
+ System.out.println("got dataset " + gimmeDataset.getName());
+
// Find the dataset with a simple query.
- Set<String> metadataFields = new HashSet<String>();
+ final Set<String> metadataFields = new HashSet<String>();
metadataFields.add("testInt");
- metadataFields.add("testFloat");
+ metadataFields.add("testFloat");
metadataFields.add("testDouble");
metadataFields.add("testString");
- List<Dataset> datasets = client.findDatasets(FOLDER, "testInt == 1", metadataFields);
- for (Dataset dataset : datasets) {
+ final List<Dataset> datasets = client.findDatasets(FOLDER, "testInt == 1", metadataFields);
+ for (final Dataset dataset : datasets) {
System.out.println("found dataset: " + dataset.getName());
System.out.println("metadata: " + dataset.getMetadata());
}
-
+
// Delete the dataset.
response = client.deleteDataset("/" + FOLDER + "/" + DATASET_NAME);
System.out.println("deleteDataset: " + response);
System.out.println();
-
+
// Remove the folder.
client.removeFolder("/" + FOLDER);
System.out.println("removeFolder: " + response);
System.out.println();
- }
+ }
}
|