Class ModelAwareSystemTool<T extends Record & ModelInput>
- All Implemented Interfaces:
SystemTool<T>
- Direct Known Subclasses:
CreateRecordTool,DeleteRecordTool,DescribeModelTool,ReadActivityTool,ReadRecordTool,SearchRecordsTool,UpdateRecordTool
Access — and field
projection.
Supports both JPA entities and custom models (MetaJsonModel / MetaJsonRecord). The tool
detects the model type internally: if JPA.model() resolves the name, the JPA entity path
is used; otherwise the tool looks up a custom model via MetaJsonModelRepository.
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionbeforeApproval(T input, ToolContext context) Refuses, before the user is asked to approve the call, what running it would refuse: the operation on the model, and whatcheckForModel(T, java.lang.Class<? extends com.axelor.db.Model>, com.axelor.ai.governance.access.Access)finds.protected ToolResultcheckForJsonModel(T input, MetaJsonModel jsonModel, Access access) The same for a custom model.protected ToolResultcheckForModel(T input, Class<? extends Model> modelClass, Access access) What the call would refuse on this entity, found without writing anything, so that a refusal known up front costs the user no approval; null when it would go through.protected static Map<String, MetaJsonField> customFieldsByName(Class<? extends Model> modelClass) An entity's custom fields, by name.entityCustomFieldNames(Class<? extends Model> modelClass) Returns the set of custom field names for an entity.protected static List<MetaJsonField> entityCustomFields(Class<? extends Model> modelClass) Queries custom field definitions for an entity's JSON property.entityFieldNames(Class<? extends Model> modelClass) The names an entity accepts: its own properties, its custom fields, id and version.final ToolResultexecute(T input, ToolContext context) Execute with the given typed input and agent-scoped context.protected abstract ToolResultexecuteForJsonModel(T input, MetaJsonModel jsonModel, Access access) Subclass hook — called for a custom model once it is allowed.protected abstract ToolResultexecuteForModel(T input, Class<? extends Model> modelClass, Access access) Subclass hook — called for a JPA entity once the model is allowed.Separates custom field values from a data map.protected static StringinvalidChoice(String modelName, String fieldName, Object value, List<Selection.Option> options) What is wrong with a value for a field limited to a set of values, or null when nothing is.protected static StringinvalidJsonValues(MetaJsonModel jsonModel, Map<String, Object> values, Projection projection) The same, for a write to a custom model, whose names are the ones it defines.protected static StringinvalidValues(Class<? extends Model> modelClass, Map<String, Object> values, Projection projection) What is wrong with a write, or null when nothing is.jsonFieldNames(MetaJsonModel jsonModel) The names a custom model defines — what a caller may pass infieldsororderBy.protected static List<MetaJsonField> jsonModelFields(MetaJsonModel jsonModel) The fields a custom model defines, which is none rather than null when it defines none.protected static StringjsonPropertyOf(Class<? extends Model> modelClass) Returns the name of the JSON property on the entity (usually "attrs"), or null if none.protected abstract OperationThe operation this tool performs, which the model's permissions are checked for.parseAttrs(Object attrsValue) Parses a JSON attrs string to a map.saveRecord(Class<? extends Model> modelClass, Map<String, Object> values, Model attrsFrom, Projection projection) Writesvaluesto a record of this model and answers with what identifies it.protected static List<Selection.Option> selectionOptions(Property prop) The options a field is limited to, empty when it is not limited to any.protected static List<Selection.Option> selectionOptions(MetaJsonField field) The same, for a custom field, which carries a named selection or none.protected static StringserializeAttrs(Map<String, Object> attrs) Serializes an attrs map to a JSON string.protected static IllegalArgumentExceptionunknownFields(String modelName, Collection<String> known, Collection<String> unknown) The error for names a model does not define, listing the ones it does.protected static StringunknownFieldsMessage(String modelName, Collection<String> known, Collection<String> unknown) The same, for a caller that reports rather than throws.protected static IllegalArgumentExceptionunknownJsonFields(MetaJsonModel jsonModel, List<String> unknown, Projection projection) The error for names the custom model does not define, listing the ones it does that the user may read.protected static voidvalidateFields(Class<? extends Model> modelClass, List<String> fields, Projection projection) Refuses names this entity cannot project, before a page of records is built from them.protected static voidvalidateJsonFields(MetaJsonModel jsonModel, List<String> fields, Projection projection) The same, for the names a custom model defines.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface com.axelor.ai.tool.system.SystemTool
callTitle, code, description, inputType, name, provideContext, refusal, runsOutsideTransaction, safety, undoneByRollback
-
Constructor Details
-
ModelAwareSystemTool
public ModelAwareSystemTool()
-
-
Method Details
-
operation
The operation this tool performs, which the model's permissions are checked for. -
execute
Description copied from interface:SystemToolExecute with the given typed input and agent-scoped context.- Specified by:
executein interfaceSystemTool<T extends Record & ModelInput>
-
beforeApproval
Refuses, before the user is asked to approve the call, what running it would refuse: the operation on the model, and whatcheckForModel(T, java.lang.Class<? extends com.axelor.db.Model>, com.axelor.ai.governance.access.Access)finds. Null asks as usual.- Specified by:
beforeApprovalin interfaceSystemTool<T extends Record & ModelInput>- Parameters:
input- the call's input, or null when the tool takes nonecontext- the call's context
-
executeForModel
protected abstract ToolResult executeForModel(T input, Class<? extends Model> modelClass, Access access) Subclass hook — called for a JPA entity once the model is allowed.- Parameters:
access- what the call may do; the tool asks it about every record and field it touches, and may throwAccessDeniedfrom anywhere to refuse the call
-
executeForJsonModel
Subclass hook — called for a custom model once it is allowed. -
checkForModel
What the call would refuse on this entity, found without writing anything, so that a refusal known up front costs the user no approval; null when it would go through. The call checks again when it runs. -
checkForJsonModel
The same for a custom model. -
saveRecord
protected Map<String,Object> saveRecord(Class<? extends Model> modelClass, Map<String, Object> values, Model attrsFrom, Projection projection) Writesvaluesto a record of this model and answers with what identifies it.Custom fields are separated out and merged into the JSON attrs of
attrsFrom— the record being updated, or the new bean when one is being created — so that writing one custom field leaves the rest of them alone. The answer is the record's identity asprojectionreads it: its name field withheld when the user may not read it. -
validateFields
protected static void validateFields(Class<? extends Model> modelClass, List<String> fields, Projection projection) Refuses names this entity cannot project, before a page of records is built from them.A name the projection does not resolve is simply absent from every record it answers with, which reads as "this field is empty" when it only means the name was wrong — and on a search that matched nothing, it is never noticed at all. Checking the ask rather than each answer also costs one lookup instead of one per record.
A dotted path is refused too: the projection reads one property, so
customer.namewould resolve to nothing. Naming the relation itself answers with{id, name}. -
validateJsonFields
protected static void validateJsonFields(MetaJsonModel jsonModel, List<String> fields, Projection projection) The same, for the names a custom model defines. -
invalidValues
protected static String invalidValues(Class<? extends Model> modelClass, Map<String, Object> values, Projection projection) What is wrong with a write, or null when nothing is.A name the entity does not define is dropped on the way to the database —
JPA.editskips what it cannot map — and the write then answers with the saved record, so a misspelled field reads as a value that was stored. Refusing the call is the only way the caller learns that it was not.A value written to a field limited to a set of values is checked against that set for the same reason: an unknown one is stored as written, and reads back as data.
Nested values are checked against the model they are written to, so an item of a one-to-many is held to that model's names rather than the parent's.
-
invalidJsonValues
protected static String invalidJsonValues(MetaJsonModel jsonModel, Map<String, Object> values, Projection projection) The same, for a write to a custom model, whose names are the ones it defines. -
invalidChoice
protected static String invalidChoice(String modelName, String fieldName, Object value, List<Selection.Option> options) What is wrong with a value for a field limited to a set of values, or null when nothing is.Nothing refuses a value outside the set: a selection is a string column, so a wrong one is stored as written, and a wrong one in a filter matches no row and reads as "there are none" — which is the same answer the caller would get if there really were none. The values the field takes are named, because guessing one is exactly what went wrong.
A value may also be several, for a multi-select field, which stores its choices as one comma-separated string, or for a criterion matching against a list. The whole value is tried first, so a single choice that contains a comma is still recognised.
-
selectionOptions
The options a field is limited to, empty when it is not limited to any.One source for what a field accepts, so that what
describe_modeltells the caller and what a write or a filter is held to cannot say different things. -
selectionOptions
The same, for a custom field, which carries a named selection or none. -
customFieldsByName
An entity's custom fields, by name. -
entityFieldNames
The names an entity accepts: its own properties, its custom fields, id and version. -
jsonFieldNames
The names a custom model defines — what a caller may pass infieldsororderBy. -
jsonModelFields
The fields a custom model defines, which is none rather than null when it defines none. -
unknownJsonFields
protected static IllegalArgumentException unknownJsonFields(MetaJsonModel jsonModel, List<String> unknown, Projection projection) The error for names the custom model does not define, listing the ones it does that the user may read.Shared so that a misspelling reads the same whether it reached us through a projection or a sort, and always names the custom model rather than the MetaJsonRecord it is stored in.
-
unknownFields
protected static IllegalArgumentException unknownFields(String modelName, Collection<String> known, Collection<String> unknown) The error for names a model does not define, listing the ones it does.The names are what lets the caller correct itself on the next call instead of guessing again, which is the whole reason this is an error rather than an empty answer. A caller lists only the names the user may read: the rest are not theirs to learn of.
-
unknownFieldsMessage
protected static String unknownFieldsMessage(String modelName, Collection<String> known, Collection<String> unknown) The same, for a caller that reports rather than throws. -
jsonPropertyOf
Returns the name of the JSON property on the entity (usually "attrs"), or null if none. -
entityCustomFields
Queries custom field definitions for an entity's JSON property. -
entityCustomFieldNames
Returns the set of custom field names for an entity. -
parseAttrs
Parses a JSON attrs string to a map. Returns null on failure. -
serializeAttrs
Serializes an attrs map to a JSON string. -
extractCustomFields
protected static Map<String,Object> extractCustomFields(Map<String, Object> data, Class<? extends Model> modelClass) Separates custom field values from a data map. Returns the custom field values that were removed from the data map, or null if none.
-