@Nonnull
	public String getCommon(@Nonnull String first, @Nonnull String second) {
		// Full upwards hierarchy for the first
		InheritanceVertex vertex = getVertex(first);
		if (vertex == null || OBJECT.equals(first) || OBJECT.equals(second))
			return OBJECT;

		Set<String> firstParents = vertex.allParents()
				.map(InheritanceVertex::getName)
				.collect(Collectors.toCollection(LinkedHashSet::new));
		firstParents.add(first);

		// Ensure 'Object' is last
		firstParents.remove(OBJECT);
		firstParents.add(OBJECT);

		// Base case
		if (firstParents.contains(second))
			return second;

		// Iterate over second's parents via breadth-first-search
		Queue<String> queue = new LinkedList<>();
		queue.add(second);
		do {
			// Item to fetch parents of
			String next = queue.poll();
			if (next == null || next.equals(OBJECT))
				break;

			InheritanceVertex nextVertex = getVertex(next);
			if (nextVertex == null)
				break;

			for (String parent : nextVertex.getParents().stream()
					.map(InheritanceVertex::getName).toList()) {
				if (!parent.equals(OBJECT)) {
					// Parent in the set of visited classes? Then its valid.
					if (firstParents.contains(parent))
						return parent;
					// Queue up the parent
					queue.add(parent);
				}
			}
		} while (!queue.isEmpty());
		// Fallback option
		return OBJECT;
	}
@Test
	void getCommon() {
		String edibleName = Inheritance.Edible.class.getName().replace('.', '/');
		String appleName = Inheritance.Apple.class.getName().replace('.', '/');
		String grapeName = Inheritance.Grape.class.getName().replace('.', '/');

		// Compare obvious case --> edible
		String commonType = graph.getCommon(appleName, grapeName);
		assertEquals(edibleName, commonType, "Common type of Apple/Grape should be Edible");

		// Compare with bogus --> object
		commonType = graph.getCommon(appleName, UUID.randomUUID().toString());
		assertEquals(Types.OBJECT_TYPE.getInternalName(), commonType,
				"Common type of two unrelated classes should be Object");
	}