Exemplo n.º 1
0
 private <T> T parse(HttpURLConnection uc, Class<T> type, T instance) throws IOException {
     InputStreamReader r = null;
     try {
         r = new InputStreamReader(wrapStream(uc, uc.getInputStream()), "UTF-8");
         String data = IOUtils.toString(r);
         if (type!=null)
             return MAPPER.readValue(data,type);
         if (instance!=null)
             return MAPPER.readerForUpdating(instance).<T>readValue(data);
         return null;
     } finally {
         IOUtils.closeQuietly(r);
     }
 }
  /**
   * Get a list of tv certification.
   *
   * @return
   * @throws MovieDbException
   */
  public ResultsMap<String, List<Certification>> getTvCertification() throws MovieDbException {
    URL url = new ApiUrl(apiKey, MethodBase.CERTIFICATION).subMethod(MethodSub.TV_LIST).buildUrl();
    String webpage = httpTools.getRequest(url);

    try {
      JsonNode node = MAPPER.readTree(webpage);
      Map<String, List<Certification>> results =
          MAPPER.readValue(
              node.elements().next().traverse(),
              new TypeReference<Map<String, List<Certification>>>() {});
      return new ResultsMap<>(results);
    } catch (IOException ex) {
      throw new MovieDbException(
          ApiExceptionType.MAPPING_FAILED, "Failed to get TV certifications", url, ex);
    }
  }
Exemplo n.º 3
0
 /**
  * Changes the name of the object in its project. The basename of the object is changed to the
  * specified name and it remains in the same folder.
  *
  * <p>The object is renamed in the project or container associated with this {@code DXDataObject},
  * or the environment's workspace if no project or container was explicitly specified.
  *
  * @param newName The new name of the object
  * @throws NullPointerException if this object has no associated project and no workspace is set
  */
 public void rename(String newName) {
   Preconditions.checkNotNull(
       this.container, "Container must be supplied for this metadata operation");
   apiCallOnObject(
       "removeTags",
       MAPPER.valueToTree(new RenameRequest(this.container.getId(), newName)),
       RetryStrategy.SAFE_TO_RETRY);
 }
Exemplo n.º 4
0
 /**
  * Removes the specified tags from the object.
  *
  * <p>The tags are modified in the project or container associated with this {@code DXDataObject},
  * or the environment's workspace if no project or container was explicitly specified.
  *
  * @param tags List of tags to remove
  * @throws NullPointerException if this object has no associated project and no workspace is set
  */
 public void removeTags(List<String> tags) {
   Preconditions.checkNotNull(
       this.container, "Container must be supplied for this metadata operation");
   apiCallOnObject(
       "removeTags",
       MAPPER.valueToTree(new AddOrRemoveTagsRequest(this.container.getId(), tags)),
       RetryStrategy.SAFE_TO_RETRY);
 }
Exemplo n.º 5
0
 /**
  * Sets and removes properties on the object.
  *
  * <p>The properties are modified in the project or container associated with this {@code
  * DXDataObject}, or the environment's workspace if no project or container was explicitly
  * specified.
  *
  * @param propertiesToSet Map from key to value for each property to be set
  * @param propertiesToRemove List of property keys to be removed
  * @throws NullPointerException if this object has no associated project and no workspace is set
  */
 public void putAllProperties(
     Map<String, String> propertiesToSet, List<String> propertiesToRemove) {
   Preconditions.checkNotNull(
       this.container, "Container must be supplied for this metadata operation");
   apiCallOnObject(
       "setProperties",
       MAPPER.valueToTree(
           new SetPropertiesRequest(this.container.getId(), propertiesToSet, propertiesToRemove)),
       RetryStrategy.SAFE_TO_RETRY);
 }
Exemplo n.º 6
0
 private void logQuerySummary() {
   try {
     LoggedQuery q =
         new LoggedQuery(
             QueryIdHelper.getQueryId(queryId),
             queryContext.getQueryContextInfo().getDefaultSchemaName(),
             queryText,
             new Date(queryContext.getQueryContextInfo().getQueryStartTime()),
             new Date(System.currentTimeMillis()),
             state,
             queryContext.getSession().getCredentials().getUserName());
     queryLogger.info(MAPPER.writeValueAsString(q));
   } catch (Exception e) {
     logger.error("Failure while recording query information to query log.", e);
   }
 }
 @Override
 @SuppressWarnings({"rawtypes", "unchecked"})
 public void set(Field field, Object object, Object value) throws JsonMappingException {
   if (value == JSONObject.NULL) {
     return;
   }
   try {
     if (value instanceof JSONArray) {
       JSONArray objectJsonArray = (JSONArray) value;
       List list = new ArrayList();
       for (int i = 0; i < objectJsonArray.length(); i++) {
         ParameterizedType type = (ParameterizedType) field.getGenericType();
         list.add(
             MAPPER.map(
                 objectJsonArray.getJSONObject(i), (Class) type.getActualTypeArguments()[0]));
       }
       field.set(object, list);
     }
   } catch (Exception e) {
     throw new JsonMappingException(e);
   }
 }
Exemplo n.º 8
0
    private void buildRequest(HttpURLConnection uc) throws IOException {
        if (!method.equals("GET")) {
            uc.setDoOutput(true);
            uc.setRequestProperty("Content-type", contentType);

            if (body == null) {
                Map json = new HashMap();
                for (Entry e : args) {
                    json.put(e.key, e.value);
                }
                MAPPER.writeValue(uc.getOutputStream(), json);
            } else {
                try {
                    byte[] bytes = new byte[32768];
                    int read = 0;
                    while ((read = body.read(bytes)) != -1) {
                        uc.getOutputStream().write(bytes, 0, read);
                    }
                } finally {
                    body.close();
                }
            }
        }
    }
Exemplo n.º 9
0
  @Test
  public void testALSSpeed() throws Exception {
    Map<String, Object> overlayConfig = new HashMap<>();
    overlayConfig.put("oryx.speed.model-manager-class", ALSSpeedModelManager.class.getName());
    overlayConfig.put("oryx.speed.streaming.generation-interval-sec", 5);
    overlayConfig.put("oryx.als.hyperparams.features", 2);
    Config config = ConfigUtils.overlayOn(overlayConfig, getConfig());

    startMessaging();

    List<Pair<String, String>> updates =
        startServerProduceConsumeTopics(
            config, new MockALSInputGenerator(), new MockALSModelUpdateGenerator(), 9, 10);

    if (log.isDebugEnabled()) {
      for (Pair<String, String> update : updates) {
        log.debug("{}", update);
      }
    }

    // 10 original updates. 9 generate just 1 update since user or item is new.
    assertEquals(19, updates.size());
    assertEquals("MODEL", updates.get(0).getFirst());
    assertEquals(
        2,
        Integer.parseInt(
            AppPMMLUtils.getExtensionValue(
                PMMLUtils.fromString(updates.get(0).getSecond()), "features")));

    for (int i = 1; i <= 9; i++) {
      assertEquals("UP", updates.get(i).getFirst());
      List<?> update = MAPPER.readValue(updates.get(i).getSecond(), List.class);
      boolean isX = "X".equals(update.get(0).toString());
      String id = update.get(1).toString();
      float[] expected =
          (isX ? MockALSModelUpdateGenerator.X : MockALSModelUpdateGenerator.Y).get(id);
      assertArrayEquals(expected, MAPPER.convertValue(update.get(2), float[].class));
      @SuppressWarnings("unchecked")
      Collection<String> knownUsersItems = (Collection<String>) update.get(3);
      Collection<String> expectedKnownUsersItems =
          (isX ? MockALSModelUpdateGenerator.A : MockALSModelUpdateGenerator.At).get(id);
      assertTrue(knownUsersItems.containsAll(expectedKnownUsersItems));
      assertTrue(expectedKnownUsersItems.containsAll(knownUsersItems));
    }

    /*
     * User 100 - 104 are solutions to eye(5)*Y*pinv(Y'*Y), but default scaling
     * will produce values that are 3/4 of this since they are brand new.
     * That is, it's really the solution to (0.75*eye(5))*Y*pinv(Y'*Y)
     * Likewise 105 - 108 are (0.75*eye(4))*X*pinv(X'*X)
     */

    Map<String, float[]> X =
        MockALSModelUpdateGenerator.buildMatrix(
            100,
            new float[][] {
              {-0.20859924f, 0.25232133f},
              {-0.22472803f, -0.1929485f},
              {-0.15592135f, 0.3977631f},
              {-0.3006522f, -0.12239703f},
              {-0.09205295f, -0.37471837f},
            });
    Map<String, float[]> Y =
        MockALSModelUpdateGenerator.buildMatrix(
            105,
            new float[][] {
              {-0.19663288f, 0.09574106f},
              {-0.23840417f, -0.50850725f},
              {-0.34360975f, 0.2466687f},
              {-0.060204573f, 0.29311115f},
            });

    for (int i = 10; i <= 18; i++) {
      assertEquals("UP", updates.get(i).getFirst());
      List<?> update = MAPPER.readValue(updates.get(i).getSecond(), List.class);
      boolean isX = "X".equals(update.get(0).toString());
      String id = update.get(1).toString();
      float[] expected = (isX ? X : Y).get(id);
      assertArrayEquals(expected, MAPPER.convertValue(update.get(2), float[].class), 1.0e-5f);
      String otherID = ALSUtilsTest.idToStringID(ALSUtilsTest.stringIDtoID(id) - 99);
      @SuppressWarnings("unchecked")
      Collection<String> knownUsersItems = (Collection<String>) update.get(3);
      assertEquals(1, knownUsersItems.size());
      assertEquals(otherID, knownUsersItems.iterator().next());
    }
  }
Exemplo n.º 10
0
 /**
  * Returns metadata about the data object, specifying which optional fields are to be returned and
  * what project to obtain project-specific metadata from.
  *
  * @param options {@code DescribeOptions} object specifying how the {@code describe} request is to
  *     be made.
  * @return a {@code Describe} containing the data object's metadata.
  */
 public Describe describe(DescribeOptions options) {
   return DXJSON.safeTreeToValue(
       apiCallOnObject("describe", MAPPER.valueToTree(options), RetryStrategy.SAFE_TO_RETRY),
       Describe.class);
 }
Exemplo n.º 11
0
 /**
  * Adds the specified types to the object.
  *
  * @param types List of types to add to the object
  */
 public void addTypes(List<String> types) {
   apiCallOnObject(
       "addTypes",
       MAPPER.valueToTree(new AddOrRemoveTypesRequest(types)),
       RetryStrategy.SAFE_TO_RETRY);
 }
Exemplo n.º 12
0
 /**
  * Adds the specified tags to the object.
  *
  * <p>The tags are modified in the project or container associated with this {@code DXDataObject},
  * or the environment's workspace if no project or container was explicitly specified.
  *
  * @param tags List of tags to add to the object
  * @throws NullPointerException if this object has no associated project and no workspace is set
  */
 public void addTags(List<String> tags) {
   apiCallOnObject(
       "addTags",
       MAPPER.valueToTree(new AddOrRemoveTagsRequest(this.container.getId(), tags)),
       RetryStrategy.SAFE_TO_RETRY);
 }
Exemplo n.º 13
0
/** Base class for all data object classes in the DNAnexus Platform. */
public abstract class DXDataObject extends DXObject {

  /** Request to /class-xxxx/{add,remove}Tags */
  @JsonInclude(Include.NON_NULL)
  private static class AddOrRemoveTagsRequest {
    @JsonProperty("project")
    private String projectId;

    @JsonProperty private List<String> tags;

    private AddOrRemoveTagsRequest(String projectId, List<String> tags) {
      this.projectId = projectId;
      this.tags = ImmutableList.copyOf(tags);
    }
  }

  /** Request to /class-xxxx/{add,remove}Types */
  @JsonInclude(Include.NON_NULL)
  private static class AddOrRemoveTypesRequest {
    @JsonProperty private List<String> types;

    private AddOrRemoveTypesRequest(List<String> types) {
      this.types = ImmutableList.copyOf(types);
    }
  }

  /**
   * Abstract builder class for creating a new data object of class {@code U}.
   *
   * @param <T> the builder type subclass
   * @param <U> class of data object to be created
   */
  protected abstract static class Builder<T extends Builder<T, U>, U extends DXDataObject> {

    /**
     * Deserializes the response to a {@code /class-xxxx/new} API call and returns the ID of the
     * newly created object.
     *
     * @return DNAnexus object ID
     */
    protected static String getNewObjectId(JsonNode responseJson) {
      return DXJSON.safeTreeToValue(responseJson, DataObjectNewResponse.class).id;
    }

    protected DXContainer project = null;
    protected String name = null;
    protected String folder = null;
    protected Boolean createParents = null;
    protected List<String> tags = null;
    protected List<String> types = null;
    protected JsonNode details = null;
    protected Boolean hidden = null;

    protected ImmutableMap.Builder<String, String> properties;

    protected final DXEnvironment env;

    protected Builder() {
      this.env = DXEnvironment.create();
    }

    protected Builder(DXEnvironment env) {
      this.env = env;
    }

    /**
     * Adds the specified tags to the newly created data object.
     *
     * @param tags tags to add
     * @return the same {@code Builder} object
     */
    public T addTags(Collection<String> tags) {
      if (this.tags == null) {
        this.tags = Lists.newArrayList();
      }
      this.tags.addAll(Preconditions.checkNotNull(tags, "tags may not be null"));
      return getThisInstance();
    }

    /**
     * Adds the specified types to the newly created data object.
     *
     * @param types types to add
     * @return the same {@code Builder} object
     */
    public T addTypes(Collection<String> types) {
      if (this.types == null) {
        this.types = Lists.newArrayList();
      }
      this.types.addAll(Preconditions.checkNotNull(types, "types may not be null"));
      return getThisInstance();
    }

    /**
     * Creates the new data object.
     *
     * @return a {@code DXDataObject} corresponding to the newly created object
     */
    public abstract U build();

    /**
     * Ensures that the project was either explicitly set or that the environment specifies a
     * workspace.
     */
    protected void checkAndFixParameters() {
      if (this.project == null) {
        this.project = this.env.getWorkspace();
      }
      Preconditions.checkState(
          this.project != null,
          "setProject must be specified if the environment does not have a workspace set");
    }

    /**
     * Returns the builder object.
     *
     * <p>This abstract method is implemented by the Builder methods so that common methods can get
     * an instance of the subclass for chaining purposes.
     *
     * @return the same object
     */
    protected abstract T getThisInstance();

    /**
     * Sets the specified properties on the newly created data object.
     *
     * @param properties Map containing non-null keys and values which will be set as property keys
     *     and values respectively
     * @return the same {@code Builder} object
     */
    public T putAllProperties(Map<String, String> properties) {
      for (Map.Entry<String, String> e : properties.entrySet()) {
        putProperty(e.getKey(), e.getValue());
      }
      return getThisInstance();
    }

    /**
     * Sets the specified property on the newly created data object.
     *
     * @param key property key to set
     * @param value property value to set
     * @return the same {@code Builder} object
     */
    public T putProperty(String key, String value) {
      if (this.properties == null) {
        this.properties = ImmutableMap.builder();
      }
      this.properties.put(
          Preconditions.checkNotNull(key, "Property key may not be null"),
          Preconditions.checkNotNull(value, "Value for property " + key + " may not be null"));
      return getThisInstance();
    }

    /**
     * Sets the details of the data object to be created.
     *
     * @param details an object whose JSON serialized form will be set as the details
     * @return the same {@code Builder} object
     */
    public T setDetails(Object details) {
      Preconditions.checkState(this.details == null, "Cannot call setDetails more than once");
      this.details =
          MAPPER.valueToTree(Preconditions.checkNotNull(details, "details may not be null"));
      return getThisInstance();
    }

    /**
     * Sets the folder in which the data object will be created.
     *
     * @param folder full path to destination folder (a String starting with {@code "/"})
     * @return the same {@code Builder} object
     */
    public T setFolder(String folder) {
      Preconditions.checkState(this.folder == null, "Cannot call setFolder more than once");
      this.folder = Preconditions.checkNotNull(folder, "folder may not be null");
      return getThisInstance();
    }

    /**
     * Sets the folder in which the data object will be created, optionally specifying that the
     * folder and its parents should be created if necessary.
     *
     * @param folder full path to destination folder (a String starting with {@code "/"})
     * @param createParents if true, the folder will be created if it doesn't exist
     * @return the same {@code Builder} object
     */
    public T setFolder(String folder, boolean createParents) {
      Preconditions.checkState(this.folder == null, "Cannot call setFolder more than once");
      this.folder = Preconditions.checkNotNull(folder, "folder may not be null");
      this.createParents = createParents;
      return getThisInstance();
    }

    /**
     * Sets the name of the newly created data object.
     *
     * @param name name to set
     * @return the same {@code Builder} object
     */
    public T setName(String name) {
      Preconditions.checkState(this.name == null, "Cannot call setName more than once");
      this.name = Preconditions.checkNotNull(name, "name may not be null");
      return getThisInstance();
    }

    /**
     * Sets the project or container where the new data object will be created.
     *
     * @param project {@code DXProject} or {@code DXContainer}
     * @return the same {@code Builder} object
     */
    public T setProject(DXContainer project) {
      Preconditions.checkState(this.project == null, "Cannot call setProject more than once");
      this.project = Preconditions.checkNotNull(project, "project may not be null");
      return getThisInstance();
    }

    /**
     * Sets the visibility of the new data object.
     *
     * @param visible if false, the object will be hidden
     * @return the same {@code Builder} object
     */
    public T setVisibility(boolean visible) {
      Preconditions.checkState(this.hidden == null, "Cannot call setVisibility more than once");
      this.hidden = !visible;
      return getThisInstance();
    }
  }

  /** Request to /class/new */
  @JsonInclude(Include.NON_NULL)
  static class DataObjectNewRequest {
    @JsonProperty("project")
    private String projectId;

    @JsonProperty private String name;
    @JsonProperty private String folder;

    @JsonProperty("parents")
    private Boolean createParents;

    @JsonProperty private Boolean hidden;
    @JsonProperty private List<String> types;
    @JsonProperty private JsonNode details;
    @JsonProperty private List<String> tags;
    @JsonProperty private Map<String, String> properties;

    protected <T extends Builder<T, U>, U extends DXDataObject> DataObjectNewRequest(
        Builder<T, U> builder) {
      this.projectId = builder.project.getId();
      this.name = builder.name;
      this.folder = builder.folder;
      this.createParents = builder.createParents;
      this.tags = builder.tags;
      this.types = builder.types;
      this.details = builder.details;
      this.hidden = builder.hidden;

      // If no properties set, omit the field entirely rather than send an empty hash
      if (builder.properties != null) {
        this.properties = builder.properties.build();
      }
    }
  }

  /** Response from /class/new */
  @JsonIgnoreProperties(ignoreUnknown = true)
  private static class DataObjectNewResponse {
    @JsonProperty private String id;
  }

  /**
   * Contains metadata for a data object (fields common to all data objects). All accessors reflect
   * the state of the data object at the time that this object was created.
   */
  @JsonIgnoreProperties(ignoreUnknown = true)
  public static class Describe {
    @JsonProperty private String project;
    @JsonProperty private String id;
    @JsonProperty private List<String> types;
    @JsonProperty private DataObjectState state;
    @JsonProperty private Boolean hidden;
    @JsonProperty private String name;
    @JsonProperty private String folder;
    @JsonProperty private List<String> tags;
    @JsonProperty private JsonNode details;
    @JsonProperty private Map<String, String> properties;
    @JsonProperty private Long created;
    @JsonProperty private Long modified;

    /** Creates a {@code Describe} object with all empty metadata. */
    protected Describe() {}

    // TODO: links, sponsored, createdBy

    /**
     * Returns the creation date of the object.
     *
     * @return creation date
     */
    public Date getCreationDate() {
      Preconditions.checkState(
          this.created != null,
          "creation time is not accessible because it was not retrieved with the describe call");
      return new Date(this.created);
    }

    /**
     * Returns the details of the object. This field may not be available unless {@link
     * DXDataObject#describe(DescribeOptions)} (or {@link
     * DXSearch.FindDataObjectsRequestBuilder#includeDescribeOutput(DXDataObject.DescribeOptions)} )
     * was called with {@link DescribeOptions#withDetails()} set.
     *
     * @param valueType class to deserialize as
     * @return the object's details
     * @throws IllegalStateException if details were not retrieved with the describe call
     */
    public <T> T getDetails(Class<T> valueType) {
      Preconditions.checkState(
          this.details != null,
          "details are not accessible because they were not retrieved with the describe call");
      return DXJSON.safeTreeToValue(this.details, valueType);
    }

    /**
     * Returns the folder that contains the object.
     *
     * @return full path to the containing folder (a String starting with {@code "/"})
     */
    public String getFolder() {
      Preconditions.checkState(
          this.folder != null,
          "folder is not accessible because it was not retrieved with the describe call");
      return this.folder;
    }

    /**
     * Returns the last modification date of the object.
     *
     * @return modification date
     */
    public Date getModificationDate() {
      Preconditions.checkState(
          this.modified != null,
          "modification time is not accessible because it was not retrieved with the describe call");
      return new Date(this.modified);
    }

    /**
     * Returns the name of the object.
     *
     * @return the object's name
     */
    public String getName() {
      Preconditions.checkState(
          this.name != null,
          "name is not accessible because it was not retrieved with the describe call");
      return this.name;
    }

    /**
     * Returns the project or container from which user-provided metadata was retrieved.
     *
     * @return {@code DXProject} or {@code DXContainer}
     */
    public DXContainer getProject() {
      Preconditions.checkState(
          this.project != null,
          "project is not accessible because it was not retrieved with the describe call");
      return DXContainer.getInstance(this.project);
    }

    /**
     * Returns the properties associated with the object. This field may not be available unless
     * {@link DXDataObject#describe(DescribeOptions)} (or {@link
     * DXSearch.FindDataObjectsRequestBuilder#includeDescribeOutput(DXDataObject.DescribeOptions)} )
     * was called with {@link DescribeOptions#withProperties()} set.
     *
     * @return Map of property keys to property values
     * @throws IllegalStateException if properties were not retrieved with the describe call
     */
    public Map<String, String> getProperties() {
      Preconditions.checkState(
          this.properties != null,
          "properties is not accessible because it was not retrieved with the describe call");
      return ImmutableMap.copyOf(this.properties);
    }

    /**
     * Returns the state of the object.
     *
     * @return a {@code DXObjectState} indicating the current state
     */
    public DataObjectState getState() {
      Preconditions.checkState(
          this.state != null,
          "state is not accessible because it was not retrieved with the describe call");
      return this.state;
    }

    /**
     * Returns a list of tags associated with the object.
     *
     * @return List of tags
     */
    public List<String> getTags() {
      Preconditions.checkState(
          this.tags != null,
          "tags is not accessible because it was not retrieved with the describe call");
      // TODO: here and elsewhere, avoid creating this ImmutableList multiple times if the
      // client requests it multiple times.
      return ImmutableList.copyOf(this.tags);
    }

    /**
     * Returns a list of types associated with the object.
     *
     * @return List of types
     */
    public List<String> getTypes() {
      Preconditions.checkState(
          this.types != null,
          "types is not accessible because it was not retrieved with the describe call");
      return ImmutableList.copyOf(this.types);
    }

    /**
     * Returns whether the object is visible.
     *
     * @return true if the object is visible
     */
    public boolean isVisible() {
      Preconditions.checkState(
          this.hidden != null,
          "visibility is not accessible because it was not retrieved with the describe call");
      return !this.hidden;
    }
  }

  /**
   * Configuration options for a describe call on a data object ({@literal e.g.} {@link
   * DXDataObject#describe(DescribeOptions)}) to control what optional fields get returned and what
   * project to obtain project-specific metadata from.
   *
   * <p>Examples:
   *
   * <pre>
   * DescribeOptions.get().inProject(proj).withDetails()<br>
   * DescribeOptions.get().withProperties()
   * </pre>
   */
  @JsonInclude(Include.NON_NULL)
  public static class DescribeOptions {
    /**
     * Returns a default instance of {@code DescribeOptions} that returns no optional fields and
     * selects the project arbitrarily.
     *
     * @return a newly initialized {@code DescribeOptions} object
     */
    public static DescribeOptions get() {
      return new DescribeOptions();
    }

    @JsonProperty("project")
    private final String projectId;

    @JsonProperty private final Boolean properties;
    @JsonProperty private final Boolean details;
    @JsonProperty private final Map<String, Boolean> fields;

    private DescribeOptions() {
      this(null, null, null, null);
    }

    private DescribeOptions(
        String projectId, Map<String, Boolean> fields, Boolean properties, Boolean details) {
      this.projectId = projectId;
      this.fields = fields;
      this.properties = properties;
      this.details = details;
    }

    /**
     * Returns a {@code DescribeOptions} that behaves like the current one, except that
     * project-specific metadata will be retrieved from the specified project or container. Attempts
     * to invoke accessors on the resulting {@link Describe} object corresponding to fields that
     * were not requested will throw {@link IllegalStateException}.
     *
     * @param project project or container from which to obtain project-specific metadata
     * @return a new {@code DescribeOptions} object
     */
    public DescribeOptions inProject(DXContainer project) {
      return new DescribeOptions(project.getId(), this.fields, this.properties, this.details);
    }

    /**
     * Returns a {@code DescribeOptions} that behaves like the current one, except that only the
     * specified fields will be included in the result. Attempts to invoke accessors on the
     * resulting {@link Describe} object corresponding to fields that were not requested will throw
     * {@link IllegalStateException}.
     *
     * @param fieldNamesToInclude API fields to be included
     * @return a new {@code DescribeOptions} object
     */
    public DescribeOptions withCustomFields(String... fieldNamesToInclude) {
      return this.withCustomFields(Lists.newArrayList(fieldNamesToInclude));
    }

    /**
     * Returns a {@code DescribeOptions} that behaves like the current one, except that only the
     * fields in the specified collection will be included in the result.
     *
     * @param fieldNamesToInclude collection of API fields to be included
     * @return a new {@code DescribeOptions} object
     */
    public DescribeOptions withCustomFields(Collection<? extends String> fieldNamesToInclude) {
      Preconditions.checkNotNull(fieldNamesToInclude);
      Preconditions.checkState(
          this.properties == null, "withProperties may not be used with fieldNamesToInclude");
      Preconditions.checkState(
          this.details == null, "withDetails may not be used with fieldNamesToInclude");
      ImmutableMap.Builder<String, Boolean> fieldMap = ImmutableMap.builder();
      for (String fieldNameToInclude : fieldNamesToInclude) {
        fieldMap.put(fieldNameToInclude, true);
      }
      return new DescribeOptions(this.projectId, fieldMap.build(), false, false);
    }

    /**
     * Returns a {@code DescribeOptions} that behaves like the current one, except that the details
     * field will be included in the result.
     *
     * @return a new {@code DescribeOptions} object
     */
    public DescribeOptions withDetails() {
      return new DescribeOptions(this.projectId, null, this.properties, true);
    }

    /**
     * Returns a {@code DescribeOptions} that behaves like the current one, except that the
     * properties field will be included in the result.
     *
     * @return a new {@code DescribeOptions} object
     */
    public DescribeOptions withProperties() {
      return new DescribeOptions(this.projectId, null, true, this.details);
    }
  }

  @JsonInclude(Include.NON_NULL)
  private static class RenameRequest {
    @JsonProperty("project")
    private String projectId;

    @JsonProperty private String name;

    private RenameRequest(String projectId, String name) {
      this.projectId = projectId;
      this.name = name;
    }
  }

  @JsonInclude(Include.NON_NULL)
  private static class SetPropertiesRequest {
    @JsonProperty("project")
    private String projectId;

    @JsonProperty private Map<String, String> properties;

    private SetPropertiesRequest(
        String projectId, Map<String, String> propertiesToSet, List<String> propertiesToUnset) {
      this.projectId = projectId;

      // We don't use ImmutableMap here because it doesn't support null values.
      Map<String, String> propertyMap = Maps.newHashMap();
      for (Map.Entry<String, String> e : propertiesToSet.entrySet()) {
        propertyMap.put(
            Preconditions.checkNotNull(e.getKey(), "Property key may not be null"),
            Preconditions.checkNotNull(
                e.getValue(), "Property value for key " + e.getKey() + " may not be null"));
      }
      for (String propertyToUnset : propertiesToUnset) {
        propertyMap.put(propertyToUnset, null);
      }
      this.properties = Collections.unmodifiableMap(propertyMap);
    }
  }

  @JsonInclude(Include.NON_NULL)
  private static class SetVisibilityRequest {
    @JsonProperty private boolean hidden;

    private SetVisibilityRequest(boolean hidden) {
      this.hidden = hidden;
    }
  }

  // Not sure how to do this (deserialization to a Map object instead of
  // a user-defined class) without bringing in this new ObjectReader
  private static final ObjectReader listProjectsReader =
      MAPPER.reader(
          new TypeReference<Map<String, AccessLevel>>() {
            // Empty body for Jackson's TypeReference
          });

  /**
   * Verifies that the specified map has the format of a DNAnexus link.
   *
   * @param value putative DNAnexus link
   */
  protected static void checkDXLinkFormat(Map<String, Object> value) {
    if (!value.containsKey("$dnanexus_link")) {
      throw new IllegalArgumentException(
          "Object must contain a field $dnanexus_link to be deserialized");
    }
  }

  /**
   * Deserializes a DXDataObject from JSON containing a DNAnexus link.
   *
   * @param value JSON object map
   * @return data object
   */
  @JsonCreator
  private static DXDataObject create(Map<String, Object> value) {
    checkDXLinkFormat(value);
    // TODO: how to set the environment?
    return DXDataObject.getInstance((String) value.get("$dnanexus_link"));
  }

  @VisibleForTesting
  static Map<String, AccessLevel> deserializeListProjectsMap(JsonNode result) {
    try {
      return listProjectsReader.<Map<String, AccessLevel>>readValue(result);
    } catch (JsonProcessingException e) {
      throw new RuntimeException(e);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Returns a {@code DXDataObject} corresponding to an existing object with the specified ID.
   *
   * @param objectId DNAnexus object id
   * @return a {@code DXDataObject} handle to the specified object
   */
  public static DXDataObject getInstance(String objectId) {
    return getInstanceWithEnvironment(objectId, DXEnvironment.create());
  }

  /**
   * Returns a {@code DXDataObject} corresponding to an existing object with the specified ID in the
   * specified project or container.
   *
   * @param objectId DNAnexus object id
   * @param project project or container in which the object resides
   * @return a {@code DXDataObject} handle to the specified object
   */
  public static DXDataObject getInstance(String objectId, DXContainer project) {
    return getInstanceWithEnvironment(objectId, project, DXEnvironment.create());
  }

  /**
   * Returns a {@code DXDataObject} corresponding to an existing object with the specified ID in the
   * specified project or container, using the specified environment, and with the specified cached
   * Describe data.
   *
   * @param objectId DNAnexus object id
   * @param project project or container in which the object resides
   * @param env environment to use to make subsequent API requests
   * @param describe cached Describe output
   * @return a {@code DXDataObject} handle to the specified object
   */
  static DXDataObject getInstanceWithCachedDescribe(
      String objectId, DXContainer project, DXEnvironment env, JsonNode describe) {
    Preconditions.checkNotNull(describe);
    if (objectId.startsWith("record-")) {
      return DXRecord.getInstanceWithCachedDescribe(objectId, project, env, describe);
    } else if (objectId.startsWith("file-")) {
      return DXFile.getInstanceWithCachedDescribe(objectId, project, env, describe);
    } else if (objectId.startsWith("gtable-")) {
      return DXGTable.getInstanceWithCachedDescribe(objectId, project, env, describe);
    } else if (objectId.startsWith("applet-")) {
      return DXApplet.getInstanceWithCachedDescribe(objectId, project, env, describe);
    } else if (objectId.startsWith("workflow-")) {
      return DXWorkflow.getInstanceWithCachedDescribe(objectId, project, env, describe);
    }
    throw new IllegalArgumentException(
        "The object ID " + objectId + " was of an unrecognized or unsupported class.");
  }

  /**
   * Returns a {@code DXDataObject} corresponding to an existing object with the specified ID in the
   * specified project or container, using the specified environment.
   *
   * @param objectId DNAnexus object id
   * @param project project or container in which the object resides
   * @param env environment to use to make subsequent API requests
   * @return a {@code DXDataObject} handle to the specified object
   */
  public static DXDataObject getInstanceWithEnvironment(
      String objectId, DXContainer project, DXEnvironment env) {
    if (objectId.startsWith("record-")) {
      return DXRecord.getInstanceWithEnvironment(objectId, project, env);
    } else if (objectId.startsWith("file-")) {
      return DXFile.getInstanceWithEnvironment(objectId, project, env);
    } else if (objectId.startsWith("gtable-")) {
      return DXGTable.getInstanceWithEnvironment(objectId, project, env);
    } else if (objectId.startsWith("applet-")) {
      return DXApplet.getInstanceWithEnvironment(objectId, project, env);
    } else if (objectId.startsWith("workflow-")) {
      return DXWorkflow.getInstanceWithEnvironment(objectId, project, env);
    }
    throw new IllegalArgumentException(
        "The object ID " + objectId + " was of an unrecognized or unsupported class.");
  }

  /**
   * Returns a {@code DXDataObject} corresponding to an existing object with the specified ID, using
   * the specified environment.
   *
   * @param objectId DNAnexus object id
   * @param env environment to use to make subsequent API requests
   * @return a {@code DXDataObject} handle to the specified object
   */
  public static DXDataObject getInstanceWithEnvironment(String objectId, DXEnvironment env) {
    if (objectId.startsWith("record-")) {
      return DXRecord.getInstanceWithEnvironment(objectId, env);
    } else if (objectId.startsWith("file-")) {
      return DXFile.getInstanceWithEnvironment(objectId, env);
    } else if (objectId.startsWith("gtable-")) {
      return DXGTable.getInstanceWithEnvironment(objectId, env);
    } else if (objectId.startsWith("applet-")) {
      return DXApplet.getInstanceWithEnvironment(objectId, env);
    } else if (objectId.startsWith("workflow-")) {
      return DXWorkflow.getInstanceWithEnvironment(objectId, env);
    }
    throw new IllegalArgumentException(
        "The object ID " + objectId + " was of an unrecognized or unsupported class.");
  }

  private final DXContainer container;
  // TODO: this might be useful to have in the superclass DXObject for other find* routes
  protected final JsonNode cachedDescribe;

  /**
   * Initializes the {@code DXDataObject} to point to the object with the specified ID in the
   * specified project.
   *
   * @param dxId DNAnexus ID of the data object
   * @param className class name that should prefix the ID
   * @param env environment to use for subsequent API requests from this {@code DXDataObject}, or
   *     null to use the default environment
   * @param cachedDescribe JSON hash of the describe output for this object if available, or null
   *     otherwise
   */
  protected DXDataObject(
      String dxId,
      String className,
      DXContainer project,
      DXEnvironment env,
      JsonNode cachedDescribe) {
    super(dxId, Preconditions.checkNotNull(className, "className may not be null"), env);
    this.container = Preconditions.checkNotNull(project, "project may not be null");
    // TODO: should we make a defensive copy?
    this.cachedDescribe = cachedDescribe;
  }

  /**
   * Initializes the {@code DXDataObject} to point to the object with the specified ID in the
   * environment's workspace.
   *
   * <p>Operations that use or retrieve project-specific metadata will fail if the object does not
   * exist in the environment's workspace. When a project is available, you should prefer to set it
   * explicitly via {@link #DXDataObject(String, String, DXContainer, DXEnvironment, JsonNode)} .
   *
   * @param dxId DNAnexus ID of the data object
   * @param className class name that should prefix the ID
   * @param env environment to use for subsequent API requests from this {@code DXDataObject}, or
   *     null to use the default environment
   * @param cachedDescribe JSON hash of the describe output for this object if available, or null
   *     otherwise
   */
  protected DXDataObject(
      String dxId, String className, DXEnvironment env, JsonNode cachedDescribe) {
    super(dxId, Preconditions.checkNotNull(className, "className may not be null"), env);
    this.container = null;
    // TODO: should we make a defensive copy?
    this.cachedDescribe = cachedDescribe;
  }

  /**
   * Adds the specified tags to the object.
   *
   * <p>The tags are modified in the project or container associated with this {@code DXDataObject},
   * or the environment's workspace if no project or container was explicitly specified.
   *
   * @param tags List of tags to add to the object
   * @throws NullPointerException if this object has no associated project and no workspace is set
   */
  public void addTags(List<String> tags) {
    apiCallOnObject(
        "addTags",
        MAPPER.valueToTree(new AddOrRemoveTagsRequest(this.container.getId(), tags)),
        RetryStrategy.SAFE_TO_RETRY);
  }

  /**
   * Adds the specified types to the object.
   *
   * @param types List of types to add to the object
   */
  public void addTypes(List<String> types) {
    apiCallOnObject(
        "addTypes",
        MAPPER.valueToTree(new AddOrRemoveTypesRequest(types)),
        RetryStrategy.SAFE_TO_RETRY);
  }

  /**
   * Verifies that this object carries cached describe data.
   *
   * @throws IllegalStateException if cachedDescribe is not set.
   */
  protected void checkCachedDescribeAvailable() throws IllegalStateException {
    if (this.cachedDescribe == null) {
      throw new IllegalStateException("This object contains no cached describe data.");
    }
  }

  /**
   * Closes the data object.
   *
   * <p>Returns the same object so you can chain calls.
   *
   * @return the same {@code DXDataObject}
   */
  public DXDataObject close() {
    apiCallOnObject("close", RetryStrategy.SAFE_TO_RETRY);
    return this;
  }

  /**
   * Closes the data object and waits until the close operation is complete.
   *
   * <p>Returns the same object so you can chain calls.
   *
   * @return the same {@code DXDataObject}
   */
  public DXDataObject closeAndWait() {
    DXDataObject obj = this.close();
    // TODO: allow supplying a timeout
    while (true) {
      DataObjectState currentState =
          this.describe(DescribeOptions.get().withCustomFields(ImmutableList.of("state")))
              .getState();
      if (currentState == DataObjectState.CLOSED) {
        return obj;
      }
      if (currentState == DataObjectState.ABANDONED) {
        throw new IllegalStateException("data object " + this.getId() + " has been abandoned");
      }
      // TODO: some kind of exponential backoff so short requests don't
      // take 2000ms to complete
      try {
        Thread.sleep(2000);
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
    }
  }

  /**
   * Returns metadata about the data object.
   *
   * <p>The properties and details fields will not be returned, and any project-specific metadata
   * fields will be selected from an arbitrary project in which the requesting user has access to
   * this object. To change either of these aspects of this behavior, use {@link
   * #describe(DescribeOptions)} instead.
   *
   * @return a {@code Describe} containing the data object's metadata.
   */
  public Describe describe() {
    return DXJSON.safeTreeToValue(
        apiCallOnObject("describe", RetryStrategy.SAFE_TO_RETRY), Describe.class);
  }

  /**
   * Returns metadata about the data object, specifying which optional fields are to be returned and
   * what project to obtain project-specific metadata from.
   *
   * @param options {@code DescribeOptions} object specifying how the {@code describe} request is to
   *     be made.
   * @return a {@code Describe} containing the data object's metadata.
   */
  public Describe describe(DescribeOptions options) {
    return DXJSON.safeTreeToValue(
        apiCallOnObject("describe", MAPPER.valueToTree(options), RetryStrategy.SAFE_TO_RETRY),
        Describe.class);
  }

  /*
   * (non-Javadoc)
   *
   * @see java.lang.Object#equals(java.lang.Object)
   */
  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!super.equals(obj)) {
      return false;
    }
    if (!(obj instanceof DXDataObject)) {
      return false;
    }
    DXDataObject other = (DXDataObject) obj;
    if (container == null) {
      if (other.container != null) {
        return false;
      }
    } else if (!container.equals(other.container)) {
      return false;
    }
    return true;
  }

  /**
   * Returns metadata about the data object, like {@link DXDataObject#describe()}, but without
   * making an API call.
   *
   * <p>This cached describe info is only available if this object appears in the result of a {@link
   * DXSearch#findDataObjects()} call that specified {@link
   * DXSearch.FindDataObjectsRequestBuilder#includeDescribeOutput()}, and the describe info that is
   * returned reflects the state of the object at the time that the search was performed.
   *
   * @return a {@code Describe} containing the data object's metadata
   * @throws IllegalStateException if no cached describe info is available
   */
  public Describe getCachedDescribe() {
    this.checkCachedDescribeAvailable();
    return DXJSON.safeTreeToValue(this.cachedDescribe, Describe.class);
  }

  /**
   * Returns a DNAnexus link for this object. This is the JSON serializer so it makes it suitable to
   * provide an object with references to DXDataObjects as the input when running a {@link
   * DXApplet}, etc.
   *
   * @return a DNAnexus link
   */
  @JsonValue
  private JsonNode getDXLink() {
    return DXJSON.getObjectBuilder().put("$dnanexus_link", this.getId()).build();
  }

  /**
   * Returns the object's project or container, if it was explicitly supplied.
   *
   * @return project or container, or {@code null} if none was specified at object creation time
   */
  public DXContainer getProject() {
    return this.container;
  }

  /*
   * (non-Javadoc)
   *
   * @see java.lang.Object#hashCode()
   */
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = super.hashCode();
    result = prime * result + ((container == null) ? 0 : container.hashCode());
    return result;
  }

  /**
   * Returns the set of projects that contain this object, and which the requesting user has
   * permissions to access.
   *
   * @return Mapping from project ID to the user's access level in that project.
   */
  public Map<DXContainer, AccessLevel> listProjects() {
    Map<String, AccessLevel> rawMap =
        deserializeListProjectsMap(apiCallOnObject("listProjects", RetryStrategy.SAFE_TO_RETRY));
    ImmutableMap.Builder<DXContainer, AccessLevel> resultBuilder = ImmutableMap.builder();
    for (Map.Entry<String, AccessLevel> entry : rawMap.entrySet()) {
      resultBuilder.put(DXContainer.getInstance(entry.getKey()), entry.getValue());
    }
    return resultBuilder.build();
  }

  /**
   * Sets properties on the object.
   *
   * <p>The properties are modified in the project or container associated with this {@code
   * DXDataObject}, or the environment's workspace if no project or container was explicitly
   * specified.
   *
   * @param properties Map from key to value for each property to be set
   * @throws NullPointerException if this object has no associated project and no workspace is set
   */
  public void putAllProperties(Map<String, String> properties) {
    putAllProperties(properties, ImmutableList.<String>of());
  }

  /**
   * Sets and removes properties on the object.
   *
   * <p>The properties are modified in the project or container associated with this {@code
   * DXDataObject}, or the environment's workspace if no project or container was explicitly
   * specified.
   *
   * @param propertiesToSet Map from key to value for each property to be set
   * @param propertiesToRemove List of property keys to be removed
   * @throws NullPointerException if this object has no associated project and no workspace is set
   */
  public void putAllProperties(
      Map<String, String> propertiesToSet, List<String> propertiesToRemove) {
    Preconditions.checkNotNull(
        this.container, "Container must be supplied for this metadata operation");
    apiCallOnObject(
        "setProperties",
        MAPPER.valueToTree(
            new SetPropertiesRequest(this.container.getId(), propertiesToSet, propertiesToRemove)),
        RetryStrategy.SAFE_TO_RETRY);
  }

  /**
   * Sets a property on the object.
   *
   * <p>The properties are modified in the project or container associated with this {@code
   * DXDataObject}, or the environment's workspace if no project or container was explicitly
   * specified.
   *
   * @param key property key to set
   * @param value property value to set
   * @throws NullPointerException if this object has no associated project and no workspace is set
   */
  public void putProperty(String key, String value) {
    putAllProperties(ImmutableMap.of(key, value));
  }

  /**
   * Removes a property from the object.
   *
   * <p>The properties are modified in the project or container associated with this {@code
   * DXDataObject}, or the environment's workspace if no project or container was explicitly
   * specified.
   *
   * @param key property key to be removed
   * @throws NullPointerException if this object has no associated project and no workspace is set
   */
  public void removeProperty(String key) {
    putAllProperties(ImmutableMap.<String, String>of(), ImmutableList.of(key));
  }

  /**
   * Removes the specified tags from the object.
   *
   * <p>The tags are modified in the project or container associated with this {@code DXDataObject},
   * or the environment's workspace if no project or container was explicitly specified.
   *
   * @param tags List of tags to remove
   * @throws NullPointerException if this object has no associated project and no workspace is set
   */
  public void removeTags(List<String> tags) {
    Preconditions.checkNotNull(
        this.container, "Container must be supplied for this metadata operation");
    apiCallOnObject(
        "removeTags",
        MAPPER.valueToTree(new AddOrRemoveTagsRequest(this.container.getId(), tags)),
        RetryStrategy.SAFE_TO_RETRY);
  }

  /**
   * Removes the specified types from the object.
   *
   * @param types List of types to remove
   */
  public void removeTypes(List<String> types) {
    apiCallOnObject(
        "removeTypes",
        MAPPER.valueToTree(new AddOrRemoveTypesRequest(types)),
        RetryStrategy.SAFE_TO_RETRY);
  }

  /**
   * Changes the name of the object in its project. The basename of the object is changed to the
   * specified name and it remains in the same folder.
   *
   * <p>The object is renamed in the project or container associated with this {@code DXDataObject},
   * or the environment's workspace if no project or container was explicitly specified.
   *
   * @param newName The new name of the object
   * @throws NullPointerException if this object has no associated project and no workspace is set
   */
  public void rename(String newName) {
    Preconditions.checkNotNull(
        this.container, "Container must be supplied for this metadata operation");
    apiCallOnObject(
        "removeTags",
        MAPPER.valueToTree(new RenameRequest(this.container.getId(), newName)),
        RetryStrategy.SAFE_TO_RETRY);
  }

  /**
   * Sets the details of the object.
   *
   * @param details an object whose JSON serialized form will be set as the details
   */
  public void setDetails(Object details) {
    apiCallOnObject("setDetails", MAPPER.valueToTree(details), RetryStrategy.SAFE_TO_RETRY);
  }

  /**
   * Makes the object visible or hidden.
   *
   * @param visible
   */
  public void setVisibility(boolean visible) {
    apiCallOnObject(
        "setVisibility",
        MAPPER.valueToTree(new SetVisibilityRequest(!visible)),
        RetryStrategy.SAFE_TO_RETRY);
  }
}
Exemplo n.º 14
0
 /**
  * Sets the details of the data object to be created.
  *
  * @param details an object whose JSON serialized form will be set as the details
  * @return the same {@code Builder} object
  */
 public T setDetails(Object details) {
   Preconditions.checkState(this.details == null, "Cannot call setDetails more than once");
   this.details =
       MAPPER.valueToTree(Preconditions.checkNotNull(details, "details may not be null"));
   return getThisInstance();
 }
Exemplo n.º 15
0
 /**
  * Makes the object visible or hidden.
  *
  * @param visible
  */
 public void setVisibility(boolean visible) {
   apiCallOnObject(
       "setVisibility",
       MAPPER.valueToTree(new SetVisibilityRequest(!visible)),
       RetryStrategy.SAFE_TO_RETRY);
 }
Exemplo n.º 16
0
 /**
  * Sets the details of the object.
  *
  * @param details an object whose JSON serialized form will be set as the details
  */
 public void setDetails(Object details) {
   apiCallOnObject("setDetails", MAPPER.valueToTree(details), RetryStrategy.SAFE_TO_RETRY);
 }