/** @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; } } }
/** @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)); } }