default PathFilter searchForRegisterContainer(int frameLevel, KeyPath path) {
		KeyPath simple = searchForSuitable(TraceObjectRegisterContainer.class, path);
		if (simple != null) {
			return PathFilter.pattern(simple);
		}
		KeyPath stackPath = searchForSuitable(TraceObjectStack.class, path);
		if (stackPath == null) {
			return PathFilter.NONE;
		}
		PathPattern framePatternRelStack =
			getSuccessorSchema(stackPath).searchFor(TraceObjectStackFrame.class, false)
					.getSingletonPattern();
		if (framePatternRelStack == null) {
			return PathFilter.NONE;
		}

		if (framePatternRelStack.countWildcards() != 1) {
			return null;
		}

		Set<PathPattern> patterns = new HashSet<>();
		for (String index : List.of(Integer.toString(frameLevel),
			"0x" + Integer.toHexString(frameLevel))) {
			KeyPath framePathRelStack =
				framePatternRelStack.applyKeys(index).getSingletonPath();
			KeyPath framePath = stackPath.extend(framePathRelStack);
			KeyPath regsPath = searchForSuitable(TraceObjectRegisterContainer.class, framePath);
			if (regsPath != null) {
				patterns.add(new PathPattern(regsPath));
			}
		}
		return PathMatcher.any(patterns.stream());
	}
Search for a suitable register container

<p>
This will try with and without considerations for frames. If the schema indicates that
register containers are not contained within frames, then frameLevel must be 0, otherwise
this will return empty. If dependent on frameLevel, this will return two singleton paths: one
for a decimal index and another for a hexadecimal index. If not, this will return a singleton
path. If it fails to find a unique container, this will return empty.

<p>
<b>NOTE:</b> This must be used at the top of the search scope, probably the root schema. For
example, to search the entire model for a register container related to {@code myObject}:

<pre>
for (PathPattern regPattern : myObject.getModel()
		.getSchema()
		.searchForRegisterContainer(0, myObject.getPath())) {
	TargetObject objRegs = myObject.getModel().getModelObject(regPattern.getSingletonPath());
	if (objRegs != null) {
		// found it
	}
}
</pre>

<p>
This places some conventional restrictions / expectations on models where registers are given
on a frame-by-frame basis. The schema should present the {@link TraceObjectRegisterContainer}
as the same object or a successor to {@link TraceObjectStackFrame}, which must in turn be a
successor to {@link TraceObjectStack}. The frame level (an index) must be in the path from
stack to frame. There can be no wildcards between the frame and the register container. For
example, the container for {@code Threads[1]} may be {@code Threads[1].Stack[n].Registers},
where {@code n} is the frame level. {@code Threads[1].Stack} would have the
{@link TraceObjectStack} interface, {@code Threads[1].Stack[0]} would have the
{@link TraceObjectStackFrame} interface, and {@code Threads[1].Stack[0].Registers} would have
the {@link TraceObjectRegisterContainer} interface. Note it is not sufficient for
{@link TraceObjectRegisterContainer} to be a successor of {@link TraceObjectStack} with a
single index between. There <em>must</em> be an intervening {@link TraceObjectStackFrame},
and the frame level (index) must precede it.

@param frameLevel the frame level. May be ignored if not applicable
@param path the path of the seed object relative to the root
@return the filter where the register container should be found, possibly
        {@link PathFilter#NONE}
Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/TraceObjectSchema.java