private Class deriveClass1(String path, String lastPathPart, boolean array) {
        Class containerClass;

        if (path.equals(lastPathPart)) {
            containerClass = rootClass;
        } else {
            containerClass = classCache.get(rootClass.getSimpleName() + "." + path.substring(0, path.lastIndexOf('.')));
        }

        if (containerClass != null && DBObject.class.isAssignableFrom(containerClass)) {
            try {
                Method m = containerClass.getMethod("__getPreEnhancedClass");

                containerClass = (Class) m.invoke(null);
            } catch (Exception e) {
                logger.warn("DBObject without __getPreEnhancedClass() method.  Was the container class enhanced?");
            }
        }

        // If we don't have a container class at this point, we are in a part of the result document that
        // does not correspond to the object model.  Return a basic MongoDB object.
        if (containerClass == null) {
            return array ? BasicDBList.class : BasicDBObject.class;
        }

        Method getter;

        try {
            // noinspection ConstantConditions
            getter = containerClass.getMethod("get" + Character.toUpperCase(lastPathPart.charAt(0)) + lastPathPart.substring(1));
        } catch (NoSuchMethodException e) {
            if (!EXPLAIN_PATHS_TO_IGNORE.contains(lastPathPart) && !lastPathPart.startsWith("__")) {
                logger.warn("No getter for: {} ({})", lastPathPart, e.getMessage());
            }

            return array ? BasicDBList.class : BasicDBObject.class;
        }

        Type returnType = getter.getGenericReturnType();
        String qualifiedPath = rootClass.getSimpleName() + "." + path;

        if (Class.class.isAssignableFrom(returnType.getClass())) {
            // noinspection unchecked
            Class enhancedClass = EnhancerHelper.getDirtyableDBObjectEnhancer((Class) returnType).getEnhancedClass();

            classCache.put(qualifiedPath, enhancedClass);

            return enhancedClass;
        } else if (ParameterizedType.class.isAssignableFrom(returnType.getClass())) {
            ParameterizedType parameterizedType = (ParameterizedType) returnType;
            Class rawType = (Class) parameterizedType.getRawType();
            Class rawClass;
            Class enhancedClass;

            if (Map.class.isAssignableFrom(rawType)) {
                rawClass = (Class) parameterizedType.getActualTypeArguments()[1];
            } else if (Iterable.class.isAssignableFrom(rawType)) {
                rawClass = (Class) parameterizedType.getActualTypeArguments()[0];
            } else {
                throw new RuntimeException("unknown type: " + rawType);
            }

            classCache.put(qualifiedPath, rawType);

            if (!DBObjectUtil.needsNoConversion(rawClass)) {
                //noinspection unchecked
                enhancedClass = EnhancerHelper.getDirtyableDBObjectEnhancer(rawClass).getEnhancedClass();

                classCache.put(qualifiedPath + ".", enhancedClass);
            }

            return rawType;
        } else {
            throw new RuntimeException("Don't know how to handle: " + qualifiedPath);
        }
    }
private Class deriveClass1 ( String path , String lastPathPart , boolean array ) { Class containerClass ; if ( path . equals ( lastPathPart ) ) { containerClass = rootClass ; } else { containerClass = classCache . get ( rootClass . getSimpleName ( ) + "." + path . substring ( 0 , path . lastIndexOf ( '.' ) ) ) ; } if ( containerClass != null && DBObject . class . isAssignableFrom ( containerClass ) ) { try { Method m = containerClass . getMethod ( "__getPreEnhancedClass" ) ; containerClass = ( Class ) m . invoke ( null ) ; } catch ( Exception e ) { logger . warn ( "DBObject without __getPreEnhancedClass() method.  Was the container class enhanced?" ) ; } } if ( containerClass == null ) { return array ? BasicDBList . class : BasicDBObject . class ; } Method getter ; try { getter = containerClass . getMethod ( "get" + Character . toUpperCase ( lastPathPart . charAt ( 0 ) ) + lastPathPart . substring ( 1 ) ) ; } catch ( NoSuchMethodException e ) { if ( ! EXPLAIN_PATHS_TO_IGNORE . contains ( lastPathPart ) && ! lastPathPart . startsWith ( "__" ) ) { logger . warn ( "No getter for: {} ({})" , lastPathPart , e . getMessage ( ) ) ; } return array ? BasicDBList . class : BasicDBObject . class ; } Type returnType = getter . getGenericReturnType ( ) ; String qualifiedPath = rootClass . getSimpleName ( ) + "." + path ; if ( Class . class . isAssignableFrom ( returnType . getClass ( ) ) ) { Class enhancedClass = EnhancerHelper . getDirtyableDBObjectEnhancer ( ( Class ) returnType ) . getEnhancedClass ( ) ; classCache . put ( qualifiedPath , enhancedClass ) ; return enhancedClass ; } else if ( ParameterizedType . class . isAssignableFrom ( returnType . getClass ( ) ) ) { ParameterizedType parameterizedType = ( ParameterizedType ) returnType ; Class rawType = ( Class ) parameterizedType . getRawType ( ) ; Class rawClass ; Class enhancedClass ; if ( Map . class . isAssignableFrom ( rawType ) ) { rawClass = ( Class ) parameterizedType . getActualTypeArguments ( ) [ 1 ] ; } else if ( Iterable . class . isAssignableFrom ( rawType ) ) { rawClass = ( Class ) parameterizedType . getActualTypeArguments ( ) [ 0 ] ; } else { throw new RuntimeException ( "unknown type: " + rawType ) ; } classCache . put ( qualifiedPath , rawType ) ; if ( ! DBObjectUtil . needsNoConversion ( rawClass ) ) { enhancedClass = EnhancerHelper . getDirtyableDBObjectEnhancer ( rawClass ) . getEnhancedClass ( ) ; classCache . put ( qualifiedPath + "." , enhancedClass ) ; } return rawType ; } else { throw new RuntimeException ( "Don't know how to handle: " + qualifiedPath ) ; } }
/* tests:
names at different depths
maps w/ other objects as keys

""
relatedMongoObjectMap                                    relatedMongoObjectMap       Map<>
relatedMongoObjectMap.foo                                relatedMongoObjectMap.      RelatedObject
nestedSimpleMongoObject                                  nestedSimpleMongoObject     SimpleObject
nestedSimpleMongoObject.relatedMongoObjectMap            nestedSimpleMongoObject.relatedObjectMap    Map<>
nestedSimpleMongoObject.relatedMongoObjectMap.bar        nestedSimpleMongoObject.relatedObjectMap.   RelatedObject