public void add(
     Class definedIn,
     String fieldName,
     String itemFieldName,
     Class itemType,
     String keyFieldName) {
   Field field = null;
   Class declaredIn = definedIn;
   while (declaredIn != Object.class) {
     try {
       field = declaredIn.getDeclaredField(fieldName);
       break;
     } catch (SecurityException e) {
       throw new InitializationException("Access denied for field with implicit collection", e);
     } catch (NoSuchFieldException e) {
       declaredIn = declaredIn.getSuperclass();
     }
   }
   if (field == null) {
     throw new InitializationException("No field \"" + fieldName + "\" for implicit collection");
   } else if (Map.class.isAssignableFrom(field.getType())) {
     if (itemFieldName == null && keyFieldName == null) {
       itemType = Map.Entry.class;
     }
   } else if (!Collection.class.isAssignableFrom(field.getType())) {
     Class fieldType = field.getType();
     if (!fieldType.isArray()) {
       throw new InitializationException(
           "Field \"" + fieldName + "\" declares no collection or array");
     } else {
       Class componentType = fieldType.getComponentType();
       componentType = componentType.isPrimitive() ? Primitives.box(componentType) : componentType;
       if (itemType == null) {
         itemType = componentType;
       } else {
         itemType = itemType.isPrimitive() ? Primitives.box(itemType) : itemType;
         if (!componentType.isAssignableFrom(itemType)) {
           throw new InitializationException(
               "Field \""
                   + fieldName
                   + "\" declares an array, but the array type is not compatible with "
                   + itemType.getName());
         }
       }
     }
   }
   ImplicitCollectionMapperForClass mapper = getOrCreateMapper(definedIn);
   mapper.add(new ImplicitCollectionMappingImpl(fieldName, itemType, itemFieldName, keyFieldName));
 }