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

com.avaje.ebean.common.BeanMap Maven / Gradle / Ivy

There is a newer version: 8.1.1
Show newest version
package com.avaje.ebean.common;

import com.avaje.ebean.bean.BeanCollection;
import com.avaje.ebean.bean.BeanCollectionLoader;
import com.avaje.ebean.bean.EntityBean;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * Map capable of lazy loading.
 */
public final class BeanMap extends AbstractBeanCollection implements Map {

  private static final long serialVersionUID = 1L;

  /**
   * The underlying map implementation.
   */
  private Map map;

  /**
   * Create with a given Map.
   */
  public BeanMap(Map map) {
    this.map = map;
  }

  /**
   * Create using a underlying LinkedHashMap.
   */
  public BeanMap() {
    this(new LinkedHashMap());
  }

  public BeanMap(BeanCollectionLoader ebeanServer, EntityBean ownerBean, String propertyName) {
    super(ebeanServer, ownerBean, propertyName);
  }

  @Override
  public void reset(EntityBean ownerBean, String propertyName) {
    this.ownerBean = ownerBean;
    this.propertyName = propertyName;
    this.map = null;
    this.touched = false;
  }

  public boolean isEmptyAndUntouched() {
    return !touched && (map == null || map.isEmpty());
  }

  @Override
  @SuppressWarnings("unchecked")
  public void loadFrom(BeanCollection other) {
    BeanMap otherMap = (BeanMap)other;
    internalPutNull();
    map.putAll(otherMap.getActualMap());
  }

  public void internalPutNull() {
    if (map == null) {
      map = new LinkedHashMap();
    }
  }

    @SuppressWarnings("unchecked")
  public void internalPut(Object key, Object bean) {
    if (map == null) {
      map = new LinkedHashMap();
    }
    if (key != null) {
      map.put((K) key, (E) bean);
    }
  }

  public void internalPutWithCheck(Object key, Object bean) {
    if (map == null || !map.containsKey(key)) {
      internalPut(key, bean);
    }
  }

  @Override
  public void internalAddWithCheck(Object bean) {
    throw new RuntimeException("Not allowed for map");
  }

  public void internalAdd(Object bean) {
    throw new RuntimeException("Not allowed for map");
  }

  /**
   * Return true if the underlying map has been populated. Returns false if it
   * has a deferred fetch pending.
   */
  public boolean isPopulated() {
    return map != null;
  }

  /**
   * Return true if this is a reference (lazy loading) bean collection. This is
   * the same as !isPopulated();
   */
  public boolean isReference() {
    return map == null;
  }

  public boolean checkEmptyLazyLoad() {
    if (map == null) {
      map = new LinkedHashMap();
      return true;
    } else {
      return false;
    }
  }

  private void initClear() {
    synchronized (this) {
      if (map == null) {
        if (modifyListening) {
          lazyLoadCollection(true);
        } else {
          map = new LinkedHashMap();
        }
      }
      touched(true);
    }
  }

  private void initAsUntouched() {
    init(false);
  }
  
  private void init() {
    init(true);
  }
  
  private void init(boolean setTouched) {
    synchronized (this) {
      if (map == null) {
        lazyLoadCollection(false);
      }
      touched(setTouched);
    }
  }

  /**
   * Set the actual underlying map. Used for performing lazy fetch.
   */
  @SuppressWarnings("unchecked")
  public void setActualMap(Map map) {
    this.map = (Map) map;
  }

  /**
   * Return the actual underlying map.
   */
  public Map getActualMap() {
    return map;
  }

  /**
   * Returns the collection of beans (map values).
   */
  public Collection getActualDetails() {
    return map.values();
  }

  /**
   * Returns the map entrySet.
   * 

* This is because the key values may need to be set against the details (so * they don't need to be set twice). *

*/ public Collection getActualEntries() { return map.entrySet(); } public String toString() { StringBuilder sb = new StringBuilder(50); sb.append("BeanMap "); if (isReadOnly()) { sb.append("readOnly "); } if (map == null) { sb.append("deferred "); } else { sb.append("size[").append(map.size()).append("]"); sb.append(" map").append(map); } return sb.toString(); } /** * Equal if obj is a Map and equal in a Map sense. */ public boolean equals(Object obj) { init(); return map.equals(obj); } public int hashCode() { init(); return map.hashCode(); } public void clear() { checkReadOnly(); initClear(); if (modifyRemoveListening) { // add all beans to the removal list for (E bean : map.values()) { modifyRemoval(bean); } } map.clear(); } public boolean containsKey(Object key) { init(); return map.containsKey(key); } public boolean containsValue(Object value) { init(); return map.containsValue(value); } @SuppressWarnings({ "unchecked", "rawtypes" }) public Set> entrySet() { init(); if (isReadOnly()) { return Collections.unmodifiableSet(map.entrySet()); } if (modifyListening) { Set> s = map.entrySet(); return new ModifySet(this, s); } return map.entrySet(); } public E get(Object key) { init(); return map.get(key); } public boolean isEmpty() { initAsUntouched(); return map.isEmpty(); } public Set keySet() { init(); if (isReadOnly()) { return Collections.unmodifiableSet(map.keySet()); } // we don't really care about modifications to the ketSet? return map.keySet(); } public E put(K key, E value) { checkReadOnly(); init(); if (modifyListening) { Object oldBean = map.put(key, value); if (value != oldBean) { // register the add of the new and the removal of the old modifyAddition(value); modifyRemoval(oldBean); } } return map.put(key, value); } @SuppressWarnings({ "unchecked", "rawtypes" }) public void putAll(Map puts) { checkReadOnly(); init(); if (modifyListening) { for (Entry entry : puts.entrySet()) { Object oldBean = map.put(entry.getKey(), entry.getValue()); if (entry.getValue() != oldBean) { modifyAddition(entry.getValue()); modifyRemoval(oldBean); } } } map.putAll(puts); } @Override public void addBean(E bean) { throw new IllegalStateException("Method not allowed on Map. Please use List instead."); } @Override public void removeBean(E bean) { throw new IllegalStateException("Method not allowed on Map. Please use List instead."); } public E remove(Object key) { checkReadOnly(); init(); if (modifyRemoveListening) { E o = map.remove(key); modifyRemoval(o); return o; } return map.remove(key); } public int size() { init(); return map.size(); } public Collection values() { init(); if (isReadOnly()) { return Collections.unmodifiableCollection(map.values()); } if (modifyListening) { Collection c = map.values(); return new ModifyCollection(this, c); } return map.values(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy