|
@@ -15,12 +15,42 @@ |
15 |
15 |
|
private String mName; |
16 |
16 |
|
private String mType; |
17 |
17 |
|
private boolean mMementoableType; |
18 |
|
- |
private boolean mNullEmpties; |
19 |
|
- |
private boolean mNullZeros; |
20 |
|
- |
private boolean mNullFalses; |
21 |
|
- |
private boolean mRepeating; |
|
18 |
+ |
protected boolean mNullEmpties; |
|
19 |
+ |
protected boolean mNullZeros; |
|
20 |
+ |
protected boolean mNullFalses; |
|
21 |
+ |
protected boolean mRepeating; |
22 |
22 |
|
private String[] mNotes = Strings.EMPTY_ARRAY; |
23 |
23 |
|
|
|
24 |
+ |
private AttributeData() |
|
25 |
+ |
{ |
|
26 |
+ |
} |
|
27 |
+ |
|
|
28 |
+ |
public AttributeData( int pID, BeanAttributeBuilder pAttribute ) |
|
29 |
+ |
{ |
|
30 |
+ |
mID = pID; |
|
31 |
+ |
mName = pAttribute.getName(); |
|
32 |
+ |
mRepeating = pAttribute.isRepeating(); |
|
33 |
+ |
mNotes = pAttribute.getNotes(); |
|
34 |
+ |
mNullEmpties = pAttribute.isNullEmpties(); |
|
35 |
+ |
mNullZeros = pAttribute.isNullZeros(); |
|
36 |
+ |
mNullFalses = pAttribute.isNullFalses(); |
|
37 |
+ |
mType = pAttribute.getType(); |
|
38 |
+ |
mMementoableType = !Objects.isOneOf( mType, VALID_TYPES ); |
|
39 |
+ |
} |
|
40 |
+ |
|
|
41 |
+ |
private AttributeData( AttributeData pCloneFrom ) |
|
42 |
+ |
{ |
|
43 |
+ |
this.mID = pCloneFrom.mID; |
|
44 |
+ |
this.mName = pCloneFrom.mName; |
|
45 |
+ |
this.mType = pCloneFrom.mType; |
|
46 |
+ |
this.mMementoableType = pCloneFrom.mMementoableType; |
|
47 |
+ |
this.mNullEmpties = pCloneFrom.mNullEmpties; |
|
48 |
+ |
this.mNullZeros = pCloneFrom.mNullZeros; |
|
49 |
+ |
this.mNullFalses = pCloneFrom.mNullFalses; |
|
50 |
+ |
this.mRepeating = pCloneFrom.mRepeating; |
|
51 |
+ |
this.mNotes = pCloneFrom.mNotes; |
|
52 |
+ |
} |
|
53 |
+ |
|
24 |
54 |
|
public int getID() |
25 |
55 |
|
{ |
26 |
56 |
|
return mID; |
|
@@ -74,18 +104,39 @@ |
74 |
104 |
|
/** |
75 |
105 |
|
* An ID is a 2 digit value (with leading zeros) between 0 & 99 |
76 |
106 |
|
*/ |
77 |
|
- |
private void parseID( String pID ) |
|
107 |
+ |
private void appendID( StringBuilder pSB ) // PART1 |
|
108 |
+ |
{ |
|
109 |
+ |
pSB.append( Integers.zeroPadIt( 2, mID ) ); |
|
110 |
+ |
} |
|
111 |
+ |
|
|
112 |
+ |
/** |
|
113 |
+ |
* An ID is a 2 digit value (with leading zeros) between 0 & 99 |
|
114 |
+ |
*/ |
|
115 |
+ |
private void parseID( String pID ) // PART1 |
78 |
116 |
|
{ |
79 |
117 |
|
mID = Integer.parseInt( pID ); |
80 |
118 |
|
} |
81 |
119 |
|
|
|
120 |
+ |
private void appendType( StringBuilder pSB ) |
|
121 |
+ |
{ |
|
122 |
+ |
pSB.append( isMementoableType() ? MEMENTOABLE_ATTRIBUTE_PROXY_TYPE : getType() ); |
|
123 |
+ |
} |
|
124 |
+ |
|
|
125 |
+ |
private void appendMementoTypeExtension1( StringBuilder pSB ) // PART5 |
|
126 |
+ |
{ |
|
127 |
+ |
if ( isMementoableType() ) |
|
128 |
+ |
{ |
|
129 |
+ |
pSB.append( '<' ).append( getType() ).append( '>' ); |
|
130 |
+ |
} |
|
131 |
+ |
} |
|
132 |
+ |
|
82 |
133 |
|
/** |
83 |
134 |
|
* Parse the Pre & Post type indicators. |
84 |
135 |
|
* |
85 |
136 |
|
* @param pPreType an AttributeProxy type: Mementoable, String, Integer, ... |
86 |
137 |
|
* @param pBracketedPostType Either an empty String of the class name of the Mementoable surrounded by generic type indicators ('<' & '>'). |
87 |
138 |
|
*/ |
88 |
|
- |
private void parseType( String pPreType, String pBracketedPostType ) |
|
139 |
+ |
private void parseType( String pPreType, String pBracketedPostType ) // PART3 & PART5 |
89 |
140 |
|
{ |
90 |
141 |
|
// "String" & "" || "Mementoable" & "<DetailBean>" |
91 |
142 |
|
if ( !MEMENTOABLE_ATTRIBUTE_PROXY_TYPE.equals( pPreType ) ) |
|
@@ -106,10 +157,30 @@ |
106 |
157 |
|
throw new IllegalArgumentException( "Unacceptable BracketedPostType: " + pBracketedPostType ); |
107 |
158 |
|
} |
108 |
159 |
|
|
|
160 |
+ |
private void appendMementoTypeExtension2( StringBuilder pSB ) // PART7b |
|
161 |
+ |
{ |
|
162 |
+ |
if ( isMementoableType() ) |
|
163 |
+ |
{ |
|
164 |
+ |
pSB.append( ATTR_PART7b_PRE_TYPE ).append( mType ).append( ATTR_PART7b_POST_TYPE ); |
|
165 |
+ |
} |
|
166 |
+ |
} |
|
167 |
+ |
|
|
168 |
+ |
private void appendName( StringBuilder pSB ) // PART7a |
|
169 |
+ |
{ |
|
170 |
+ |
if ( mName == null ) |
|
171 |
+ |
{ |
|
172 |
+ |
pSB.append( ATTR_PART7a_NO_NAME ); |
|
173 |
+ |
} |
|
174 |
+ |
else |
|
175 |
+ |
{ |
|
176 |
+ |
pSB.append( DOUBLE_QUOTE ).append( mName ).append( DOUBLE_QUOTE ); |
|
177 |
+ |
} |
|
178 |
+ |
} |
|
179 |
+ |
|
109 |
180 |
|
/** |
110 |
181 |
|
* Parse the name from the Attribute Proxy's Parameters. |
111 |
182 |
|
*/ |
112 |
|
- |
private void parseName( String pAttributeProxyParameters ) |
|
183 |
+ |
private void parseName( String pAttributeProxyParameters ) // PART7 |
113 |
184 |
|
{ |
114 |
185 |
|
// A string of 'null' which indicates that this is a legacy place holder |
115 |
186 |
|
// Single (double quoted) Names, e.g.: "FirstName", "Name", "Description" |
|
@@ -119,7 +190,7 @@ |
119 |
190 |
|
String zName = pAttributeProxyParameters; |
120 |
191 |
|
if ( mMementoableType ) |
121 |
192 |
|
{ |
122 |
|
- |
String zDefaultInstanceTail = ", " + mType + ".DEFAULT_INSTANCE"; |
|
193 |
+ |
String zDefaultInstanceTail = ATTR_PART7b_PRE_TYPE + mType + ATTR_PART7b_POST_TYPE; |
123 |
194 |
|
if ( !pAttributeProxyParameters.endsWith( zDefaultInstanceTail ) ) |
124 |
195 |
|
{ |
125 |
196 |
|
throw new IllegalArgumentException( |
|
@@ -127,9 +198,9 @@ |
127 |
198 |
|
} |
128 |
199 |
|
zName = pAttributeProxyParameters.substring( 0, pAttributeProxyParameters.length() - zDefaultInstanceTail.length() ); |
129 |
200 |
|
} |
130 |
|
- |
if ( !zName.equals( "null" ) ) |
|
201 |
+ |
if ( !zName.equals( ATTR_PART7a_NO_NAME ) ) |
131 |
202 |
|
{ |
132 |
|
- |
if ( (zName.length() < 3) || !zName.startsWith( "\"" ) || !zName.endsWith( "\"" ) ) |
|
203 |
+ |
if ( (zName.length() < 3) || !zName.startsWith( DOUBLE_QUOTE ) || !zName.endsWith( DOUBLE_QUOTE ) ) |
133 |
204 |
|
{ |
134 |
205 |
|
throw new IllegalArgumentException( "Malformed name '" + zName + "' in: " + pAttributeProxyParameters ); |
135 |
206 |
|
} |
|
@@ -142,6 +213,14 @@ |
142 |
213 |
|
} |
143 |
214 |
|
} |
144 |
215 |
|
|
|
216 |
+ |
private void appendFlags( StringBuilder pSB ) // PART9 |
|
217 |
+ |
{ |
|
218 |
+ |
for ( BeanAttributeProperties zValue : BeanAttributeProperties.values() ) |
|
219 |
+ |
{ |
|
220 |
+ |
zValue.appendFlag( this, pSB ); |
|
221 |
+ |
} |
|
222 |
+ |
} |
|
223 |
+ |
|
145 |
224 |
|
// /* 00 */ new StringAttributeProxy( "FirstName" ), // |
146 |
225 |
|
// /* 00 */ new StringAttributeProxy( "Name" ).nullEmpties(), // |
147 |
226 |
|
// /* 01 */ new StringAttributeProxy( null ), // |
|
@@ -151,28 +230,34 @@ |
151 |
230 |
|
// /* 04 */ new MementoableAttributeProxy<DetailBean>( "Details", DetailBean.DEFAULT_INSTANCE ).nullEmpties().repeating(), // |
152 |
231 |
|
// 123 12345678 12345678901234 12 12 1234 |
153 |
232 |
|
// 0 1 2 3 4 5 6 7 8 9 10 |
154 |
|
- |
private void parseFlags( String pFlags ) |
|
233 |
+ |
private void parseFlags( String pFlags ) // PART9 |
155 |
234 |
|
{ |
156 |
235 |
|
StringBuilder zFlags = new StringBuilder( pFlags ); |
157 |
|
- |
mNullEmpties = checkFor( ".nullEmpties()", zFlags ); |
158 |
|
- |
mNullZeros = checkFor( ".nullZeros()", zFlags ); |
159 |
|
- |
mNullFalses = checkFor( ".nullFalses()", zFlags ); |
160 |
|
- |
mRepeating = checkFor( ".repeating()", zFlags ); |
|
236 |
+ |
for ( BeanAttributeProperties zValue : BeanAttributeProperties.values() ) |
|
237 |
+ |
{ |
|
238 |
+ |
zValue.parseFlag( this, zFlags ); |
|
239 |
+ |
} |
161 |
240 |
|
if ( zFlags.length() != 0 ) |
162 |
241 |
|
{ |
163 |
242 |
|
throw new IllegalArgumentException( "Don't understand '" + zFlags + "' in: " + pFlags ); |
164 |
243 |
|
} |
165 |
244 |
|
} |
166 |
245 |
|
|
167 |
|
- |
private boolean checkFor( String pStringToFind, StringBuilder pFlags ) |
|
246 |
+ |
public String toParseLine() |
168 |
247 |
|
{ |
169 |
|
- |
int zAt = pFlags.indexOf( pStringToFind ); |
170 |
|
- |
if ( zAt == -1 ) |
171 |
|
- |
{ |
172 |
|
- |
return false; |
173 |
|
- |
} |
174 |
|
- |
pFlags.delete( zAt, zAt + pStringToFind.length() ); |
175 |
|
- |
return true; |
|
248 |
+ |
StringBuilder sb = new StringBuilder(); |
|
249 |
+ |
sb.append( ATTR_PART0 ); |
|
250 |
+ |
appendID( sb ); // PART1 |
|
251 |
+ |
sb.append( ATTR_PART2 ); |
|
252 |
+ |
appendType( sb ); // PART3 |
|
253 |
+ |
sb.append( ATTR_PART4 ); |
|
254 |
+ |
appendMementoTypeExtension1( sb ); // PART5 |
|
255 |
+ |
sb.append( ATTR_PART6 ); |
|
256 |
+ |
appendName( sb ); // PART7a |
|
257 |
+ |
appendMementoTypeExtension2( sb ); // PART7b |
|
258 |
+ |
sb.append( ATTR_PART8 ); |
|
259 |
+ |
appendFlags( sb ); // PART9 |
|
260 |
+ |
return sb.append( ATTR_PART10 ).toString(); |
176 |
261 |
|
} |
177 |
262 |
|
|
178 |
263 |
|
public static AttributeData parseLine( String pLine ) |
|
@@ -197,10 +282,11 @@ |
197 |
282 |
|
AttributeData zAttribute = new AttributeData(); |
198 |
283 |
|
try |
199 |
284 |
|
{ |
200 |
|
- |
zAttribute.parseID( pLine.substring( 3, atPart2 ) ); |
201 |
|
- |
zAttribute.parseType( pLine.substring( 13, atPart4 ), pLine.substring( atPart4 + 14, atPart6 ) ); |
202 |
|
- |
zAttribute.parseName( pLine.substring( atPart6 + 2, atPart8 ) ); |
203 |
|
- |
zAttribute.parseFlags( pLine.substring( atPart8 + 2, pLine.length() - 4 ) ); |
|
285 |
+ |
zAttribute.parseID( pLine.substring( ATTR_PART0.length(), atPart2 ) ); // PART1 |
|
286 |
+ |
zAttribute.parseType( pLine.substring( atPart2 + ATTR_PART2.length(), atPart4 ), // PART3 |
|
287 |
+ |
pLine.substring( atPart4 + ATTR_PART4.length(), atPart6 ) ); // PART5 |
|
288 |
+ |
zAttribute.parseName( pLine.substring( atPart6 + ATTR_PART6.length(), atPart8 ) ); // PART7 |
|
289 |
+ |
zAttribute.parseFlags( pLine.substring( atPart8 + ATTR_PART8.length(), pLine.length() - ATTR_PART10.length() ) ); // PART9 |
204 |
290 |
|
return zAttribute; |
205 |
291 |
|
} |
206 |
292 |
|
catch ( IllegalArgumentException e ) |
|
@@ -225,4 +311,52 @@ |
225 |
311 |
|
} |
226 |
312 |
|
return zTypes.toArray( new String[zTypes.size()] ); |
227 |
313 |
|
} |
|
314 |
+ |
|
|
315 |
+ |
public AttributeData makePlaceHolder() |
|
316 |
+ |
{ |
|
317 |
+ |
AttributeData zAttributeData = new AttributeData( this ); |
|
318 |
+ |
zAttributeData.mName = null; |
|
319 |
+ |
zAttributeData.setNotes( null ); |
|
320 |
+ |
if ( isMementoableType() ) |
|
321 |
+ |
{ |
|
322 |
+ |
zAttributeData.mNullEmpties = true; |
|
323 |
+ |
zAttributeData.mType = "String"; |
|
324 |
+ |
zAttributeData.mMementoableType = false; |
|
325 |
+ |
} |
|
326 |
+ |
return zAttributeData; |
|
327 |
+ |
} |
|
328 |
+ |
|
|
329 |
+ |
public boolean isUpdatableFrom( BeanAttributeBuilder pAttribute ) |
|
330 |
+ |
{ |
|
331 |
+ |
return Objects.areNonArraysEqual( this.getName(), pAttribute.getName() ) && // |
|
332 |
+ |
Objects.areNonArraysEqual( this.getType(), pAttribute.getType() ) && // |
|
333 |
+ |
(this.isRepeating() == pAttribute.isRepeating()); |
|
334 |
+ |
} |
|
335 |
+ |
|
|
336 |
+ |
/** |
|
337 |
+ |
* Either return <code>this</code> if nothing has changed or create a new instance from <code>this</code> with the changes |
|
338 |
+ |
* <p/> |
|
339 |
+ |
* Note: <code>pAttribute</code> must have already passed thru <code>isUpdatableFrom</code> |
|
340 |
+ |
*/ |
|
341 |
+ |
public AttributeData updateWith( BeanAttributeBuilder pAttribute ) |
|
342 |
+ |
{ |
|
343 |
+ |
if ( isUpdatableFromRestIsEquivalent( pAttribute ) ) |
|
344 |
+ |
{ |
|
345 |
+ |
return this; |
|
346 |
+ |
} |
|
347 |
+ |
AttributeData zAttributeData = new AttributeData( this ); |
|
348 |
+ |
zAttributeData.setNotes( pAttribute.getNotes() ); |
|
349 |
+ |
zAttributeData.mNullEmpties = pAttribute.isNullEmpties(); |
|
350 |
+ |
zAttributeData.mNullZeros = pAttribute.isNullZeros(); |
|
351 |
+ |
zAttributeData.mNullFalses = pAttribute.isNullFalses(); |
|
352 |
+ |
return zAttributeData; |
|
353 |
+ |
} |
|
354 |
+ |
|
|
355 |
+ |
private boolean isUpdatableFromRestIsEquivalent( BeanAttributeBuilder pAttribute ) |
|
356 |
+ |
{ |
|
357 |
+ |
return Objects.areArraysEqual( this.getNotes(), pAttribute.getNotes() ) && // |
|
358 |
+ |
(this.isNullEmpties() == pAttribute.isNullEmpties()) && // |
|
359 |
+ |
(this.isNullZeros() == pAttribute.isNullZeros()) && // |
|
360 |
+ |
(this.isNullFalses() == pAttribute.isNullFalses()); |
|
361 |
+ |
} |
228 |
362 |
|
} |