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

org.qas.api.internal.PropertyContainer Maven / Gradle / Ivy

The newest version!
package org.qas.api.internal;

import com.fasterxml.jackson.annotation.*;
import org.qas.api.JsonMapper;
import org.qas.api.JsonModel;
import org.qas.api.internal.util.json.JsonException;
import org.qas.api.internal.util.json.JsonObject;

import java.util.*;
import java.util.regex.Pattern;

/**
 * PropertyContainer
 *
 * @author: Dzung Nguyen
 * @version: $Id PropertyContainer 2014-01-13 17:50:30z dungvnguyen $
 * @since 1.0
 */
@JsonModel
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PropertyContainer implements Cloneable {
  //~ class properties ========================================================
  // the pattern that recognizing the reserved name.
  protected static final Pattern RESERVED_NAME = Pattern.compile("^__.*__$");
  protected static final String NL = System.getProperty("line.separator");
  protected final Map properties = new HashMap<>();

  //~ class members ===========================================================

  /**
   * Gets the property with the specified name. The value returned may not be
   * the same type as originally set via {@link #setProperty(String, Object)}
   *
   * @param name the property name.
   * @return the property corresponding to {@code name}
   */
  @JsonGetter
  public Object getProperty(String name) {
    return properties.get(name);
  }

  /**
   * Gets all of the properties belonging to this container.
   *
   * @return an unmodifiable {@code Map} of properties.
   */
  @JsonIgnore
  public Map getProperties() {
    Map props = new HashMap(properties.size());

    // copy the object.
    for (Map.Entry entry : properties.entrySet()) {
      props.put(entry.getKey(), entry.getValue());
    }

    return Collections.unmodifiableMap(props);
  }

  /**
   * Returns {@code true} if a property has been set. This function can be used to
   * test if property has been specifically set to {@code null}.
   *
   * @param name the given property name.
   * @return {@code true} iff the property named {@code name} exists.
   */
  @JsonIgnore
  public boolean hasProperty(String name) {
    return properties.containsKey(name);
  }

  /**
   * Removes the property which the specified name. If the is no property with this
   * name set, simply does nothing.
   *
   * @param name the given property name.
   */
  public void removeProperty(String name) {
    properties.remove(name);
  }

  /**
   * Sets the property named, {@code name}, to {@code value}
   *
   * @param name  the given property name.
   * @param value the given property value.
   */
  @JsonAnySetter
  public void setProperty(String name, Object value) {
    properties.put(name, value);
  }

  /**
   * A convenience method that populates properties from those in the given container.
   *
   * @param src the container from which we will populate ourself.
   */
  public void setPropertiesFrom(PropertyContainer src) {
    for (Map.Entry entry : src.getPropertyMap().entrySet()) {
      String name = entry.getKey();
      Object entryValue = entry.getValue();

      if (entryValue instanceof Collection) {
        Collection srcCol = (Collection) entryValue;
        Collection destColl = new ArrayList(srcCol.size());

        entryValue = destColl;
        for (Object element : srcCol) {
          destColl.add(cloneIfMutable(element));
        }
      } else {
        entryValue = cloneIfMutable(entryValue);
      }

      properties.put(name, entryValue);
    }
  }

  /**
   * @return the current property map.
   */
  @JsonIgnore
  protected Object clone() {
    throw new UnsupportedOperationException();
  }

  /**
   * @return {@code true} if this container contains another properties except reversed name.
   */
  @Deprecated
  @JsonIgnore
  protected boolean hasProperties() {
    for (Map.Entry entry : getPropertyMap().entrySet()) {
      if (!RESERVED_NAME.matcher(entry.getKey()).find()) return true;
    }

    return false;
  }

  /**
   * @param key property key
   * @return if the given the key is visible to display.
   */
  @JsonIgnore
  protected boolean isVisible(String key) {
    return !RESERVED_NAME.matcher(key).find();
  }

  /**
   * Build current container information and put to the given {@code builder}
   *
   * @param builder the given {@link java.lang.StringBuilder} to store value.
   * @param indent  the given indent.
   * @param depth   the given depth value.
   */
  @Deprecated
  public void appendPropertiesTo(StringBuilder builder, String indent, int depth) {
  }

  /**
   * @return the current property map.
   */
  @JsonAnyGetter
  public Map getPropertyMap() {
    return properties;
  }

  /**
   * @return the name of the root element.
   * @deprecated will be remove in future release
   */
  @JsonIgnore
  @Deprecated
  public String elementName() {
    return "container";
  }

  /**
   * @return the name of the root element.
   * @deprecated will be remove in future release
   */
  @JsonIgnore
  @Deprecated
  public String jsonElementName() {
    return elementName();
  }

  /**
   * Build JsonObject from the property container.
   *
   * @param jsonObject the given {@link org.qas.api.internal.util.json.JsonObject} to hold value.
   * @throws JsonException if an error occurs during building json object.
   */
  @Deprecated
  public void appendPropertiesTo(JsonObject jsonObject) throws JsonException {
  }

  /**
   * @return the current object as {@link org.qas.api.internal.util.json.JsonObject} instance.
   * @throws JsonException if an error occurs during building json object.
   */
  @JsonIgnore
  public JsonObject toJson() throws JsonException {
    JsonObject jsonObject = new JsonObject(JsonMapper.toMap(this));
    return jsonObject;
  }

  @JsonIgnore
  @Override
  public String toString() {
    return JsonMapper.toJson(this);
  }

  /**
   * @param source source
   * @return a clone of the provided object if it is mutable, otherwise just
   * return the provided object.
   */
  private static Object cloneIfMutable(Object source) {
    if (source instanceof Date) {
      return ((Date) source).clone();
    } else if (source instanceof PropertyContainer) {
      return ((PropertyContainer) source).clone();
    }

    return source;
  }


  /**
   * @param key property name
   * @return 0 as default value
   */
  public Integer asInteger(String key) {
    return asInteger(key, 0);
  }

  /**
   * @param key          property name
   * @param defaultValue default value
   * @return Integer value
   */
  public Integer asInteger(String key, Integer defaultValue) {
    try {
      return (Integer) getProperty(key);
    } catch (Exception e) {
      return defaultValue;
    }
  }

  /**
   * @param key property name
   * @return 0L as default value
   */
  public Long asLong(String key) {
    return asLong(key, 0L);
  }

  /**
   * @param key          property name
   * @param defaultValue default value
   * @return Long value
   */
  public Long asLong(String key, Long defaultValue) {
    try {
      return (Long) getProperty(key);
    } catch (Exception e) {
      return defaultValue;
    }
  }

  public String asString(String key) {
    return asString(key, "");
  }

  /**
   * @param key          property name
   * @param defaultValue default value
   * @return String value
   */
  public String asString(String key, String defaultValue) {
    Object value = getProperty(key);
    if (null == value) {
      return defaultValue;
    }
    return value instanceof String ? (String) value : value.toString();
  }

  /**
   * @param key property name
   * @return null as default value
   */
  public Date asDate(String key) {
    return asDate(key, null);
  }

  /**
   * @param key          property name
   * @param defaultValue default value
   * @return Date value
   */
  public Date asDate(String key, Date defaultValue) {
    try {
      return (Date) getProperty(key);
    } catch (Exception e) {
      return defaultValue;
    }
  }
}