docs: Object toMongoObject(final Object javaObj, final boolean includeClassName) {
          if (javaObj == null) {
              return null;
          }
          Class origClass = javaObj.getClass();
  
          if (origClass.isAnonymousClass() && origClass.getSuperclass().isEnum()) {
              origClass = origClass.getSuperclass();
          }
  
          final Object newObj = getConverters().encode(origClass, javaObj);
          if (newObj == null) {
              LOG.warn("converted " + javaObj + " to null");
              return null;
          }
          final Class type = newObj.getClass();
          final boolean bSameType = origClass.equals(type);
  
          //TODO: think about this logic a bit more.
          //Even if the converter changed it, should it still be processed?
          if (!bSameType && !(Map.class.isAssignableFrom(type) || Iterable.class.isAssignableFrom(type))) {
              return newObj;
          } else { //The converter ran, and produced another type, or it is a list/map
  
              boolean isSingleValue = true;
              boolean isMap = false;
              Class subType = null;
  
              if (type.isArray() || Map.class.isAssignableFrom(type) || Iterable.class.isAssignableFrom(type)) {
                  isSingleValue = false;
                  isMap = implementsInterface(type, Map.class);
                  // subtype of Long[], List<Long> is Long
                  subType = (type.isArray()) ? type.getComponentType() : getParameterizedClass(type, (isMap) ? 1 : 0);
              }
  
              if (isSingleValue && !isPropertyType(type)) {
                  final DBObject dbObj = toDBObject(newObj);
                  if (!includeClassName) {
                      dbObj.removeField(opts.getDiscriminatorField());
                  }
                  return dbObj;
              } else if (newObj instanceof DBObject) {
                  return newObj;
              } else if (isMap) {
                  if (isPropertyType(subType)) {
                      return toDBObject(newObj);
                  } else {
                      final LinkedHashMap m = new LinkedHashMap();
                      for (final Map.Entry e : (Iterable<Map.Entry>) ((Map) newObj).entrySet()) {
                          m.put(e.getKey(), toMongoObject(e.getValue(), includeClassName));
                      }
  
                      return m;
                  }
                  //Set/List but needs elements converted
              } else if (!isSingleValue && !isPropertyType(subType)) {
                  final List<Object> values = new BasicDBList();
                  if (type.isArray()) {
                      for (final Object obj : (Object[]) newObj) {
                          values.add(toMongoObject(obj, includeClassName));
                      }
                  } else {
                      for (final Object obj : (Iterable) newObj) {
                          values.add(toMongoObject(obj, includeClassName));
                      }
                  }
  
                  return values;
              } else {
                  return newObj;
              }
          }
      }