Subversion Repository Public Repository

litesoft

Diff Revisions 949 vs 950 for /trunk/Java/core/Anywhere/src/org/litesoft/bo/change/AbstractChangeTrackingObject.java

Diff revisions: vs.
  @@ -1,256 +1,268 @@
1 - // This Source Code is in the Public Domain per: http://unlicense.org
2 - package org.litesoft.bo.change;
3 -
4 - import org.litesoft.bo.*;
5 - import org.litesoft.commonfoundation.typeutils.Objects;
6 -
7 - import java.util.*;
8 -
9 - public abstract class AbstractChangeTrackingObject implements IChangeTrackingObject {
10 - public static final int INITIAL_CHANGE_NUMBER = 0;
11 -
12 - private int mChangeNumber = INITIAL_CHANGE_NUMBER;
13 -
14 - private boolean mInitialized = false;
15 - private boolean mDeleteRequested = false;
16 -
17 - private transient Boolean mChangeAllowed; // null means that we are reconstituted after Serialization
18 - private boolean mNew;
19 -
20 - private OriginalValueChangeTracker mChangeTracker;
21 -
22 - /**
23 - * For Serialization
24 - */
25 - protected AbstractChangeTrackingObject() {
26 - mChangeAllowed = null;
27 - }
28 -
29 - protected AbstractChangeTrackingObject( boolean pChangeAllowed, boolean pNew ) {
30 - mChangeAllowed = pNew || pChangeAllowed;
31 - mNew = pNew;
32 - mChangeTracker = OriginalValueChangeTrackerNull.INSTANCE;
33 - }
34 -
35 - public final void forceSetAttributeValue( String pAttributeName, Object pValue )
36 - throws NoSuchElementException, AttributeIllegalArgumentException {
37 - boolean zInitialized = mInitialized;
38 - mInitialized = false;
39 - Boolean zChangeAllowed = mChangeAllowed;
40 - mChangeAllowed = true;
41 - setAttributeValue( pAttributeName, pValue );
42 - mChangeAllowed = zChangeAllowed;
43 - mInitialized = zInitialized;
44 - }
45 -
46 - protected void LLunNew() {
47 - mNew = false;
48 - }
49 -
50 - public boolean isInitialized() {
51 - return mInitialized;
52 - }
53 -
54 - // IChangeTrackingObject...
55 -
56 - public void initialize() {
57 - mInitialized = true;
58 - }
59 -
60 - public boolean isChangeAllowed() {
61 - return Boolean.TRUE.equals( mChangeAllowed );
62 - }
63 -
64 - public final int getChangeNumber() {
65 - return mChangeNumber;
66 - }
67 -
68 - public final boolean isDirty() {
69 - return isDeleteRequested() || isNew() || isAnyAttributeChanged() || LLisDirty();
70 - }
71 -
72 - public final void requestDelete() {
73 - if ( !mInitialized ) {
74 - throw new IllegalStateException( "During Object initialization, attempted to Delete: " + toString() );
75 - }
76 - if ( verifyMutability() ) {
77 - mDeleteRequested = LLrequestDelete();
78 - }
79 - }
80 -
81 - public final boolean isDeleteRequested() {
82 - return mDeleteRequested;
83 - }
84 -
85 - public final boolean isNew() {
86 - return mNew;
87 - }
88 -
89 - public final boolean isAnyAttributeChanged() {
90 - return mChangeTracker.hasChanges();
91 - }
92 -
93 - /**
94 - * @return if Attribute exists && it has changed
95 - */
96 - public final boolean isAttributeChanged( String pAttributeName ) {
97 - return mChangeTracker.isAttributeChanged( pAttributeName );
98 - }
99 -
100 - public final String[] getChangedAttributeNames() {
101 - return mChangeTracker.getChangedAttributeNames();
102 - }
103 -
104 - public final boolean isOriginalValueAvailableFor( String pAttributeName ) {
105 - return mChangeTracker.isOriginalValueAvailableFor( pAttributeName );
106 - }
107 -
108 - public final Object getOriginalValueFor( String pAttributeName ) {
109 - return mChangeTracker.getOriginalValueFor( pAttributeName );
110 - }
111 -
112 - // support...
113 -
114 - protected void populateFrom( AbstractChangeTrackingObject pThem ) {
115 - boolean zAnyChanges = false;
116 -
117 - for ( BoAttribute zAttribute : getBoMetaData().getBoAttributes() ) {
118 - zAnyChanges |= populateFromRegular( pThem, zAttribute );
119 - }
120 - if ( zAnyChanges ) {
121 - incChangeNumber();
122 - }
123 - }
124 -
125 - protected boolean populateFromRegular( AbstractChangeTrackingObject pThem, BoAttribute pAttribute ) {
126 - String zName = pAttribute.getName();
127 - Object zCurValue = this.getAttributeValue( zName );
128 - Object zNewValue = pThem.getAttributeValue( zName );
129 - if ( !Objects.areEqual( zCurValue, zNewValue ) ) {
130 - ChangeControlledBoAttribute zCCA = getChangeControlledBoAttribute( pAttribute );
131 -
132 - if ( zCCA == null ) {
133 - this.setAttributeValue( zName, zNewValue ); // Assume changeable
134 - return true;
135 - }
136 - if ( zCCA.isSetable() && canMutate( zCCA ) ) {
137 - this.setAttributeValue( zName, zNewValue );
138 - ChangeEntry zChangeEntry = pThem.mChangeTracker.getOriginalValueChangeEntryFor( zName );
139 - if ( zChangeEntry != null ) {
140 - recordChange( zName, zChangeEntry, zCurValue, zNewValue );
141 - }
142 - return true;
143 - }
144 - }
145 - return false;
146 - }
147 -
148 - private ChangeControlledBoAttribute getChangeControlledBoAttribute( BoAttribute pAttribute ) {
149 - return (pAttribute instanceof ChangeControlledBoAttribute) ? (ChangeControlledBoAttribute) pAttribute : null;
150 - }
151 -
152 - private boolean canMutate( ChangeControlledBoAttribute pAttribute ) {
153 - if ( mInitialized ) {
154 - switch ( pAttribute.getMutability() ) {
155 - case RW:
156 - return true;
157 - case AddOnly:
158 - return isNew();
159 - case RO:
160 - return LLallowMutabilityOnRO( pAttribute );
161 - default:
162 - throw new UnsupportedOperationException(
163 - "Unknown Mutability (" + pAttribute.getMutability() + ") on change of Attribute (" + pAttribute.getName() + ") on: " + toString() );
164 - }
165 - }
166 - return true;
167 - }
168 -
169 - private void recordChange( ChangeControlledBoAttribute pChangeControlledBoAttribute, Object pOldValue, Object pNewValue ) {
170 - ChangeEntry zChangeEntry = pChangeControlledBoAttribute.createChangeEntryFor( pOldValue );
171 - if ( zChangeEntry != null ) {
172 - String zAttributeName = pChangeControlledBoAttribute.getName();
173 -
174 - recordChange( zAttributeName, zChangeEntry, pOldValue, pNewValue );
175 - }
176 - }
177 -
178 - private void recordChange( String pAttributeName, ChangeEntry pChangeEntry, Object pOldValue, Object pNewValue ) {
179 - mChangeTracker = mChangeTracker.recordChange( pAttributeName, pChangeEntry, pOldValue, pNewValue );
180 - }
181 -
182 - protected final boolean verifyMutability()
183 - throws UnsupportedOperationException {
184 - if ( !mInitialized ) // We are in "Creation" mode
185 - {
186 - return false;
187 - }
188 - if ( mChangeAllowed == null ) {
189 - throw new UnsupportedOperationException( "Attempt to change a re-constituted from Serialization immutable: " + toString() );
190 - }
191 - if ( Boolean.FALSE.equals( mChangeAllowed ) ) {
192 - throw new UnsupportedOperationException( "Attempt to change a read-only: " + toString() );
193 - }
194 - LLverifyMutability();
195 - return true;
196 - }
197 -
198 - protected final ChangeControlledBoAttribute verifyMutability( BoAttribute pAttribute )
199 - throws UnsupportedOperationException {
200 - return verifyMutability() ? getChangeControlledBoAttribute( pAttribute ) : null;
201 - }
202 -
203 - public final boolean verifyMutabilityOnChange( BoAttribute pBoAttribute, Object pOldValue, Object pNewValue )
204 - throws UnsupportedOperationException {
205 - if ( Objects.areEqual( pOldValue, pNewValue ) ) {
206 - return false;
207 - }
208 - if ( mInitialized ) {
209 - ChangeControlledBoAttribute zChangeControlledBoAttribute = verifyMutability( pBoAttribute );
210 -
211 - if ( zChangeControlledBoAttribute == null ) {
212 - incChangeNumber();
213 - } else {
214 - if ( !canMutate( zChangeControlledBoAttribute ) ) {
215 - throw new UnsupportedOperationException( "Attempt to change read-only attribute '" + pBoAttribute.getName() + "' on: " + toString() );
216 - }
217 - incChangeNumber();
218 -
219 - recordChange( zChangeControlledBoAttribute, pOldValue, pNewValue );
220 - }
221 - }
222 - return true;
223 - }
224 -
225 - protected final void incChangeNumber() {
226 - mChangeNumber++;
227 - }
228 -
229 - /**
230 - * Throw exception if you want to STOP changes!
231 - */
232 - protected void LLverifyMutability() {
233 - }
234 -
235 - /**
236 - * @return true to allow Object's RO attribute to be changed anyway.
237 - */
238 - @SuppressWarnings({"UnusedDeclaration"})
239 - protected boolean LLallowMutabilityOnRO( ChangeControlledBoAttribute pAttribute ) {
240 - return false;
241 - }
242 -
243 - /**
244 - * @return true to report dirty beyond the tracked attributes, and New, and Delete Requested
245 - */
246 - protected boolean LLisDirty() {
247 - return false;
248 - }
249 -
250 - /**
251 - * @return true if allowed to actually Request Delete
252 - */
253 - protected boolean LLrequestDelete() {
254 - return true;
255 - }
256 - }
1 + // This Source Code is in the Public Domain per: http://unlicense.org
2 + package org.litesoft.bo.change;
3 +
4 + import org.litesoft.bo.*;
5 + import org.litesoft.commonfoundation.base.*;
6 +
7 + import java.util.*;
8 +
9 + public abstract class AbstractChangeTrackingObject implements IChangeTrackingObject {
10 + public static final int INITIAL_CHANGE_NUMBER = 0;
11 +
12 + private int mChangeNumber = INITIAL_CHANGE_NUMBER;
13 +
14 + private boolean mInitialized = false;
15 + private boolean mDeleteRequested = false;
16 +
17 + private transient Boolean mChangeAllowed; // null means that we are reconstituted after Serialization
18 + private boolean mNew;
19 +
20 + private OriginalValueChangeTracker mChangeTracker;
21 +
22 + /**
23 + * For Serialization
24 + */
25 + protected AbstractChangeTrackingObject() {
26 + mChangeAllowed = null;
27 + }
28 +
29 + protected AbstractChangeTrackingObject( boolean pChangeAllowed, boolean pNew ) {
30 + mChangeAllowed = pNew || pChangeAllowed;
31 + mNew = pNew;
32 + mChangeTracker = OriginalValueChangeTrackerNull.INSTANCE;
33 + }
34 +
35 + public final void forceSetAttributeValue( String pAttributeName, Object pValue )
36 + throws NoSuchElementException, AttributeIllegalArgumentException {
37 + boolean zInitialized = mInitialized;
38 + mInitialized = false;
39 + Boolean zChangeAllowed = mChangeAllowed;
40 + mChangeAllowed = true;
41 + setAttributeValue( pAttributeName, pValue );
42 + mChangeAllowed = zChangeAllowed;
43 + mInitialized = zInitialized;
44 + }
45 +
46 + protected void LLunNew() {
47 + mNew = false;
48 + }
49 +
50 + public boolean isInitialized() {
51 + return mInitialized;
52 + }
53 +
54 + // IChangeTrackingObject...
55 +
56 + @Override
57 + public void initialize() {
58 + mInitialized = true;
59 + }
60 +
61 + @Override
62 + public boolean isChangeAllowed() {
63 + return Boolean.TRUE.equals( mChangeAllowed );
64 + }
65 +
66 + @Override
67 + public final int getChangeNumber() {
68 + return mChangeNumber;
69 + }
70 +
71 + @Override
72 + public final boolean isDirty() {
73 + return isDeleteRequested() || isNew() || isAnyAttributeChanged() || LLisDirty();
74 + }
75 +
76 + @Override
77 + public final void requestDelete() {
78 + if ( !mInitialized ) {
79 + throw new IllegalStateException( "During Object initialization, attempted to Delete: " + toString() );
80 + }
81 + if ( verifyMutability() ) {
82 + mDeleteRequested = LLrequestDelete();
83 + }
84 + }
85 +
86 + @Override
87 + public final boolean isDeleteRequested() {
88 + return mDeleteRequested;
89 + }
90 +
91 + @Override
92 + public final boolean isNew() {
93 + return mNew;
94 + }
95 +
96 + @Override
97 + public final boolean isAnyAttributeChanged() {
98 + return mChangeTracker.hasChanges();
99 + }
100 +
101 + /**
102 + * @return if Attribute exists && it has changed
103 + */
104 + @Override
105 + public final boolean isAttributeChanged( String pAttributeName ) {
106 + return mChangeTracker.isAttributeChanged( pAttributeName );
107 + }
108 +
109 + @Override
110 + public final String[] getChangedAttributeNames() {
111 + return mChangeTracker.getChangedAttributeNames();
112 + }
113 +
114 + @Override
115 + public final boolean isOriginalValueAvailableFor( String pAttributeName ) {
116 + return mChangeTracker.isOriginalValueAvailableFor( pAttributeName );
117 + }
118 +
119 + @Override
120 + public final Object getOriginalValueFor( String pAttributeName ) {
121 + return mChangeTracker.getOriginalValueFor( pAttributeName );
122 + }
123 +
124 + // support...
125 +
126 + protected void populateFrom( AbstractChangeTrackingObject pThem ) {
127 + boolean zAnyChanges = false;
128 +
129 + for ( BoAttribute zAttribute : getBoMetaData().getBoAttributes() ) {
130 + zAnyChanges |= populateFromRegular( pThem, zAttribute );
131 + }
132 + if ( zAnyChanges ) {
133 + incChangeNumber();
134 + }
135 + }
136 +
137 + protected boolean populateFromRegular( AbstractChangeTrackingObject pThem, BoAttribute pAttribute ) {
138 + String zName = pAttribute.getName();
139 + Object zCurValue = this.getAttributeValue( zName );
140 + Object zNewValue = pThem.getAttributeValue( zName );
141 + if ( !Currently.areEqual( zCurValue, zNewValue ) ) {
142 + ChangeControlledBoAttribute zCCA = getChangeControlledBoAttribute( pAttribute );
143 +
144 + if ( zCCA == null ) {
145 + this.setAttributeValue( zName, zNewValue ); // Assume changeable
146 + return true;
147 + }
148 + if ( zCCA.isSetable() && canMutate( zCCA ) ) {
149 + this.setAttributeValue( zName, zNewValue );
150 + ChangeEntry zChangeEntry = pThem.mChangeTracker.getOriginalValueChangeEntryFor( zName );
151 + if ( zChangeEntry != null ) {
152 + recordChange( zName, zChangeEntry, zCurValue, zNewValue );
153 + }
154 + return true;
155 + }
156 + }
157 + return false;
158 + }
159 +
160 + private ChangeControlledBoAttribute getChangeControlledBoAttribute( BoAttribute pAttribute ) {
161 + return (pAttribute instanceof ChangeControlledBoAttribute) ? (ChangeControlledBoAttribute) pAttribute : null;
162 + }
163 +
164 + private boolean canMutate( ChangeControlledBoAttribute pAttribute ) {
165 + if ( mInitialized ) {
166 + switch ( pAttribute.getMutability() ) {
167 + case RW:
168 + return true;
169 + case AddOnly:
170 + return isNew();
171 + case RO:
172 + return LLallowMutabilityOnRO( pAttribute );
173 + default:
174 + throw new UnsupportedOperationException(
175 + "Unknown Mutability (" + pAttribute.getMutability() + ") on change of Attribute (" + pAttribute.getName() + ") on: " + toString() );
176 + }
177 + }
178 + return true;
179 + }
180 +
181 + private void recordChange( ChangeControlledBoAttribute pChangeControlledBoAttribute, Object pOldValue, Object pNewValue ) {
182 + ChangeEntry zChangeEntry = pChangeControlledBoAttribute.createChangeEntryFor( pOldValue );
183 + if ( zChangeEntry != null ) {
184 + String zAttributeName = pChangeControlledBoAttribute.getName();
185 +
186 + recordChange( zAttributeName, zChangeEntry, pOldValue, pNewValue );
187 + }
188 + }
189 +
190 + private void recordChange( String pAttributeName, ChangeEntry pChangeEntry, Object pOldValue, Object pNewValue ) {
191 + mChangeTracker = mChangeTracker.recordChange( pAttributeName, pChangeEntry, pOldValue, pNewValue );
192 + }
193 +
194 + protected final boolean verifyMutability()
195 + throws UnsupportedOperationException {
196 + if ( !mInitialized ) // We are in "Creation" mode
197 + {
198 + return false;
199 + }
200 + if ( mChangeAllowed == null ) {
201 + throw new UnsupportedOperationException( "Attempt to change a re-constituted from Serialization immutable: " + toString() );
202 + }
203 + if ( Boolean.FALSE.equals( mChangeAllowed ) ) {
204 + throw new UnsupportedOperationException( "Attempt to change a read-only: " + toString() );
205 + }
206 + LLverifyMutability();
207 + return true;
208 + }
209 +
210 + protected final ChangeControlledBoAttribute verifyMutability( BoAttribute pAttribute )
211 + throws UnsupportedOperationException {
212 + return verifyMutability() ? getChangeControlledBoAttribute( pAttribute ) : null;
213 + }
214 +
215 + public final boolean verifyMutabilityOnChange( BoAttribute pBoAttribute, Object pOldValue, Object pNewValue )
216 + throws UnsupportedOperationException {
217 + if ( Currently.areEqual( pOldValue, pNewValue ) ) {
218 + return false;
219 + }
220 + if ( mInitialized ) {
221 + ChangeControlledBoAttribute zChangeControlledBoAttribute = verifyMutability( pBoAttribute );
222 +
223 + if ( zChangeControlledBoAttribute == null ) {
224 + incChangeNumber();
225 + } else {
226 + if ( !canMutate( zChangeControlledBoAttribute ) ) {
227 + throw new UnsupportedOperationException( "Attempt to change read-only attribute '" + pBoAttribute.getName() + "' on: " + toString() );
228 + }
229 + incChangeNumber();
230 +
231 + recordChange( zChangeControlledBoAttribute, pOldValue, pNewValue );
232 + }
233 + }
234 + return true;
235 + }
236 +
237 + protected final void incChangeNumber() {
238 + mChangeNumber++;
239 + }
240 +
241 + /**
242 + * Throw exception if you want to STOP changes!
243 + */
244 + protected void LLverifyMutability() {
245 + }
246 +
247 + /**
248 + * @return true to allow Object's RO attribute to be changed anyway.
249 + */
250 + @SuppressWarnings({"UnusedDeclaration"})
251 + protected boolean LLallowMutabilityOnRO( ChangeControlledBoAttribute pAttribute ) {
252 + return false;
253 + }
254 +
255 + /**
256 + * @return true to report dirty beyond the tracked attributes, and New, and Delete Requested
257 + */
258 + protected boolean LLisDirty() {
259 + return false;
260 + }
261 +
262 + /**
263 + * @return true if allowed to actually Request Delete
264 + */
265 + protected boolean LLrequestDelete() {
266 + return true;
267 + }
268 + }