Interface TraceObjectSchema
- All Known Implementing Classes:
DefaultTraceObjectSchema,PrimitiveTraceObjectSchema
TraceObject
This allows a client to inspect predictable aspects of a model before fetching any actual objects. This also helps a client understand where to listen for particular types of objects and comprehend the model's structure in general.
For a primitive type, the type is given by getType(). For TraceObjects,
supported interfaces are given by getInterfaces(). The types of children are determined
by matching on the keys (indices and names), the result being a subordinate
TraceObjectSchema. Keys must match exactly, unless the "pattern" is the empty string,
which matches any key. Similarly, the wild-card index is [].
The schema can specify attribute aliases, which implies that a particular key ("from") will always have the same value as another ("to"). As a result, the schemas of aliased keys will also implicitly match.
-
Nested Class Summary
Nested ClassesModifier and TypeInterfaceDescriptionstatic interfaceSchema descriptor for a child attribute.static enumstatic classstatic final recordAn identifier for schemas within a context. -
Method Summary
Modifier and TypeMethodDescriptiondefault StringcheckAliasedAttribute(String name) Check if the given name is an alias and get the target attribute namedefault intcomputeFrameLevel(KeyPath path) Compute the frame level of the object at the given path relative to this schemadefault PathFilterfilterForSuitable(Class<? extends TraceObjectInterface> type, KeyPath path) Search for all suitable objects with this schema at the given pathGet the map of attribute name aliasesgetAttributeSchema(String name) Get the attribute schema for a given attribute nameGet the map of attribute names to named schemasdefault TraceObjectSchemagetChildSchema(String key) Get the schema for a child having the given keydefault TraceObjectSchema.SchemaNamegetChildSchemaName(String key) Get the named schema for a child having the given keyGet the context of which this schema is a memberGet the default schema for attributesdefault TraceObjectSchema.SchemaNameGet the default schema for elementsdefault TraceObjectSchema.SchemaNamegetElementSchema(String index) Get the named schema for a given element indexGet the map of element indices to named schemasSet<Class<? extends TraceObjectInterface>> Get the minimum interfaces supported by a conforming objectgetName()Get the name of this schemadefault TraceObjectSchemagetSuccessorSchema(KeyPath path) Get the schema for a successor at the given (sub) pathdefault List<TraceObjectSchema> getSuccessorSchemas(KeyPath path) Get the list of schemas traversed from this schema along the given (sub) pathClass<?> getType()Get the Java class that best represents this type.default booleanCheck if this schema can accept a value of the given other schemabooleanCheck if this object is the canonical container for its elementsdefault booleanCheck if the given key should be hidden for an object having this schemadefault PathFiltersearchFor(Class<? extends TraceObjectInterface> type, boolean requireCanonical) Do the same assearchFor(Class, KeyPath, boolean)with an empty prefixdefault PathFiltersearchFor(Class<? extends TraceObjectInterface> type, KeyPath prefix, boolean requireCanonical) Find (sub) path patterns that match objects implementing a given interfacedefault KeyPathsearchForAncestor(Class<? extends TraceObjectInterface> type, KeyPath path) Find the nearest ancestor implementing the given interface along the given pathdefault KeyPathsearchForAncestorContainer(Class<? extends TraceObjectInterface> type, KeyPath path) Find the nearest ancestor which is the canonical container of the given interfacedefault KeyPathsearchForCanonicalContainer(Class<? extends TraceObjectInterface> type) Find the (sub) path to the canonical container for objects implementing a given interfacedefault PathFiltersearchForRegisterContainer(int frameLevel, KeyPath path) Search for a suitable register containerdefault KeyPathsearchForSuitable(TraceObjectSchema schema, KeyPath path) Search for a suitable object with this schema at the given pathdefault KeyPathsearchForSuitable(Class<? extends TraceObjectInterface> type, KeyPath path) Search for a suitable object with this schema at the given pathdefault KeyPathsearchForSuitableContainer(Class<? extends TraceObjectInterface> type, KeyPath path) LikesearchForSuitable(Class, KeyPath), but searches for the canonical container whose elements have the given typedefault voidvalidateRequiredAttributes(TraceObject object, boolean strict, long snap) Verify that all required attributes are presentdefault voidvalidateTypeAndInterfaces(Object value, KeyPath parentPath, String key, boolean strict) Verify that the given value is of this schema's required type and, if applicable, implements the required interfaces
-
Method Details
-
getContext
SchemaContext getContext()Get the context of which this schema is a memberAll schema names are resolved in this same context
- Returns:
- the context
-
getName
TraceObjectSchema.SchemaName getName()Get the name of this schema- Returns:
- the name
-
getType
Class<?> getType()Get the Java class that best represents this type.Note that this is either a primitive, or
TraceObject. Even though an object implementation is necessarily a sub-type ofTraceObject, for any object schema, this returnTraceObject. Information about a "sub-type" of object is communicated via interfaces, element schemas, and attribute schemas.- Returns:
- the Java class for this type
-
getInterfaces
Set<Class<? extends TraceObjectInterface>> getInterfaces()Get the minimum interfaces supported by a conforming object- Returns:
- the set of required interfaces
-
isCanonicalContainer
boolean isCanonicalContainer()Check if this object is the canonical container for its elementsThis is generally in reference to the default type of this object's elements. For example, if elements of this object are all expected to support the "Process" interface, then this is the canonical Process container. Any Process ought to have a (canonical) path in this container. Any other path referring to such a Process ought to be a link.
NOTE: the concept of links is still in incubation, as some native debugging APIs seem to have made it difficult to detect object identity. Additionally, it's possible a caller's first encounter with an object is not via its canonical path, and it may be difficult to assign a path having only the native-API-given object in hand.
- Returns:
- true if this is a canonical container, false otherwise
-
getElementSchemas
Map<String,TraceObjectSchema.SchemaName> getElementSchemas()Get the map of element indices to named schemasIt is uncommon for this map to be populated, since the elements of a given container are typically uniform in type. Nevertheless, there can be restrictions imposed on -- and information provided for -- specific indices.
- Returns:
- the map
-
getDefaultElementSchema
Get the default schema for elementsSince elements of a given container are typically uniform in type, this is the primary means of specifying element schemas.
- Returns:
- the default named schema
-
getElementSchema
Get the named schema for a given element indexIf there's a schema specified for the given index, that schema is taken. Otherwise, the default element schema is taken.
- Parameters:
index- the index- Returns:
- the named schema
-
getAttributeSchemas
Map<String,TraceObjectSchema.AttributeSchema> getAttributeSchemas()Get the map of attribute names to named schemasThe returned map will include aliases. To determine whether or not an attribute key is an alias, check whether the entry's key matches the name of the attribute (see
TraceObjectSchema.AttributeSchema.getName()). It is possible the schema's name is empty, i.e., the default schema. This indicates an alias to a key that was not named in the schema. UsegetAttributeAliases()to determine the name of that key.- Returns:
- the map
-
getAttributeAliases
Get the map of attribute name aliasesThe returned map must provide the direct alias names. For any given key, the client need only query the map once to determine the name of the attribute to which the alias refers. Consequently, the map also cannot indicate a cycle.
An aliased attribute takes the value of its target implicitly.
- Returns:
- the map
-
checkAliasedAttribute
Check if the given name is an alias and get the target attribute name- Parameters:
name- the name- Returns:
- the alias' target, or the given name if not an alias
-
getDefaultAttributeSchema
Get the default schema for attributesSince the expected attributes and their respective schemas are generally enumerated, this most commonly returns
TraceObjectSchema.AttributeSchema.DEFAULT_ANY, to allow unrestricted use of additional attributes, orTraceObjectSchema.AttributeSchema.DEFAULT_VOID, to forbid any additional attributes.- Returns:
- the default attribute schema
-
getAttributeSchema
Get the attribute schema for a given attribute nameIf there's a schema specified for the given name, that schema is taken. If the name refers to an alias, its schema is taken. Otherwise, the default attribute schema is taken.
- Parameters:
name- the name- Returns:
- the attribute schema
-
getChildSchemaName
Get the named schema for a child having the given key- Parameters:
key- the key- Returns:
- the named schema
-
getChildSchema
Get the schema for a child having the given keyThis is the preferred method for navigating a schema and computing the expected type of a child.
- Parameters:
key- the key- Returns:
- the schema
-
getSuccessorSchema
Get the schema for a successor at the given (sub) pathIf this is the schema of the root object, then this gives the schema of the object at the given path in the model. This will always give a non-null result, though that result might be
PrimitiveTraceObjectSchema.VOID.- Parameters:
path- the relative path from an object having this schema to the desired successor- Returns:
- the schema for the successor
-
getSuccessorSchemas
Get the list of schemas traversed from this schema along the given (sub) pathThis list always begins with this schema, followed by the child schema for each key in the path. Thus, for a path of length n, the resulting list has n+1 entries. This is useful for searches along the ancestry of a given path:
List<TargetObjectSchema> schemas = getSuccessorSchemas(path); for (; path != null; path = PathUtils.parent(path)) { TargetObjectSchema schema = schemas.get(path.size()); // ... }All entries are non-null, though they may be
PrimitiveTraceObjectSchema.VOID.- Parameters:
path- the relative path from an object having this schema to the desired successor- Returns:
- the list of schemas traversed, ending with the successor's schema
-
searchFor
Do the same assearchFor(Class, KeyPath, boolean)with an empty prefix- Parameters:
type- the sub-type ofTraceObjectInterfaceto search forrequireCanonical- only return patterns matching a canonical location for the type- Returns:
- a set of patterns where such objects could be found
-
searchFor
default PathFilter searchFor(Class<? extends TraceObjectInterface> type, KeyPath prefix, boolean requireCanonical) Find (sub) path patterns that match objects implementing a given interfaceEach returned path pattern accepts relative paths from an object having this schema to a successor implementing the interface.
- Parameters:
type- the sub-type ofTraceObjectInterfaceto search forprefix- the prefix for each relative path patternrequireCanonical- only return patterns matching a canonical location for the type- Returns:
- a set of patterns where such objects could be found
-
searchForCanonicalContainer
Find the (sub) path to the canonical container for objects implementing a given interfaceIf more than one container is found having the shortest path, then
nullis returned.- Parameters:
type- the sub-type ofTraceObjectInterfaceto search for- Returns:
- the single path to that container
-
searchForSuitable
Search for a suitable object with this schema at the given path- Parameters:
type- the type of object soughtpath- the path of a seed object- Returns:
- the expected path of the suitable object, or null
-
searchForSuitable
Search for a suitable object with this schema at the given path- Parameters:
schema- the schema of object soughtpath- the path of a seed object- Returns:
- the expected path of the suitable object, or null
-
filterForSuitable
Search for all suitable objects with this schema at the given pathThis behaves like
searchForSuitable(Class, KeyPath), except that it returns a matcher for all possibilities. Conventionally, when the client uses the matcher to find suitable objects and must choose from among the results, those having the longer paths should be preferred. More specifically, it should prefer those sharing the longer path prefixes with the given path. The client should not just take the first objects, since these will likely have the shortest paths. If exactly one object is required, consider usingsearchForSuitable(Class, KeyPath)instead.- Parameters:
type-path-- Returns:
- the filter for finding objects
-
searchForSuitableContainer
default KeyPath searchForSuitableContainer(Class<? extends TraceObjectInterface> type, KeyPath path) LikesearchForSuitable(Class, KeyPath), but searches for the canonical container whose elements have the given type- Parameters:
type- the type of object soughtpath- the path of a seed object- Returns:
- the expected path of the suitable container of those objects, or null
-
searchForAncestor
Find the nearest ancestor implementing the given interface along the given pathIf the given path implements the interface, it is returned, i.e., it is not strictly an ancestor.
- Parameters:
type- the interface to search forpath- the seed path- Returns:
- the found path, or
nullif no ancestor implements the interface
-
searchForAncestorContainer
default KeyPath searchForAncestorContainer(Class<? extends TraceObjectInterface> type, KeyPath path) Find the nearest ancestor which is the canonical container of the given interfaceIf the given path is such a container, it is returned, i.e., it is not strictly an ancestor.
- Parameters:
type- the interface whose canonical container to search forpath- the seed path- Returns:
- the found path, or
nullif no such ancestor was found
-
isHidden
Check if the given key should be hidden for an object having this schemaElements ought never to be hidden. Otherwise, this defers to the attribute schema.
- Parameters:
key- the child key to check- Returns:
- true if hidden
-
validateTypeAndInterfaces
default void validateTypeAndInterfaces(Object value, KeyPath parentPath, String key, boolean strict) Verify that the given value is of this schema's required type and, if applicable, implements the required interfaces- Parameters:
value- the value being assigned to the keyparentPath- the path of the object whose key is being assigned, for diagnosticskey- the key that is being assignedstrict- true to throw an exception upon violation; false to just log and continue
-
validateRequiredAttributes
Verify that all required attributes are presentNOTE: This may become part of a schema and/or connector tester/validator later.
- Parameters:
object- the object whose schema is this onestrict- to throw exceptions upon violationssnap- the relevant snapshot
-
searchForRegisterContainer
Search for a suitable register containerThis 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.
NOTE: 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
myObject:for (PathPattern regPattern : myObject.getModel() .getSchema() .searchForRegisterContainer(0, myObject.getPath())) { TargetObject objRegs = myObject.getModel().getModelObject(regPattern.getSingletonPath()); if (objRegs != null) { // found it } }This places some conventional restrictions / expectations on models where registers are given on a frame-by-frame basis. The schema should present the
TraceRegisterContaineras the same object or a successor toTraceStackFrame, which must in turn be a successor toTraceStack. 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 forThreads[1]may beThreads[1].Stack[n].Registers, wherenis the frame level.Threads[1].Stackwould have theTraceStackinterface,Threads[1].Stack[0]would have theTraceStackFrameinterface, andThreads[1].Stack[0].Registerswould have theTraceRegisterContainerinterface. Note it is not sufficient forTraceRegisterContainerto be a successor ofTraceStackwith a single index between. There must be an interveningTraceStackFrame, and the frame level (index) must precede it.- Parameters:
frameLevel- the frame level. May be ignored if not applicablepath- the path of the seed object relative to the root- Returns:
- the filter where the register container should be found, possibly
PathFilter.NONE
-
computeFrameLevel
Compute the frame level of the object at the given path relative to this schemaIf there is no
TraceStackFramein the path, this will return 0 since it is not applicable to the object. If there is a stack frame in the path, this will examine its ancestry, up to and excluding theTraceStackfor an index. If there isn't a stack in the path, it is assumed to be an ancestor of this schema, meaning the examination will exhaust the ancestry provided in the path. If no index is found, an exception is thrown, because the frame level is applicable, but couldn't be computed from the path given. In that case, the client should include more ancestry in the path. Ideally, this is invoked relative to the root schema.- Parameters:
path- the path- Returns:
- the frame level, or 0 if not applicable
- Throws:
IllegalArgumentException- if frame level is applicable but not given in the path
-
isAssignableFrom
Check if this schema can accept a value of the given other schemaThis works analogously to
Class.isAssignableFrom(Class), except that schemas are quite a bit less flexible. OnlyPrimitiveTraceObjectSchema.ANYandPrimitiveTraceObjectSchema.OBJECTcan accept anything other than exactly themselves.- Parameters:
that-- Returns:
- true if an object of that schema can be assigned to this schema.
-