@Nonnull
	public Mappings generate(@Nullable Workspace workspace,
	                         @Nonnull WorkspaceResource resource,
	                         @Nonnull InheritanceGraph inheritanceGraph,
	                         @Nonnull NameGenerator generator,
	                         @Nullable NameGeneratorFilter filter) {
		// Adapt filter to handle baseline cases.
		filter = new ExcludeEnumMethodsFilter(filter);

		// Setup adapter to store our mappings in.
		MappingsAdapter mappings = new MappingsAdapter(true, true);
		mappings.enableHierarchyLookup(inheritanceGraph);
		if (workspace != null)
			mappings.enableClassLookup(workspace);
		SortedMap<String, ClassInfo> classMap = new TreeMap<>();
		resource.versionedJvmClassBundleStream()
				.flatMap(Bundle::stream)
				.forEach(c -> classMap.put(c.getName(), c));
		classMap.putAll(resource.getJvmClassBundle());

		// Pull a class, create mappings for its inheritance family, then remove those classes from the map.
		// When the map is empty everything has been run through the mapping generation process.
		while (!classMap.isEmpty()) {
			// Get family from the class.
			String className = classMap.firstKey();
			Set<InheritanceVertex> family = inheritanceGraph.getVertexFamily(className, false);

			// Create mappings for the family
			generateFamilyMappings(mappings, family, generator, filter);

			// Remove all family members from the class map.
			if (family.isEmpty())
				classMap.remove(className);
			else
				family.forEach(vertex -> classMap.remove(vertex.getName()));
		}
		return mappings;
	}
@Test
	void testGeneral() {
		// Apply and assert no unexpected values exist
		Mappings mappings = mappingGenerator.generate(workspace, resource, inheritanceGraph, nameGenerator, null);

		// Should not generate names for internal classes
		assertNull(mappings.getMappedClassName("java/lang/Object"));
		assertNull(mappings.getMappedClassName("java/lang/enum"));

		// Should not generate names for constructors/override/library methods
		//  - but still generate names for members
		String className = AccessibleFields.class.getName().replace('.', '/');
		assertNull(mappings.getMappedMethodName(className, "hashCode", "()I"));
		assertNull(mappings.getMappedMethodName(className, "<init>>", "()V"));
		assertNotNull(mappings.getMappedFieldName(className, "CONSTANT_FIELD", "I"));
		assertNotNull(mappings.getMappedFieldName(className, "privateFinalField", "I"));
		assertNotNull(mappings.getMappedFieldName(className, "protectedField", "I"));
		assertNotNull(mappings.getMappedFieldName(className, "publicField", "I"));
		assertNotNull(mappings.getMappedFieldName(className, "packageField", "I"));
	}