1818
1919import com .igormaznitsa .jbbp .exceptions .JBBPException ;
2020import com .igormaznitsa .jbbp .exceptions .JBBPIllegalArgumentException ;
21- import com .igormaznitsa .jbbp .mapper .Bin ;
22- import com .igormaznitsa .jbbp .mapper .BinType ;
23- import com .igormaznitsa .jbbp .mapper .JBBPMapper ;
24- import com .igormaznitsa .jbbp .mapper .MappedFieldRecord ;
21+ import com .igormaznitsa .jbbp .mapper .*;
2522import com .igormaznitsa .jbbp .model .JBBPFieldInt ;
2623import com .igormaznitsa .jbbp .model .JBBPFieldLong ;
2724import com .igormaznitsa .jbbp .model .JBBPFieldShort ;
2825import com .igormaznitsa .jbbp .model .JBBPFieldString ;
2926import com .igormaznitsa .jbbp .utils .BinAnnotationWrapper ;
3027import com .igormaznitsa .jbbp .utils .JBBPUtils ;
28+
3129import java .lang .reflect .Array ;
3230import java .lang .reflect .Field ;
3331import java .util .List ;
@@ -68,7 +66,7 @@ private static Object readFieldValue(final Object obj, final MappedFieldRecord r
6866 private static void assertFieldArray (final Field field ) {
6967 if (!field .getType ().isArray ()) {
7068 throw new IllegalArgumentException (
71- "Detected non-array field marked to be written as an array [" + field + ']' );
69+ "Detected non-array field marked to be written as an array [" + field + ']' );
7270 }
7371 }
7472
@@ -83,35 +81,81 @@ private static void assertFieldArray(final Field field) {
8381 * @since 2.0.2
8482 */
8583 protected void processObject (
86- final Object obj ,
87- final Field field ,
88- final BinAnnotationWrapper binAnnotationWrapper ,
89- final Object customFieldProcessor
84+ final Object obj ,
85+ final Field field ,
86+ final BinAnnotationWrapper binAnnotationWrapper ,
87+ final Object customFieldProcessor
88+ ) {
89+ this .processObject (obj , field , binAnnotationWrapper , null , customFieldProcessor );
90+ }
91+
92+ /**
93+ * Process an object. It works only with classes and fields marked by Bin annotations. <b>It doesn't process classes and fields marked by DslBinCustom annotations.</b>
94+ *
95+ * @param obj an object which is an instance of a mapped class, must not be null
96+ * @param field a field where the object has been found, it can be null for first call
97+ * @param binAnnotationWrapper wrapper to replace Bin annotation values for processing fields, can be null to be ignored
98+ * @param binFieldFilter filter for mapped fields, alows to exclude some of them, can be null
99+ * @param customFieldProcessor a processor for custom fields, it can be null
100+ * @see Bin
101+ * @since 2.0.4
102+ */
103+ protected void processObject (
104+ final Object obj ,
105+ final Field field ,
106+ final BinAnnotationWrapper binAnnotationWrapper ,
107+ final BinFieldFilter binFieldFilter ,
108+ final Object customFieldProcessor
90109 ) {
91110 JBBPUtils .assertNotNull (obj , "Object must not be null" );
92111
93- final List <MappedFieldRecord > orderedFields = JBBPMapper .findAffectedFields (obj );
112+ final List <MappedFieldRecord > orderedFields = JBBPMapper .findAffectedFields (obj , binFieldFilter );
94113
95114 final Bin clazzAnno = obj .getClass ().getAnnotation (Bin .class );
96115 final Bin fieldAnno = field == null ? null : field .getAnnotation (Bin .class );
97116
98- this . onStructStart ( obj , field , clazzAnno == null ? fieldAnno : clazzAnno ) ;
117+ final Bin binAnno = clazzAnno == null ? fieldAnno : clazzAnno ;
99118
100- for (final MappedFieldRecord rec : orderedFields ) {
101- final Bin binAnno = binAnnotationWrapper == null ? rec .binAnnotation :
102- binAnnotationWrapper .setWrapped (rec .binAnnotation );
119+ if (binFieldFilter == null || binFieldFilter .isAllowed (binAnno , field )) {
120+ this .onStructStart (obj , field , binAnno );
103121
104- if (binAnno .custom () && customFieldProcessor == null ) {
105- throw new JBBPIllegalArgumentException (
106- "Class '" + obj .getClass ().getName () + "' contains field '" +
107- rec .mappingField .getName () +
108- "' which is custom one, you must provide JBBPCustomFieldWriter instance to save it." );
122+ for (final MappedFieldRecord rec : orderedFields ) {
123+ final Bin annotation = binAnnotationWrapper == null ? rec .binAnnotation :
124+ binAnnotationWrapper .setWrapped (rec .binAnnotation );
125+
126+ if (binFieldFilter == null || binFieldFilter .isAllowed (annotation , rec .mappingField )) {
127+ if (annotation .custom () && customFieldProcessor == null ) {
128+ throw new JBBPIllegalArgumentException (
129+ "Class '" + obj .getClass ().getName () + "' contains field '" +
130+ rec .mappingField .getName () +
131+ "' which is custom one, you must provide JBBPCustomFieldWriter instance to save it." );
132+ }
133+ processObjectField (obj , rec , annotation , customFieldProcessor , binFieldFilter );
134+ }
109135 }
110136
111- processObjectField (obj , rec , binAnno , customFieldProcessor );
137+ this . onStructEnd (obj , field , binAnno );
112138 }
139+ }
113140
114- this .onStructEnd (obj , field , clazzAnno == null ? fieldAnno : clazzAnno );
141+ /**
142+ * Inside auxiliary method to process a field of an object.
143+ *
144+ * @param obj the object which field under processing, must not be null
145+ * @param fieldRecord internal record about the field, must not be null
146+ * @param annotation the annotation to be used as data source about the field,
147+ * must not be null
148+ * @param customFieldProcessor an object which will be provided for processing
149+ * of custom fields, must not be null if object contains custom fields
150+ * @since 2.0.4
151+ */
152+ protected void processObjectField (
153+ final Object obj ,
154+ final MappedFieldRecord fieldRecord ,
155+ final Bin annotation ,
156+ final Object customFieldProcessor
157+ ) {
158+ this .processObjectField (obj , fieldRecord , annotation , customFieldProcessor , null );
115159 }
116160
117161 /**
@@ -123,23 +167,26 @@ protected void processObject(
123167 * must not be null
124168 * @param customFieldProcessor an object which will be provided for processing
125169 * of custom fields, must not be null if object contains custom fields
126- * @since 2.0.2
170+ * @param binFieldFilter filter allows to exclude some fields from process, can be null
171+ * @since 2.0.4
127172 */
128173 protected void processObjectField (
129- final Object obj ,
130- final MappedFieldRecord fieldRecord ,
131- final Bin annotation ,
132- final Object customFieldProcessor
174+ final Object obj ,
175+ final MappedFieldRecord fieldRecord ,
176+ final Bin annotation ,
177+ final Object customFieldProcessor ,
178+ final BinFieldFilter binFieldFilter
133179 ) {
134180 final Field field = fieldRecord .mappingField ;
135181
136182 if (annotation .custom ()) {
137183 this .onFieldCustom (obj , field , annotation , customFieldProcessor ,
138- readFieldValue (obj , fieldRecord ));
184+ readFieldValue (obj , fieldRecord ));
139185 } else {
140186 final Class <?> fieldType = field .getType ();
141187 final BinAnnotationWrapper wrapper =
142- annotation instanceof BinAnnotationWrapper ? (BinAnnotationWrapper ) annotation : null ;
188+ annotation instanceof BinAnnotationWrapper ? (BinAnnotationWrapper ) annotation : null ;
189+
143190 final BinType type ;
144191 if (annotation .type () == BinType .UNDEFINED ) {
145192 type = BinType .findCompatible (fieldType );
@@ -154,7 +201,7 @@ protected void processObjectField(
154201 final JBBPBitNumber bitNumber = annotation .bitNumber ();
155202 if (fieldType == boolean .class ) {
156203 this .onFieldBits (obj , field , annotation , bitNumber ,
157- ((Boolean ) readFieldValue (obj , fieldRecord )) ? 0xFF : 0x00 );
204+ ((Boolean ) readFieldValue (obj , fieldRecord )) ? 0xFF : 0x00 );
158205 } else {
159206 byte value = ((Number ) readFieldValue (obj , fieldRecord )).byteValue ();
160207 if (reverseBits ) {
@@ -169,7 +216,7 @@ protected void processObjectField(
169216 onFieldBool (obj , field , annotation , (Boolean ) readFieldValue (obj , fieldRecord ));
170217 } else {
171218 onFieldBool (obj , field , annotation ,
172- ((Number ) readFieldValue (obj , fieldRecord )).longValue () != 0 );
219+ ((Number ) readFieldValue (obj , fieldRecord )).longValue () != 0 );
173220 }
174221 }
175222 break ;
@@ -214,7 +261,7 @@ protected void processObjectField(
214261 }
215262 if (reverseBits ) {
216263 value =
217- Float .intBitsToFloat ((int ) JBBPFieldInt .reverseBits (Float .floatToIntBits (value )));
264+ Float .intBitsToFloat ((int ) JBBPFieldInt .reverseBits (Float .floatToIntBits (value )));
218265 }
219266 this .onFieldFloat (obj , field , annotation , value );
220267 }
@@ -253,13 +300,13 @@ protected void processObjectField(
253300
254301 if (reverseBits ) {
255302 value =
256- Double .longBitsToDouble (JBBPFieldLong .reverseBits (Double .doubleToLongBits (value )));
303+ Double .longBitsToDouble (JBBPFieldLong .reverseBits (Double .doubleToLongBits (value )));
257304 }
258305 this .onFieldDouble (obj , field , annotation , value );
259306 }
260307 break ;
261308 case STRUCT : {
262- processObject (readFieldValue (obj , fieldRecord ), field , wrapper , customFieldProcessor );
309+ processObject (readFieldValue (obj , fieldRecord ), field , wrapper , binFieldFilter , customFieldProcessor );
263310 }
264311 break ;
265312 default : {
@@ -276,7 +323,7 @@ protected void processObjectField(
276323 if (fieldType .getComponentType () == boolean .class ) {
277324 for (int i = 0 ; i < len ; i ++) {
278325 this .onFieldBits (obj , field , annotation , bitNumber ,
279- (Boolean ) Array .get (array , i ) ? 0xFF : 0x00 );
326+ (Boolean ) Array .get (array , i ) ? 0xFF : 0x00 );
280327 }
281328 } else {
282329 for (int i = 0 ; i < len ; i ++) {
@@ -386,7 +433,7 @@ protected void processObjectField(
386433 float value = Array .getFloat (array , i );
387434 if (reverseBits ) {
388435 value = Float
389- .intBitsToFloat ((int ) JBBPFieldInt .reverseBits (Float .floatToIntBits (value )));
436+ .intBitsToFloat ((int ) JBBPFieldInt .reverseBits (Float .floatToIntBits (value )));
390437 }
391438 this .onFieldFloat (obj , field , annotation , value );
392439 }
@@ -445,7 +492,7 @@ protected void processObjectField(
445492 double value = ((Number ) Array .get (array , i )).doubleValue ();
446493 if (reverseBits ) {
447494 value = Double
448- .longBitsToDouble (JBBPFieldLong .reverseBits (Double .doubleToLongBits (value )));
495+ .longBitsToDouble (JBBPFieldLong .reverseBits (Double .doubleToLongBits (value )));
449496 }
450497 this .onFieldDouble (obj , field , annotation , value );
451498 }
@@ -457,14 +504,14 @@ protected void processObjectField(
457504 final int len = Array .getLength (array );
458505 this .onArrayStart (obj , field , annotation , len );
459506 for (int i = 0 ; i < len ; i ++) {
460- this .processObject (Array .get (array , i ), field , wrapper , customFieldProcessor );
507+ this .processObject (Array .get (array , i ), field , wrapper , binFieldFilter , customFieldProcessor );
461508 }
462509 this .onArrayEnd (obj , field , annotation );
463510 }
464511 break ;
465512 default : {
466513 throw new Error (
467- "Unexpected situation for field type, contact developer [" + type + ']' );
514+ "Unexpected situation for field type, contact developer [" + type + ']' );
468515 }
469516 }
470517 }
0 commit comments