Пример #1
0
/** @author Tao Chen */
public abstract class AbstractLazyXMap<K, V> extends AbstractWrapperXMap<K, V>
    implements LazinessManageable {

  static final LazyResource<CommonResource> LAZY_COMMON_RESOURCE =
      LazyResource.of(CommonResource.class);

  protected AbstractLazyXMap(XMap<K, V> base) {
    super(base);
  }

  protected AbstractLazyXMap(AbstractLazyXMap<K, V> parent, ViewInfo viewInfo) {
    super(parent, viewInfo);
  }

  /**
   * This method should not be invoked by the customer immediately.
   *
   * <p>It is used to create the instance during the when {@link java.io.ObjectInputStream} reads
   * this object from a stream. Although the derived classes of this class may implement {@link
   * java.io.Serializable}, but this abstract super class does not implement {@link
   * java.io.Serializable} because it have some derived class that implements {@link View} which can
   * not be implement {@link java.io.Serializable}
   *
   * <p>If the derived class is still a class does not implement {@link java.io.Serializable},
   * please support a no arguments constructor and mark it with {@link Deprecated} too, like this
   * method.
   */
  @Deprecated
  protected AbstractLazyXMap() {}

  @Override
  public final boolean isLoaded() {
    return this.<RootData<K, V>>getRootData().isLoaded();
  }

  @Override
  public final boolean isLoadable() {
    return this.<RootData<K, V>>getRootData().isLoadable();
  }

  @Override
  public final void load() {
    this.<RootData<K, V>>getRootData().load();
  }

  @Override
  public int hashCode() {
    this.load();
    return this.getBase().hashCode();
  }

  @Override
  public boolean equals(Object obj) {
    this.load();
    return this.getBase().equals(obj);
  }

  @Override
  public String toString() {
    if (!this.isLoaded()) {
      return "{ lazyMap : NotLoaded }";
    }
    return super.toString();
  }

  @Override
  public int size() {
    this.requiredEnabled();
    if (this.getParent() == null) {
      int size = this.<RootData<K, V>>getRootData().visionallyReadSize();
      if (size != -1) {
        return size;
      }
    }
    this.load();
    return this.getBase().size();
  }

  @Override
  public boolean isEmpty() {
    this.requiredEnabled();
    if (0 == this.<RootData<K, V>>getRootData().visionallyReadSize()) {
      return true;
    }
    this.load();
    return this.getBase().isEmpty();
  }

  @SuppressWarnings("unchecked")
  @Override
  public V get(Object key) {
    this.requiredEnabled();
    RootData<K, V> rootData = this.<RootData<K, V>>getRootData();
    Ref<V> ref = rootData.visionallyRead((K) key, null);
    if (ref != null) {
      return ref.get();
    }
    rootData.load();
    return this.getBase().get(key);
  }

  @SuppressWarnings("unchecked")
  @Override
  public boolean containsKey(Object key, ElementMatcher<? super K> keyMatcher) {
    this.requiredEnabled();
    RootData<K, V> rootData = this.<RootData<K, V>>getRootData();
    if (keyMatcher == null) {
      Ref<V> ref = rootData.visionallyRead((K) key, null);
      if (ref != null) {
        return ref.get() != null;
      }
    }
    rootData.load();
    return this.getBase().containsKey(key, keyMatcher);
  }

  @Override
  public boolean containsValue(Object value, ElementMatcher<? super V> valueMatcher) {
    this.requiredEnabled();
    if (valueMatcher == null) {
      if (this.<RootData<K, V>>getRootData().getQueuedOrphans().containsValue(value)) {
        return false;
      }
    }
    this.load();
    return this.getBase().containsValue(value, valueMatcher);
  }

  @Override
  public Ref<K> keyOf(V value, ElementMatcher<? super V> valueMatcher) {
    this.requiredEnabled();
    this.load();
    return this.getBase().keyOf(value, valueMatcher);
  }

  @Override
  public XEntry<K, V> real(K key) {
    try {
      return new RealEntryImpl<>(this, key);
    } catch (NoEntryException ex) {
      return null;
    }
  }

  @Override
  public V put(K key, V value) {
    this.enable();
    this.load();
    return this.getBase().put(key, value);
  }

  @Override
  public void putAll(Map<? extends K, ? extends V> m) {
    this.enable();
    this.load();
    this.getBase().putAll(m);
  }

  @Override
  public void clear() {
    this.enable();
    this.load();
    this.getBase().clear();
  }

  @Override
  public V remove(Object key) {
    this.enable();
    Ref<V> retval = this.visionallyRemove(key);
    if (retval != null) {
      return retval.get();
    }
    this.load();
    return this.getBase().remove(key);
  }

  @Override
  public XEntrySetView<K, V> entrySet() {
    return this.getEntrySet();
  }

  @Override
  public XKeySetView<K> keySet() {
    return this.getKeySet();
  }

  @Override
  public XValuesView<V> values() {
    return this.getValues();
  }

  @Override
  protected XEntrySetView<K, V> createEntrySet() {
    return new EntrySetImpl<K, V>(this);
  }

  @Override
  protected XKeySetView<K> createKeySet() {
    return new KeySetImpl<K, V>(this);
  }

  @Override
  protected XValuesView<V> createValues() {
    return new ValuesImpl<K, V>(this);
  }

  protected final Ref<V> visionallyRemove(Object key) {
    return this.visionallyRemoveImpl(key);
  }

  @SuppressWarnings("unchecked")
  Ref<V> visionallyRemoveImpl(Object key) {
    RootData<K, V> rootData = this.getRootData();
    if (rootData.isLoaded()) {
      return null;
    }
    if (!rootData.isVisionallyReadable(QueuedOperationType.DETACH)) {
      return null;
    }
    if (!rootData.getLazyBehaviorProcessor().preVisionallyRead(1)) {
      return null;
    }
    if (rootData.isLoading()) {
      throw new IllegalStateException(
          LAZY_COMMON_RESOURCE.get().visionOperationWhenDataIsBeingLoaded());
    }
    Ref<V> ref = rootData.visionallyRead((K) key, QueuedOperationType.DETACH);
    if (ref != null) {
      rootData.visinallyRemove((K) key, ref.get());
    }
    return ref;
  }

  @Override
  protected abstract RootData<K, V> createRootData();

  protected abstract static class AbstractKeySetImpl<K, V>
      extends AbstractWrapperXMap.AbstractKeySetImpl<K, V> implements LazinessManageable {

    protected AbstractKeySetImpl(AbstractLazyXMap<K, V> parentMap, ViewInfo viewInfo) {
      super(parentMap, viewInfo);
    }

    protected AbstractKeySetImpl(AbstractKeySetImpl<K, V> parent, ViewInfo viewInfo) {
      super(parent, viewInfo);
    }

    @Override
    public final boolean isLoaded() {
      return this.<RootData<K, V>>getRootData().isLoaded();
    }

    @Override
    public final boolean isLoadable() {
      return this.<RootData<K, V>>getRootData().isLoadable();
    }

    @Override
    public final void load() {
      this.<RootData<K, V>>getRootData().load();
    }

    @Override
    public int hashCode() {
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().hashCode();
    }

    @Override
    public boolean equals(Object obj) {
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().equals(obj);
    }

    @Override
    public String toString() {
      if (!this.<RootData<K, V>>getRootData().isLoaded()) {
        return "[lazyKeySet : NotLoaded]";
      }
      return this.getBase().toString();
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean contains(Object o, ElementMatcher<? super K> matcher) {
      this.requiredEnabled();
      RootData<K, V> rootData = this.<RootData<K, V>>getRootData();
      if (matcher == null) {
        Ref<V> ref = rootData.visionallyRead((K) o, null);
        if (ref != null) {
          return ref.get() != null;
        }
      }
      rootData.load();
      return this.getBase().contains(o, matcher);
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean containsAll(Collection<?> c, ElementMatcher<? super K> matcher) {
      this.requiredEnabled();
      RootData<K, V> rootData = this.<RootData<K, V>>getRootData();
      if (matcher == null) {
        for (Object o : c) {
          Ref<V> ref = rootData.visionallyRead((K) o, null);
          if (ref == null) {
            rootData.load();
            return this.getBase().containsAll(c, matcher);
          }
          if (ref.get() == null) {
            return false;
          }
        }
        return true;
      }
      rootData.load();
      return this.getBase().containsAll(c, matcher);
    }

    @Override
    public Object[] toArray() {
      this.requiredEnabled();
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
      this.requiredEnabled();
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().toArray(a);
    }

    @Override
    public boolean isEmpty() {
      this.requiredEnabled();
      RootData<K, V> rootData = this.<RootData<K, V>>getRootData();
      if (0 == rootData.visionallyReadSize()) {
        return true;
      }
      rootData.load();
      return this.getBase().isEmpty();
    }

    @Override
    public int size() {
      this.requiredEnabled();
      RootData<K, V> rootData = this.<RootData<K, V>>getRootData();
      if (this.getParent() == null
          && this.<AbstractLazyXMap<K, V>>getParentMap().getParent() == null) {
        int size = rootData.visionallyReadSize();
        if (size != -1) {
          return size;
        }
      }
      rootData.load();
      return this.getBase().size();
    }

    @Override
    public void clear() {
      this.enable();
      this.<RootData<K, V>>getRootData().load();
      this.getBase().clear();
    }

    @Override
    public boolean remove(Object o) {
      this.enable();
      Boolean retval = this.visionallyRemove(o);
      if (retval != null) {
        return retval.booleanValue();
      }
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().remove(o);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
      this.enable();
      Boolean retval = this.visionallyRemoveAll(c);
      if (retval != null) {
        return retval.booleanValue();
      }
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().removeAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
      this.enable();
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().retainAll(c);
    }

    @Override
    public XIterator<K> iterator() {
      return new IteratorImpl<K, V>(this);
    }

    protected final Boolean visionallyRemove(Object o) {
      return this.visionallyRemoveImpl(o);
    }

    protected final Boolean visionallyRemoveAll(Collection<?> c) {
      return this.visionallyRemoveAllImpl(c);
    }

    @SuppressWarnings("unchecked")
    Boolean visionallyRemoveImpl(Object o) {
      RootData<K, V> rootData = this.<RootData<K, V>>getRootData();
      if (rootData.isLoaded()) {
        return null;
      }
      if (!rootData.isVisionallyReadable(QueuedOperationType.DETACH)) {
        return null;
      }
      if (rootData.isLoading()) {
        throw new IllegalStateException(
            LAZY_COMMON_RESOURCE.get().visionOperationWhenDataIsBeingLoaded());
      }
      Ref<V> ref = rootData.visionallyRead((K) o, QueuedOperationType.DETACH);
      if (ref != null) {
        if (ref.get() == null) {
          return false;
        }
        rootData.visinallyRemove((K) o, ref.get());
        return true;
      }
      return null;
    }

    @SuppressWarnings("unchecked")
    Boolean visionallyRemoveAllImpl(Collection<?> c) {
      RootData<K, V> rootData = this.<RootData<K, V>>getRootData();
      if (rootData.isLoaded()) {
        return null;
      }
      if (!rootData.isVisionallyReadable(QueuedOperationType.DETACH)) {
        return null;
      }
      if (rootData.isLoading()) {
        throw new IllegalStateException(
            LAZY_COMMON_RESOURCE.get().visionOperationWhenDataIsBeingLoaded());
      }
      int len = 0;
      Object[] arr = new Object[c.size() << 1];
      for (Object o : c) {
        Ref<V> ref = rootData.visionallyRead((K) o, QueuedOperationType.DETACH);
        if (ref == null) {
          return null;
        }
        if (ref.get() == null) {
          continue;
        }
        arr[len++] = o;
        arr[len++] = ref.get();
      }
      for (int i = 0; i < len; i += 2) {
        rootData.visinallyRemove((K) arr[i], (V) arr[i + 1]);
      }
      return len != 0;
    }

    protected abstract static class AbstractIteratorImpl<K, V>
        extends AbstractWrapperXMap.AbstractKeySetImpl.AbstractIteratorImpl<K, V> {

      protected AbstractIteratorImpl(AbstractKeySetImpl<K, V> parent, ViewInfo viewInfo) {
        super(loadParent(parent), viewInfo);
      }

      private static <K, V> AbstractKeySetImpl<K, V> loadParent(AbstractKeySetImpl<K, V> parent) {
        parent.<RootData<K, V>>getRootData().load();
        return parent;
      }
    }

    protected static class IteratorImpl<K, V> extends AbstractIteratorImpl<K, V> {

      public IteratorImpl(AbstractKeySetImpl<K, V> parent) {
        super(parent, CollectionViewInfos.iterator());
      }

      @Override
      protected XIterator<K> createBaseView(XKeySetView<K> baseKeySet, ViewInfo viewInfo) {
        if (viewInfo instanceof CollectionViewInfos.Iterator) {
          return baseKeySet.iterator();
        }
        throw new IllegalArgumentException(LAZY_COMMON_RESOURCE.get().illegalViewInfo());
      }
    }
  }

  protected static class KeySetImpl<K, V> extends AbstractKeySetImpl<K, V> {

    protected KeySetImpl(AbstractLazyXMap<K, V> parentMap) {
      super(parentMap, MapViewInfos.keySet());
    }

    @Override
    protected XKeySetView<K> createBaseView(XMap<K, V> baseMap, ViewInfo viewInfo) {
      if (viewInfo instanceof MapViewInfos.KeySet) {
        return baseMap.keySet();
      }
      throw new IllegalArgumentException(LAZY_COMMON_RESOURCE.get().illegalViewInfo());
    }
  }

  protected static class EntrySetImpl<K, V> extends AbstractWrapperXMap.EntrySetImpl<K, V>
      implements LazinessManageable {

    public EntrySetImpl(AbstractLazyXMap<K, V> parentMap) {
      super(parentMap);
    }

    @Override
    public final boolean isLoaded() {
      return this.<RootData<K, V>>getRootData().isLoaded();
    }

    @Override
    public final boolean isLoadable() {
      return this.<RootData<K, V>>getRootData().isLoadable();
    }

    @Override
    public final void load() {
      this.<RootData<K, V>>getRootData().load();
    }

    @Override
    public int hashCode() {
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().hashCode();
    }

    @Override
    public boolean equals(Object obj) {
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().equals(obj);
    }

    @Override
    public String toString() {
      if (!this.<RootData<K, V>>getRootData().isLoaded()) {
        return "{ lazyKeySet : NotLoaded }";
      }
      return this.getBase().toString();
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean contains(Object o, ElementMatcher<? super Entry<K, V>> matcher) {
      this.requiredEnabled();
      if (!(o instanceof Entry<?, ?>)) {
        return false;
      }
      Entry<K, V> e = (Entry<K, V>) o;
      RootData<K, V> rootData = this.getRootData();
      if (matcher == null) {
        Ref<V> ref = rootData.visionallyRead(e.getKey(), null);
        if (ref != null) {
          if (ref.get() == null) {
            return false;
          }
          if (!rootData.valueUnifiedComparator().equals(ref.get(), e.getValue())) {
            return false;
          }
          return true;
        }
      }
      rootData.load();
      return this.getBase().contains(o, matcher);
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean containsAll(Collection<?> c, ElementMatcher<? super Entry<K, V>> matcher) {
      this.requiredEnabled();
      RootData<K, V> rootData = this.getRootData();
      if (matcher == null) {
        UnifiedComparator<? super V> valueUnifiedComparator = rootData.valueUnifiedComparator();
        for (Object o : c) {
          if (!(o instanceof Entry<?, ?>)) {
            return false;
          }
          Entry<K, V> e = (Entry<K, V>) o;
          Ref<V> ref = rootData.visionallyRead(e.getKey(), null);
          if (ref == null) {
            rootData.load();
            return this.getBase().containsAll(c, matcher);
          }
          if (ref.get() == null) {
            return false;
          }
          if (!valueUnifiedComparator.equals(ref.get(), e.getValue())) {
            return false;
          }
        }
        return true;
      }
      rootData.load();
      return this.getBase().containsAll(c, matcher);
    }

    @Override
    public Object[] toArray() {
      this.requiredEnabled();
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
      this.requiredEnabled();
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().toArray(a);
    }

    @Override
    public boolean isEmpty() {
      this.requiredEnabled();
      RootData<K, V> rootData = this.<RootData<K, V>>getRootData();
      if (0 == rootData.visionallyReadSize()) {
        return true;
      }
      rootData.load();
      return this.getBase().isEmpty();
    }

    @Override
    public int size() {
      this.requiredEnabled();
      RootData<K, V> rootData = this.<RootData<K, V>>getRootData();
      if (this.<AbstractLazyXMap<K, V>>getParentMap().getParent() != null) {
        int size = rootData.visionallyReadSize();
        if (size != -1) {
          return size;
        }
      }
      rootData.load();
      return this.getBase().size();
    }

    @Override
    public void clear() {
      this.enable();
      this.<RootData<K, V>>getRootData().load();
      this.getBase().clear();
    }

    @Override
    public boolean remove(Object o) {
      this.enable();
      Boolean retval = this.visionallyRemove(o);
      if (retval != null) {
        return retval.booleanValue();
      }
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().remove(o);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
      this.enable();
      Boolean retval = this.visionallyRemoveAll(c);
      if (retval != null) {
        return retval.booleanValue();
      }
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().removeAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
      this.enable();
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().retainAll(c);
    }

    @Override
    public XEntrySetIterator<K, V> iterator() {
      return new IteratorImpl<K, V>(this);
    }

    protected final Boolean visionallyRemove(Object o) {
      return this.visionallRemoveImpl(o);
    }

    protected final Boolean visionallyRemoveAll(Collection<?> c) {
      return this.visionallyRemoveAllImpl(c);
    }

    @SuppressWarnings("unchecked")
    Boolean visionallRemoveImpl(Object o) {
      if (!(o instanceof Entry<?, ?>)) {
        return false;
      }
      RootData<K, V> rootData = this.<RootData<K, V>>getRootData();
      if (rootData.isLoaded()) {
        return null;
      }
      if (!rootData.isVisionallyReadable(QueuedOperationType.DETACH)) {
        return null;
      }
      if (rootData.isLoading()) {
        throw new IllegalStateException(
            LAZY_COMMON_RESOURCE.get().visionOperationWhenDataIsBeingLoaded());
      }
      Entry<K, V> e = (Entry<K, V>) o;
      Ref<V> ref = rootData.visionallyRead(e.getKey(), null);
      if (ref != null) {
        if (ref.get() == null) {
          return false;
        }
        if (!rootData.valueUnifiedComparator().equals(ref.get(), e.getValue())) {
          return false;
        }
        rootData.visinallyRemove(e.getKey(), ref.get());
        return true;
      }
      return null;
    }

    @SuppressWarnings("unchecked")
    Boolean visionallyRemoveAllImpl(Collection<?> c) {
      RootData<K, V> rootData = this.<RootData<K, V>>getRootData();
      if (rootData.isLoaded()) {
        return null;
      }
      if (!rootData.isVisionallyReadable(QueuedOperationType.DETACH)) {
        return null;
      }
      if (rootData.isLoading()) {
        throw new IllegalStateException(
            LAZY_COMMON_RESOURCE.get().visionOperationWhenDataIsBeingLoaded());
      }
      int len = 0;
      Object[] arr = new Object[c.size() << 1];
      UnifiedComparator<? super V> valueUnifiedComparator = rootData.valueUnifiedComparator();
      for (Object o : c) {
        if (o instanceof Entry<?, ?>) {
          Entry<K, V> e = (Entry<K, V>) o;
          Ref<V> ref = rootData.visionallyRead(e.getKey(), QueuedOperationType.DETACH);
          if (ref == null) {
            return null;
          }
          if (ref.get() == null) {
            continue;
          }
          if (!valueUnifiedComparator.equals(ref.get(), e.getValue())) {
            continue;
          }
          arr[len++] = e.getKey();
          arr[len++] = ref.get();
        }
      }
      for (int i = 0; i < len; i += 2) {
        rootData.visinallyRemove((K) arr[i], (V) arr[i + 1]);
      }
      return len != 0;
    }

    protected static class IteratorImpl<K, V>
        extends AbstractWrapperXMap.EntrySetImpl.IteratorImpl<K, V> {

      public IteratorImpl(EntrySetImpl<K, V> parent) {
        super(loadParent(parent));
      }

      private static <K, V> EntrySetImpl<K, V> loadParent(EntrySetImpl<K, V> parent) {
        parent.<RootData<K, V>>getRootData().load();
        return parent;
      }

      @Override
      public XEntry<K, V> next() {
        return new EntryImpl<>(this);
      }
    }
  }

  protected static class ValuesImpl<K, V> extends AbstractWrapperXMap.ValuesImpl<K, V>
      implements LazinessManageable {

    public ValuesImpl(AbstractLazyXMap<K, V> parentMap) {
      super(parentMap);
    }

    @Override
    public final boolean isLoaded() {
      return this.<RootData<K, V>>getRootData().isLoaded();
    }

    @Override
    public final boolean isLoadable() {
      return this.<RootData<K, V>>getRootData().isLoadable();
    }

    @Override
    public final void load() {
      this.<RootData<K, V>>getRootData().load();
    }

    @Override
    public String toString() {
      if (!this.<RootData<K, V>>getRootData().isLoaded()) {
        return "{ lazyValues : NotLoaded }";
      }
      return this.getBase().toString();
    }

    @Override
    public boolean contains(Object o, ElementMatcher<? super V> matcher) {
      this.requiredEnabled();
      if (matcher == null) {
        if (this.<RootData<K, V>>getRootData().getQueuedOrphans().containsValue(o)) {
          return false;
        }
      }
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().contains(o, matcher);
    }

    @Override
    public boolean containsAll(Collection<?> c, ElementMatcher<? super V> matcher) {
      this.requiredEnabled();
      if (matcher == null) {
        if (this.<RootData<K, V>>getRootData().getQueuedOrphans().values().containsAll(c)) {
          return false;
        }
      }
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().containsAll(c, matcher);
    }

    @Override
    public boolean isEmpty() {
      this.requiredEnabled();
      RootData<K, V> rootData = this.getRootData();
      if (0 == rootData.visionallyReadSize()) {
        return true;
      }
      rootData.load();
      return this.getBase().isEmpty();
    }

    @Override
    public int size() {
      this.requiredEnabled();
      RootData<K, V> rootData = this.getRootData();
      if (this.<AbstractLazyXMap<K, V>>getParentMap().getParent() == null) {
        int size = rootData.visionallyReadSize();
        if (size != -1) {
          return size;
        }
      }
      rootData.load();
      return this.getBase().size();
    }

    @Override
    public Object[] toArray() {
      this.requiredEnabled();
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
      this.requiredEnabled();
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().toArray(a);
    }

    @Override
    public void clear() {
      this.enable();
      this.<RootData<K, V>>getRootData().load();
      this.getBase().clear();
    }

    @Override
    public boolean remove(Object o) {
      this.enable();
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().remove(o);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
      this.enable();
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().removeAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
      this.enable();
      this.<RootData<K, V>>getRootData().load();
      return this.getBase().retainAll(c);
    }

    @Override
    public XIterator<V> iterator() {
      return new IteratorImpl<K, V>(this);
    }

    protected static class IteratorImpl<K, V>
        extends AbstractWrapperXMap.ValuesImpl.IteratorImpl<K, V> {

      public IteratorImpl(ValuesImpl<K, V> parent) {
        super(loadParent(parent));
      }

      private static <K, V> ValuesImpl<K, V> loadParent(ValuesImpl<K, V> parent) {
        parent.<RootData<K, V>>getRootData().load();
        return parent;
      }
    }
  }

  protected abstract static class AbstractEntryImpl<K, V>
      extends AbstractWrapperXMap.AbstractEntryImpl<K, V> {

    public AbstractEntryImpl(AbstractLazyXMap<K, V> parentMap, ViewInfo viewInfo)
        throws NoEntryException {
      super(loadedParentMap(parentMap), viewInfo);
    }

    public AbstractEntryImpl(AbstractLazyXMap.EntrySetImpl.IteratorImpl<K, V> iterator) {
      super(iterator);
    }

    private static <K, V> AbstractLazyXMap<K, V> loadedParentMap(AbstractLazyXMap<K, V> parentMap) {
      parentMap.load();
      return parentMap;
    }
  }

  protected static class EntryImpl<K, V> extends AbstractEntryImpl<K, V> {

    public EntryImpl(AbstractLazyXMap.EntrySetImpl.IteratorImpl<K, V> iterator) {
      super(iterator);
    }
  }

  protected static class RealEntryImpl<K, V> extends AbstractEntryImpl<K, V> {

    protected RealEntryImpl(AbstractLazyXMap<K, V> parentMap, K key) throws NoEntryException {
      super(parentMap, MapViewInfos.real(key));
    }

    @SuppressWarnings("unchecked")
    @Override
    protected org.babyfish.collection.XMap.XEntry<K, V> createBaseView(
        XMap<K, V> baseMap, ViewInfo viewInfo) {
      if (viewInfo instanceof MapViewInfos.RealByKey) {
        K key = (K) ((MapViewInfos.RealByKey) viewInfo).getKey();
        return baseMap.real(key);
      }
      throw new IllegalArgumentException(LAZY_COMMON_RESOURCE.get().illegalViewInfo());
    }
  }

  protected abstract static class RootData<K, V> extends AbstractWrapperXMap.RootData<K, V> {

    private static final long serialVersionUID = -2206856734988661149L;

    private XMap<K, V> delayOrphanMap;

    private LazyBehaviorProcessor lazyBehaviorProcessor;

    public RootData() {}

    public abstract boolean isLoaded();

    public abstract boolean isLoading();

    public abstract boolean isLoadable();

    protected abstract void setLoaded(boolean loaded);

    protected abstract void setLoading(boolean loading);

    public final void load() {
      if (!this.isLoaded()) {
        if (this.isLoading()) {
          throw new IllegalStateException(
              LAZY_COMMON_RESOURCE.get().loadingOperationWhenDataIsBeingLoaded());
        }
        this.setLoading(true);
        try {
          this.onLoad();
          // The second setLoading(true) is very important!
          // because onLoad() may set the initializing to be false.
          this.setLoading(true);
          this.performQueuedOrphans();
        } finally {
          this.setLoading(false);
        }
        this.setLoaded(true);
      }
    }

    @Override
    public boolean isDispatchable() {
      if (this.isLoading()) {
        return false;
      }
      return super.isDispatchable();
    }

    public final boolean isVisionallyReadable(QueuedOperationType nullOrOperationType) {
      return !this.isLoaded() && this.onGetVisionallyReadable(nullOrOperationType);
    }

    public final boolean hasQueuedOrphans() {
      return this.delayOrphanMap != null;
    }

    public final XMap<K, V> getQueuedOrphans() {
      XMap<K, V> map = this.delayOrphanMap;
      if (map == null) {
        return MACollections.emptyMap();
      }
      return MACollections.unmodifiable(map);
    }

    public final boolean performQueuedOrphans() {
      if (this.isLoaded()) {
        XMap<K, V> map = this.delayOrphanMap;
        if (map != null) {
          this.delayOrphanMap = null;
          this.getBase().keySet().removeAll(map.keySet());
          return true;
        }
      }
      return false;
    }

    public final int visionallyReadSize() {
      if (this.isVisionallyReadable(null)) {
        LazyBehaviorProcessor lazyBehaviorProcessor = this.getLazyBehaviorProcessor();
        if (lazyBehaviorProcessor.preVisionallyReadSize()) {
          int size = this.onGetVisionalSize();
          if (size != -1) {
            lazyBehaviorProcessor.visionallyReadSize();
          }
        }
      }
      return -1;
    }

    public final Ref<V> visionallyRead(K key, QueuedOperationType nullOrOperationType) {
      XMap<K, V> delayOrphanMap = this.delayOrphanMap;
      if (delayOrphanMap != null && delayOrphanMap.containsKey(key)) {
        return new Ref<V>(null);
      }
      if (!this.isVisionallyReadable(nullOrOperationType)) {
        return null;
      }
      return this.onVisionallyRead(key, nullOrOperationType);
    }

    protected abstract void onLoad();

    protected boolean onGetVisionallyReadable(QueuedOperationType nullOrOperationType) {
      return true;
    }

    protected int onGetVisionalSize() {
      return -1;
    }

    protected Ref<V> onVisionallyRead(K key, QueuedOperationType nullOrOperationType) {
      return null;
    }

    protected LazyBehaviorProcessor createLazyBehaviorProcessor() {
      return null;
    }

    final void visinallyRemove(K key, V value) {
      XMap<K, V> delayOrphanMap = this.delayOrphanMap;
      if (delayOrphanMap == null) {
        UnifiedComparator<? super K> keyUnifiedComparator = this.keyUnifiedComparator();
        if (keyUnifiedComparator.comparator() != null) {
          delayOrphanMap =
              new TreeMap<K, V>(
                  ReplacementRule.NEW_REFERENCE_WIN,
                  keyUnifiedComparator.comparator(),
                  this.valueUnifiedComparator());
        } else {
          delayOrphanMap =
              new LinkedHashMap<K, V>(
                  ReplacementRule.NEW_REFERENCE_WIN,
                  keyUnifiedComparator.equalityComparator(),
                  this.valueUnifiedComparator(),
                  false,
                  OrderAdjustMode.TAIL,
                  OrderAdjustMode.TAIL);
        }
        this.delayOrphanMap = delayOrphanMap;
      }
      delayOrphanMap.put(key, value);
    }

    final LazyBehaviorProcessor getLazyBehaviorProcessor() {
      LazyBehaviorProcessor lazyBehaviorProcessor = this.lazyBehaviorProcessor;
      if (lazyBehaviorProcessor == null) {
        lazyBehaviorProcessor = this.createLazyBehaviorProcessor();
        if (lazyBehaviorProcessor == null) {
          lazyBehaviorProcessor = LazyBehaviorProcessor.unlimited();
        }
        this.lazyBehaviorProcessor = lazyBehaviorProcessor;
      }
      return lazyBehaviorProcessor;
    }
  }
}
Пример #2
0
/** @author Tao Chen */
public abstract class EntityOrderedMap<O, K, V> extends AssociatedOrderedMap<O, K, V>
    implements PersistentCollection<V> {

  private static final long serialVersionUID = 6771523680037334618L;

  private static LazyResource<CommonResource> LAZY_COMMON_RESOURCE =
      LazyResource.of(CommonResource.class);

  @Override
  protected boolean isLoadedValue(V value) {
    return Hibernate.isInitialized(value);
  }

  @Override
  protected boolean isAbandonableValue(V value) {
    // This endpoint is not inverse means the opposite end point is inverse.
    if (!this.isInverse() && value instanceof HibernateProxy) {
      HibernateProxy proxy = (HibernateProxy) value;
      SessionImplementor session = proxy.getHibernateLazyInitializer().getSession();
      return session == null || !session.isOpen() || !session.isConnected();
    }
    return false;
  }

  @Override
  protected void loadValue(V value) {
    Hibernate.initialize(value);
  }

  protected abstract boolean isInverse();

  Map<K, V> hibernateGet() {
    return this.getBase();
  }

  void hibernateSet(Object value) {
    this.replace(value);
  }

  /*
   * Implements the methods of "org.babyfish.hibernate.collection.spi.Persistence",
   * which is the derived interface of "org.hibernate.collection.PersistentCollection"
   * in order to change the ugly methods to be generic methods.
   *
   * Actually, the collection is a wrapper of "org.hibernate.collection.PersistentCollection"
   * so it need not to implement that interface.
   *
   * But Hibernate.isInitialized(Object) and Hibernate.initialize(Object)
   * required that the collections are always implementations of
   * "org.hibernate.collection.PersistentCollection".
   *
   * If the class does not implement that interface, the
   * Hibernate.isInitialized(Object) and Hibernate.initialize(Object)
   * can work normally. This is not a good idea, even if the user
   * can cast the collection to "org.babyfish.model.LazinessManageable" and invoke its
   * isLoaded() and load().
   *
   * So this class implements "org.hibernate.collection.PersistentCollection"
   * and deprecated all the methods except wasInitialized() and forceInitialization().
   * because
   * Hibernate.isInitialized(Object) invokes
   * "org.hibernate.collection.PersistentCollection.wasInitialized()"
   * and
   * Hibernate.initialized(Object) invokes
   * "org.hibernate.collection.PersistentCollection.forceInitialization()"
   */
  @Override
  public final boolean wasInitialized() {
    return this.isLoaded();
  }

  @Override
  public final void forceInitialization() throws HibernateException {
    this.load();
  }

  @Deprecated
  @Override
  public final void setOwner(Object entity) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean empty() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final void setSnapshot(Serializable key, String role, Serializable snapshot) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final void postAction() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Object getValue() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final void beginRead() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean endRead() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean afterInitialize() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean isDirectlyAccessible() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean unsetSession(SessionImplementor currentSession) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean setCurrentSession(SessionImplementor session) throws HibernateException {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final void initializeFromCache(
      CollectionPersister persister, Serializable disassembled, Object owner)
      throws HibernateException {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Object getIdentifier(Object entry, int i) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Object getIndex(Object entry, int i, CollectionPersister persister) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Object getSnapshotElement(Object entry, int i) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean isSnapshotEmpty(Serializable snapshot) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Serializable disassemble(CollectionPersister persister) throws HibernateException {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean needsRecreate(CollectionPersister persister) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean entryExists(Object entry, int i) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean needsInserting(Object entry, int i, Type elemType)
      throws HibernateException {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean isRowUpdatePossible() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean isWrapper(Object collection) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean hasQueuedOperations() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Serializable getKey() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final String getRole() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean isUnreferenced() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final boolean isDirty() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final void clearDirty() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Serializable getStoredSnapshot() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final void dirty() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final void preInsert(CollectionPersister persister) throws HibernateException {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final void afterRowInsert(CollectionPersister persister, Object entry, int i)
      throws HibernateException {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final V getElement(Object entry) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Iterator<V> entries(CollectionPersister persister) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final V readFrom(
      ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner)
      throws HibernateException, SQLException {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Iterator<V> getDeletes(CollectionPersister persister, boolean indexIsFormula)
      throws HibernateException {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Collection<V> getOrphans(Serializable snapshot, String entityName)
      throws HibernateException {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Iterator<V> queuedAdditionIterator() {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }

  @Deprecated
  @Override
  public final Collection<V> getQueuedOrphans(String entityName) {
    throw new UnsupportedOperationException(
        LAZY_COMMON_RESOURCE
            .get()
            .persistentCollectionBehaviorIsInvalid(
                EntityOrderedMap.class, org.hibernate.collection.spi.PersistentCollection.class));
  }
}