|
18 | 18 | import java.lang.reflect.Constructor; |
19 | 19 | import java.util.Objects; |
20 | 20 |
|
| 21 | +import org.eclipse.serializer.memory.XMemory; |
21 | 22 | import org.eclipse.serializer.persistence.binary.types.AbstractBinaryHandlerCustom; |
22 | 23 | import org.eclipse.serializer.persistence.binary.types.Binary; |
| 24 | +import org.eclipse.serializer.persistence.binary.types.BinaryTypeHandler; |
23 | 25 | import org.eclipse.serializer.persistence.types.PersistenceLoadHandler; |
24 | 26 | import org.eclipse.serializer.persistence.types.PersistenceReferenceLoader; |
25 | 27 | import org.eclipse.serializer.persistence.types.PersistenceStoreHandler; |
|
29 | 31 |
|
30 | 32 |
|
31 | 33 | /** |
32 | | - * Copied from |
33 | | - * {@link org.eclipse.serializer.persistence.binary.org.eclipse.serializer.reference.BinaryHandlerLazyDefault}. |
| 34 | + * This is a complicated one. First off: this handler should only be used for WorkingCopies (see |
| 35 | + * {@link software.xdev.spring.data.eclipse.store.repository.support.copier.copier.EclipseSerializerRegisteringCopier})! |
| 36 | + * <p> |
| 37 | + * First case:<br/> |
| 38 | + * The user creates a {@link SpringDataEclipseStoreLazy} and puts a object in it. |
| 39 | + * This object is stored as with a default {@link BinaryTypeHandler}. But when it gets loaded, |
| 40 | + * it <b>does not</b> load as the stored object, but it gets wrapped in a {@link Lazy#Reference(Object)}. |
| 41 | + * </p> |
| 42 | + * <p> |
| 43 | + * Second case:<br/> |
| 44 | + * The actual lazy object gets loaded from the actual storage. In this case the {@link ObjectSwizzling} is |
| 45 | + * important! It's the actual {@link ObjectSwizzling} from the storage (not from the |
| 46 | + * {@link software.xdev.spring.data.eclipse.store.repository.support.copier.copier.EclipseSerializerRegisteringCopier}). |
| 47 | + * This means, the {@link SpringDataEclipseStoreLazy} holds the objectId of the original lazy in the original |
| 48 | + * storage. |
| 49 | + * Therefore if {@link SpringDataEclipseStoreLazy#get()} is called a new working copy of the lazy from the |
| 50 | + * storage is loaded. |
| 51 | + * </p> |
34 | 52 | */ |
35 | 53 | public final class SpringDataEclipseStoreLazyBinaryHandler |
36 | 54 | extends AbstractBinaryHandlerCustom<SpringDataEclipseStoreLazy.Default<?>> |
37 | 55 | { |
38 | 56 | @SuppressWarnings("rawtypes") |
39 | | - static final Constructor<SpringDataEclipseStoreLazy.Default> CONSTRUCTOR = XReflect.setAccessible( |
| 57 | + static final Constructor<SpringDataEclipseStoreLazy.Default> CONSTRUCTOR_SURROGATE_LAZY = XReflect.setAccessible( |
40 | 58 | XReflect.getDeclaredConstructor( |
41 | 59 | SpringDataEclipseStoreLazy.Default.class, |
42 | 60 | long.class, |
43 | 61 | ObjectSwizzling.class |
44 | 62 | ) |
45 | 63 | ); |
46 | 64 |
|
47 | | - private final ObjectSwizzling objectSwizzling; |
| 65 | + public static final int OFFSET_UNWRAPPED_OBJECT = 8; |
| 66 | + public static final int OFFSET_LAZY = 0; |
48 | 67 |
|
49 | | - public SpringDataEclipseStoreLazyBinaryHandler(final ObjectSwizzling objectSwizzling) |
| 68 | + private final ObjectSwizzling originalStoreLoader; |
| 69 | + |
| 70 | + public SpringDataEclipseStoreLazyBinaryHandler(final ObjectSwizzling originalStoreLoader) |
50 | 71 | { |
51 | 72 | super( |
52 | 73 | SpringDataEclipseStoreLazy.Default.genericType(), |
53 | 74 | CustomFields( |
54 | | - CustomField(Object.class, "subject") |
| 75 | + CustomField(Object.class, "lazySubject"), |
| 76 | + CustomField(Object.class, "unwrappedSubject") |
55 | 77 | ) |
56 | 78 | ); |
57 | | - this.objectSwizzling = Objects.requireNonNull(objectSwizzling); |
| 79 | + this.originalStoreLoader = Objects.requireNonNull(originalStoreLoader); |
58 | 80 | } |
59 | 81 |
|
60 | 82 | @Override |
61 | | - public final void store( |
| 83 | + public void store( |
62 | 84 | final Binary data, |
63 | 85 | final SpringDataEclipseStoreLazy.Default<?> instance, |
64 | 86 | final long objectId, |
65 | 87 | final PersistenceStoreHandler<Binary> handler |
66 | 88 | ) |
67 | 89 | { |
68 | | - final long referenceOid = instance.objectId(); |
69 | | - data.storeEntityHeader(Binary.referenceBinaryLength(1), this.typeId(), objectId); |
70 | | - data.store_long(referenceOid); |
| 90 | + data.storeEntityHeader(Binary.referenceBinaryLength(2), this.typeId(), objectId); |
| 91 | + if(instance.getObjectToBeWrapped() != null) |
| 92 | + { |
| 93 | + // Store unwrapped Object |
| 94 | + final long newObjectId = handler.applyEager(instance.getObjectToBeWrapped()); |
| 95 | + data.store_long(OFFSET_UNWRAPPED_OBJECT, newObjectId); |
| 96 | + } |
| 97 | + else |
| 98 | + { |
| 99 | + // Store only reference to lazy |
| 100 | + data.store_long(OFFSET_LAZY, instance.objectId()); |
| 101 | + } |
71 | 102 | instance.setStored(); |
72 | 103 | } |
73 | 104 |
|
74 | 105 | @SuppressWarnings("unchecked") |
75 | 106 | @Override |
76 | | - public final SpringDataEclipseStoreLazy.Default<?> create(final Binary data, final PersistenceLoadHandler handler) |
| 107 | + public SpringDataEclipseStoreLazy.Default<?> create(final Binary data, final PersistenceLoadHandler handler) |
77 | 108 | { |
78 | | - final long objectId = data.read_long(0); |
| 109 | + final long objectIdOfLazy = data.read_long(OFFSET_LAZY); |
| 110 | + final long objectIdOfUnwrappedObject = data.read_long(OFFSET_UNWRAPPED_OBJECT); |
79 | 111 |
|
80 | | - return Lazy.register( |
81 | | - XReflect.invoke(CONSTRUCTOR, objectId, this.objectSwizzling) |
82 | | - ); |
| 112 | + if(objectIdOfUnwrappedObject == 0) |
| 113 | + { |
| 114 | + return Lazy.register( |
| 115 | + XReflect.invoke(CONSTRUCTOR_SURROGATE_LAZY, objectIdOfLazy, this.originalStoreLoader) |
| 116 | + ); |
| 117 | + } |
| 118 | + return XMemory.instantiateBlank(SpringDataEclipseStoreLazy.Default.class); |
83 | 119 | } |
84 | 120 |
|
85 | 121 | @Override |
86 | | - public final void updateState( |
| 122 | + public void updateState( |
87 | 123 | final Binary data, |
88 | 124 | final SpringDataEclipseStoreLazy.Default<?> instance, |
89 | 125 | final PersistenceLoadHandler handler |
90 | 126 | ) |
91 | 127 | { |
92 | | - // no-op |
| 128 | + this.updateStateT(data, instance, handler); |
| 129 | + } |
| 130 | + |
| 131 | + private <T> void updateStateT( |
| 132 | + final Binary data, |
| 133 | + final SpringDataEclipseStoreLazy.Default<T> instance, |
| 134 | + final PersistenceLoadHandler handler |
| 135 | + ) |
| 136 | + { |
| 137 | + final long objectIdOfUnwrappedObject = data.read_long(OFFSET_UNWRAPPED_OBJECT); |
| 138 | + |
| 139 | + if(objectIdOfUnwrappedObject != 0) |
| 140 | + { |
| 141 | + instance.setWrappedLazy(Lazy.Reference((T)handler.lookupObject(objectIdOfUnwrappedObject))); |
| 142 | + } |
93 | 143 | } |
94 | 144 |
|
95 | 145 | @Override |
@@ -122,10 +172,15 @@ public final boolean hasVaryingPersistedLengthInstances() |
122 | 172 |
|
123 | 173 | @Override |
124 | 174 | public final void iterateLoadableReferences( |
125 | | - final Binary offset, |
| 175 | + final Binary data, |
126 | 176 | final PersistenceReferenceLoader iterator |
127 | 177 | ) |
128 | 178 | { |
129 | | - // the lazy reference is not naturally loadable, but special-handled by this handler |
| 179 | + final long objectIdOfUnwrappedObject = data.read_long(OFFSET_UNWRAPPED_OBJECT); |
| 180 | + |
| 181 | + if(objectIdOfUnwrappedObject != 0) |
| 182 | + { |
| 183 | + iterator.acceptObjectId(objectIdOfUnwrappedObject); |
| 184 | + } |
130 | 185 | } |
131 | 186 | } |
0 commit comments