default void validateTypeAndInterfaces(Object value, KeyPath parentPath, String key,
			boolean strict) {
		Class<?> cls = value.getClass();
		if (!getType().isAssignableFrom(cls)) {
			String path = key == null ? null : parentPath.key(key).toString();
			String msg = path == null
					? "Value " + value + " does not conform to required type " + getType() +
						" of schema " + this
					: "Value " + value + " for " + path + " does not conform to required type " +
						getType() + " of schema " + this;
			Msg.error(this, msg);
			if (strict) {
				throw new AssertionError(msg);
			}
		}
		for (Class<? extends TraceObjectInterface> iface : getInterfaces()) {
			if (!iface.isAssignableFrom(cls)) {
				// TODO: Should this throw an exception, eventually?
				String msg = "Value " + value + " does not implement required interface " + iface +
					" of schema " + this;
				Msg.error(this, msg);
				if (strict) {
					throw new AssertionError(msg);
				}
			}
		}
	}
Verify that the given value is of this schema's required type and, if applicable, implements
the required interfaces

@param value the value being assigned to the key
@param parentPath the path of the object whose key is being assigned, for diagnostics
@param key the key that is being assigned
@param strict true to throw an exception upon violation; false to just log and continue
Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/target/schema/TraceObjectSchema.java