@@ -76,6 +76,78 @@ public void setName(String name) {
7676 }
7777 }
7878
79+ // Another concrete implementation
80+ public static class Cat implements Animal {
81+ private String id ;
82+ private String name ;
83+
84+ public Cat () {}
85+
86+ public Cat (String id , String name ) {
87+ this .id = id ;
88+ this .name = name ;
89+ }
90+
91+ @ Override
92+ public String getId () {
93+ return id ;
94+ }
95+
96+ public void setId (String id ) {
97+ this .id = id ;
98+ }
99+
100+ @ Override
101+ public String getName () {
102+ return name ;
103+ }
104+
105+ public void setName (String name ) {
106+ this .name = name ;
107+ }
108+ }
109+
110+ // Third concrete implementation with boolean property
111+ public static class Bird implements Animal {
112+ private String id ;
113+ private String name ;
114+ private boolean canFly ;
115+
116+ public Bird () {}
117+
118+ public Bird (String id , String name , boolean canFly ) {
119+ this .id = id ;
120+ this .name = name ;
121+ this .canFly = canFly ;
122+ }
123+
124+ @ Override
125+ public String getId () {
126+ return id ;
127+ }
128+
129+ public void setId (String id ) {
130+ this .id = id ;
131+ }
132+
133+ @ Override
134+ public String getName () {
135+ return name ;
136+ }
137+
138+ public void setName (String name ) {
139+ this .name = name ;
140+ }
141+
142+ public boolean isCanFly () {
143+ return canFly ;
144+ }
145+
146+ public void setCanFly (boolean canFly ) {
147+ this .canFly = canFly ;
148+ }
149+ }
150+
79151 // EntityDecorator for the interface
80152 public static class AnimalDecorator implements EntityDecorator <Animal > {
81153
@@ -155,4 +227,120 @@ public void testCreateIdIndexWithInterface() {
155227
156228 assertTrue (collection .hasIndex ("id" ));
157229 }
230+
231+ @ Test
232+ public void testMultipleImplementationsFieldAccess () throws IllegalAccessException {
233+ scanner .readEntity ();
234+ ObjectIdField idField = scanner .getObjectIdField ();
235+ assertNotNull (idField );
236+
237+ // Test with Dog instance
238+ Dog dog = new Dog ("dog-1" , "Buddy" );
239+ Object dogId = FieldAccessHelper .get (idField .getField (), dog );
240+ assertEquals ("dog-1" , dogId );
241+
242+ FieldAccessHelper .set (idField .getField (), dog , "dog-2" );
243+ assertEquals ("dog-2" , dog .getId ());
244+
245+ // Test with Cat instance
246+ Cat cat = new Cat ("cat-1" , "Whiskers" );
247+ Object catId = FieldAccessHelper .get (idField .getField (), cat );
248+ assertEquals ("cat-1" , catId );
249+
250+ FieldAccessHelper .set (idField .getField (), cat , "cat-2" );
251+ assertEquals ("cat-2" , cat .getId ());
252+
253+ // Test with Bird instance
254+ Bird bird = new Bird ("bird-1" , "Tweety" , true );
255+ Object birdId = FieldAccessHelper .get (idField .getField (), bird );
256+ assertEquals ("bird-1" , birdId );
257+
258+ FieldAccessHelper .set (idField .getField (), bird , "bird-2" );
259+ assertEquals ("bird-2" , bird .getId ());
260+ }
261+
262+ @ Test
263+ public void testEdgeCaseEmptyPropertyName () {
264+ // This tests that our validation works
265+ scanner .readEntity ();
266+ ObjectIdField idField = scanner .getObjectIdField ();
267+
268+ Dog dog = new Dog ("test" , "TestDog" );
269+
270+ try {
271+ // Directly test the helper with an empty property name
272+ // This should fail gracefully
273+ java .lang .reflect .Field testField = InterfacePropertyHolder .class .getDeclaredField ("property" );
274+ InterfacePropertyHolder .registerProperty (testField , "" , null );
275+ FieldAccessHelper .get (testField , dog );
276+ fail ("Should have thrown IllegalAccessException for empty property name" );
277+ } catch (IllegalAccessException e ) {
278+ assertTrue (e .getMessage ().contains ("Property name cannot be null or empty" ));
279+ } catch (Exception e ) {
280+ // Expected - field access may fail in different ways
281+ }
282+ }
283+
284+ @ Test
285+ public void testEdgeCaseNullPropertyName () {
286+ scanner .readEntity ();
287+ Dog dog = new Dog ("test" , "TestDog" );
288+
289+ try {
290+ // Directly test the helper with a null property name
291+ java .lang .reflect .Field testField = InterfacePropertyHolder .class .getDeclaredField ("property" );
292+ InterfacePropertyHolder .registerProperty (testField , null , null );
293+ FieldAccessHelper .get (testField , dog );
294+ fail ("Should have thrown IllegalAccessException for null property name" );
295+ } catch (IllegalAccessException e ) {
296+ assertTrue (e .getMessage ().contains ("Property name cannot be null or empty" ));
297+ } catch (Exception e ) {
298+ // Expected - field access may fail in different ways
299+ }
300+ }
301+
302+ @ Test
303+ public void testBooleanPropertyWithIsPrefix () throws IllegalAccessException {
304+ scanner .readEntity ();
305+
306+ Bird bird = new Bird ("bird-1" , "Tweety" , true );
307+
308+ // Create a synthetic field for a boolean property
309+ try {
310+ java .lang .reflect .Method isMethod = Bird .class .getMethod ("isCanFly" );
311+ java .lang .reflect .Field syntheticField = InterfacePropertyHolder .class .getDeclaredField ("property" );
312+ InterfacePropertyHolder .registerProperty (syntheticField , "canFly" , isMethod );
313+
314+ // Test getting boolean property via 'is' prefix
315+ Object value = FieldAccessHelper .get (syntheticField , bird );
316+ assertEquals (true , value );
317+
318+ // Test setting boolean property
319+ FieldAccessHelper .set (syntheticField , bird , false );
320+ assertEquals (false , bird .isCanFly ());
321+ } catch (Exception e ) {
322+ fail ("Should be able to access boolean property with 'is' prefix: " + e .getMessage ());
323+ }
324+ }
325+
326+ @ Test
327+ public void testMultipleClassesWithSameInterface () {
328+ // Verify that the scanner can handle multiple different implementations
329+ scanner .readEntity ();
330+ ObjectIdField idField = scanner .getObjectIdField ();
331+ assertNotNull (idField );
332+
333+ // All three implementations should work with the same scanner
334+ Dog dog = new Dog ("1" , "Dog" );
335+ Cat cat = new Cat ("2" , "Cat" );
336+ Bird bird = new Bird ("3" , "Bird" , true );
337+
338+ try {
339+ assertEquals ("1" , FieldAccessHelper .get (idField .getField (), dog ));
340+ assertEquals ("2" , FieldAccessHelper .get (idField .getField (), cat ));
341+ assertEquals ("3" , FieldAccessHelper .get (idField .getField (), bird ));
342+ } catch (IllegalAccessException e ) {
343+ fail ("Should be able to access id field on all implementations: " + e .getMessage ());
344+ }
345+ }
158346}
0 commit comments