private static void searchFor(TraceObjectSchema sch, Set<PathPattern> patterns,
				KeyPath prefix, boolean parentIsCanonical,
				Class<? extends TraceObjectInterface> type,
				boolean requireAggregate, boolean requireCanonical,
				Set<TraceObjectSchema> visited) {
			if (sch instanceof PrimitiveTraceObjectSchema) {
				return;
			}
			if (sch.getInterfaces().contains(type) && (parentIsCanonical || !requireCanonical)) {
				patterns.add(new PathPattern(prefix));
				return;
			}
			if (!visited.add(sch)) {
				return;
			}
			if (requireAggregate && !sch.getInterfaces().contains(TraceObjectAggregate.class)) {
				return;
			}
			SchemaContext ctx = sch.getContext();
			boolean isCanonical = sch.isCanonicalContainer();
			for (Entry<String, SchemaName> ent : sch.getElementSchemas().entrySet()) {
				KeyPath extended = prefix.index(ent.getKey());
				TraceObjectSchema elemSchema = ctx.getSchema(ent.getValue());
				searchFor(elemSchema, patterns, extended, isCanonical, type, requireAggregate,
					requireCanonical, visited);
			}
			KeyPath deExtended = prefix.key("[]");
			TraceObjectSchema deSchema = ctx.getSchema(sch.getDefaultElementSchema());
			searchFor(deSchema, patterns, deExtended, isCanonical, type, requireAggregate,
				requireCanonical, visited);

			for (Entry<String, AttributeSchema> ent : sch.getAttributeSchemas().entrySet()) {
				KeyPath extended = prefix.key(ent.getKey());
				TraceObjectSchema attrSchema = ctx.getSchema(ent.getValue().getSchema());
				searchFor(attrSchema, patterns, extended, isCanonical, type, requireAggregate,
					requireCanonical, visited);
			}
			KeyPath daExtended = prefix.key("");
			TraceObjectSchema daSchema =
				ctx.getSchema(sch.getDefaultAttributeSchema().getSchema());
			searchFor(daSchema, patterns, daExtended, isCanonical, type, requireAggregate,
				requireCanonical, visited);

			visited.remove(sch);
		}
Find (sub) path patterns that match objects implementing a given interface

<p>
Each returned path pattern accepts relative paths from an object having this schema to a
successor implementing the interface.

@param type the sub-type of {@link TraceObjectInterface} to search for
@param prefix the prefix for each relative path pattern
@param requireCanonical only return patterns matching a canonical location for the type
@return a set of patterns where such objects could be found
Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/TraceObjectSchema.java