All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.spotify.asyncdatastoreclient.Entity Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
/*
 * Copyright (c) 2011-2015 Spotify AB
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.spotify.asyncdatastoreclient;

import com.google.common.collect.Maps;
import com.google.protobuf.ByteString;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Represents an entity that is stored in Datastore.
 *
 * All properties are immutable; use {@code Entity.builder()} to construct new
 * {@code Entity} instances.
 */
public final class Entity {

  private final com.google.datastore.v1.Entity entity;
  private Map properties;

  private Entity(final com.google.datastore.v1.Entity entity) {
    this.entity = entity;
    this.properties = null;
  }

  public static final class Builder {

    private com.google.datastore.v1.Entity.Builder entity;
    private Map properties;

    private Builder() {
      this.entity = com.google.datastore.v1.Entity.newBuilder();
      this.properties = Maps.newHashMap();
    }

    private Builder(final Key key) {
      this.entity = com.google.datastore.v1.Entity.newBuilder().setKey(key.getPb());
      this.properties = Maps.newHashMap();
    }

    private Builder(final Entity entity) {
      this(entity.getPb());
    }

    private Builder(final com.google.datastore.v1.Entity entity) {
      this.entity = com.google.datastore.v1.Entity.newBuilder(entity);
      this.properties = entity.getProperties().entrySet().stream()
        .collect(Collectors.toMap(Map.Entry::getKey, e -> Value.builder(e.getValue()).build()));
    }

    /**
     * Creates a new {@code Entity}.
     *
     * @return an immutable entity.
     */
    public Entity build() {
      entity.getMutableProperties().clear();
      entity.putAllProperties(
          properties
              .entrySet()
              .stream()
              .collect(Collectors.toMap(
                  Map.Entry::getKey, e -> e.getValue().getPb().toBuilder().build())));

      return new Entity(entity.build());
    }

    /**
     * Set the key for this entity.
     *
     * @param key the key to set for this entity.
     * @return this entity builder.
     */
    public Builder key(final Key key) {
      entity.setKey(key.getPb());
      return this;
    }

    /**
     * Set property and its value for this entity.
     *
     * @param name the property name to set.
     * @param value the property value.
     * @return this entity builder.
     */
    public Builder property(final String name, final Value value) {
      properties.put(name, value);
      return this;
    }

    /**
     * Set property and its value for this entity.
     *
     * @param name the property name to set.
     * @param value the property value.
     * @return this entity builder.
     */
    public Builder property(final String name, final Object value) {
      properties.put(name, Value.builder(value).build());
      return this;
    }

    /**
     * Set property and its value for this entity.
     *
     * @param name the property name to set.
     * @param value the property value.
     * @param indexed indicates whether the value should be indexed or not.
     * @return this entity builder.
     */
    public Builder property(final String name, final Object value, final boolean indexed) {
      properties.put(name, Value.builder(value).indexed(indexed).build());
      return this;
    }

    /**
     * Set property and a list of value for this entity.
     *
     * @param name the property name to set.
     * @param values a list of value.
     * @return this entity builder.
     */
    public Builder property(final String name, final List values) {
      properties.put(name, Value.builder(values).build());
      return this;
    }

    /**
     * Remove a property from this entity.
     *
     * @param name the property name to remove.
     * @return this entity builder.
     */
    public Builder remove(final String name) {
      properties.remove(name);
      return this;
    }
  }

  /**
   * Creates a new empty {@code Entity} builder.
   *
   * @return an entity builder.
   */
  public static Entity.Builder builder() {
    return new Entity.Builder();
  }

  /**
   * Creates a new {@code Entity} builder for a given kind.
   *
   * This is a shortcut for {@code Entity.builder().key(Key.builder(kind).build())}
   *
   * @param kind the kind of entity.
   * @return an entity builder.
   */
  public static Entity.Builder builder(final String kind) {
    return new Entity.Builder(Key.builder(kind).build());
  }

  /**
   * Creates a new {@code Entity} builder for a given kind and key id.
   *
   * This is a shortcut for {@code Entity.builder().key(Key.builder(kind, id).build())}
   *
   * @param kind the kind of entity.
   * @param id the key id.
   * @return an entity builder.
   */
  public static Entity.Builder builder(final String kind, final long id) {
    return new Entity.Builder(Key.builder(kind, id).build());
  }

  /**
   * Creates a new {@code Entity} builder for a given kind and key name.
   *
   * This is a shortcut for {@code Entity.builder().key(Key.builder(kind, name).build())}
   *
   * @param kind the kind of entity.
   * @param name the key name.
   * @return an entity builder.
   */
  public static Entity.Builder builder(final String kind, final String name) {
    return new Entity.Builder(Key.builder(kind, name).build());
  }

  /**
   * Creates a new {@code Entity} builder for a given key.
   *
   * This is a shortcut for {@code Entity.builder().key(key).build())}
   *
   * @param key the key for this entity.
   * @return an entity builder.
   */
  public static Entity.Builder builder(final Key key) {
    return new Entity.Builder(key);
  }

  /**
   * Creates a new {@code Entity} builder based on an existing entity.
   *
   * @param entity the entity to use as a base.
   * @return an entity builder.
   */
  public static Entity.Builder builder(final Entity entity) {
    return new Entity.Builder(entity);
  }

  static Entity.Builder builder(final com.google.datastore.v1.Entity entity) {
    return new Entity.Builder(entity);
  }

  /**
   * Return the key for this entity.
   *
   * @return a {@code Key}.
   */
  public Key getKey() {
    return Key.builder(entity.getKey()).build();
  }

  /**
   * Return the value for a given property as a string, or null
   * if the property doesn't exist.
   *
   * @param name the name of the property to get.
   * @return a property value.
   */
  public String getString(final String name) {
    final Value value = getProperties().get(name);
    return value == null ? null : value.getString();
  }

  /**
   * Return the value for a given property as an integer, or null
   * if the property doesn't exist.
   *
   * @param name the name of the property to get.
   * @return a property value.
   */
  public Long getInteger(final String name) {
    final Value value = getProperties().get(name);
    return value == null ? null : value.getInteger();
  }

  /**
   * Return the value for a given property as a boolean, or null
   * if the property doesn't exist.
   *
   * @param name the name of the property to get.
   * @return a property value.
   */
  public Boolean getBoolean(final String name) {
    final Value value = getProperties().get(name);
    return value == null ? null : value.getBoolean();
  }

  /**
   * Return the value for a given property as a double, or null
   * if the property doesn't exist.
   *
   * @param name the name of the property to get.
   * @return a property value.
   */
  public Double getDouble(final String name) {
    final Value value = getProperties().get(name);
    return value == null ? null : value.getDouble();
  }

  /**
   * Return the value for a given property as a date, or null
   * if the property doesn't exist.
   *
   * @param name the name of the property to get.
   * @return a property value.
   */
  public Date getDate(final String name) {
    final Value value = getProperties().get(name);
    return value == null ? null : value.getDate();
  }

  /**
   * Return the value for a given property as a blob, or null
   * if the property doesn't exist.
   *
   * @param name the name of the property to get.
   * @return a property value.
   */
  public ByteString getBlob(final String name) {
    final Value value = getProperties().get(name);
    return value == null ? null : value.getBlob();
  }

  /**
   * Return the value for a given property as an entity, or null
   * if the property doesn't exist.
   *
   * @param name the name of the property to get.
   * @return a property value.
   */
  public Entity getEntity(final String name) {
    final Value value = getProperties().get(name);
    return value == null ? null : value.getEntity();
  }

  /**
   * Return the value for a given property as a key, or null
   * if the property doesn't exist.
   *
   * @param name the name of the property to get.
   * @return a property value.
   */
  public Key getKey(final String name) {
    final Value value = getProperties().get(name);
    return value == null ? null : value.getKey();
  }

  /**
   * Return the value for a given property as a list of {@code Key}, or null
   * if the property doesn't exist.
   *
   * @param name the name of the property to get.
   * @return a list of property values.
   */
  public List getList(final String name) {
    final Value value = getProperties().get(name);
    return value == null ? null : value.getList();
  }

  /**
   * Return the value for a given property as a list of values that are cast
   * to a given type, or null if the property doesn't exist.
   *
   * @param name the name of the property to get.
   * @param clazz the type of class to cast values to.
   * @return a list of property values.
   */
  public  List getList(final String name, final Class clazz) {
    final Value value = getProperties().get(name);
    return value == null ? null : value.getList(clazz);
  }

  /**
   * Return a map of properties to their values for this entity.
   *
   * @return a map of property values.
   */
  public Map getProperties() {
    if (properties == null) {
      properties = entity
          .getProperties()
          .entrySet()
          .stream()
          .collect(Collectors.toMap(Map.Entry::getKey, e -> Value.builder(e.getValue()).build()));
    }
    return properties;
  }

  /**
   * Get the value for given property, or empty if none exists.
   *
   * @param name name of the property to get.
   * @return an optional containing a property value, or empty.
   */
  public Optional get(final String name) {
      return Optional.ofNullable(getProperties().get(name));
  }

  /**
   * Return whether a given property name exists in this entity.
   *
   * @param name the name of the property.
   * @return true if the property exists.
   */
  public boolean contains(final String name) {
    return getProperties().containsKey(name);
  }

  @Override
  public String toString() {
    return "{" + getProperties().entrySet().stream()
        .map(property -> property.getKey() + ":" + property.getValue())
        .collect(Collectors.joining(", ")) + "}";
  }

  @Override
  public int hashCode() {
    return entity.hashCode();
  }

  @Override
  public boolean equals(final Object obj) {
    return obj.getClass() == this.getClass() || (obj instanceof Entity && Objects.equals(entity, ((Entity) obj).entity));
  }

  com.google.datastore.v1.Entity getPb() {
    return entity;
  }

  com.google.datastore.v1.Entity getPb(final String namespace) {
    final Map propertiesLocal = entity.getProperties()
        .entrySet()
        .stream()
        .collect(Collectors.toMap(
            Map.Entry::getKey, e -> Value.builder(e.getValue()).build().getPb(namespace)));

    return com.google.datastore.v1.Entity
        .newBuilder()
        .putAllProperties(propertiesLocal)
        .setKey(getKey().getPb(namespace))
        .build();
  }
}