Class Collection
- All Implemented Interfaces:
Serializable,Comparable<Collection>
Api users interact with Collections and their JSON representation while Inversion abstracts the details of of the storage implementations.
Collections can remap ugly legacy column names to pretty JSON friendly camelCase names, and Collection Relationships can be used to create logical traversable foreign keys between Collections with the same underlying Db or even between Collections with different backend storage systems.
Generally it is the job of a Db to reflect on its underlying data source and automatically configure Collections and the
associated Relationships that will be accessed and manipulated by Api caller.
The Engine inspects the inbound Request path and attempts to match a Collection to the call.
The default mapping would be: /${endpointPath}/[${collection}]/[${resource}]/[${relationship}]
Querying "/${endpointPath}/${collection}" would typically result an a paginated list of resources ie. rows from your underlying Db translated into JSON speak.
Querying "/${endpointPath}/${collection}/${resource}" will fetch a single resource or row.
Querying "/${endpointPath}/${collection}/${resource}/${relationship}" will fetch all members from the relationship target Collection that are related to resource.
RestGet/Post/Put/Patch/DeleteAction are responsible for handling basic Rest semantics for interacting with Dbs via Collections.
TODO: check on test cases related to hasName and path matching TODO: need tests for resource keys with commas
- See Also:
-
Nested Class Summary
Nested classes/interfaces inherited from class io.inversion.Rule
Rule.RuleMatcher -
Field Summary
FieldsModifier and TypeFieldDescriptionAdditional names that should cause this Collection to match to a Request.protected DbThe backend storage adapter that probably generated this Collection and associated Indexes and Relationships.protected booleanSet this to true to prevent it from being automatically exposed through your Api.Representation of underlying Db datasource indexes.Properties map database column names to JSON property names.protected final ArrayList<Relationship>Relationships like resources in one collection to the resources in another collection.protected StringThe backend datasource name that this Collection operates on.Fields inherited from class io.inversion.Rule
configMap, configStr, excludeMatchers, excludeOn, includeMatchers, includeOn, log, name, order -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptioncopy()Performs a deep clone operation via object serialization/deserialization.decodeResourceKey(Index index, String inKey) Decodes a resource key into its columnName / value parts.decodeResourceKey(String inKey) Decodes a resource key into its columnName / value parts.decodeResourceKeys(Index index, String inKeys) Decodes a comma separated list of encoded resource keys.decodeResourceKeys(String inKeys) static StringThe reciprocal ofencodeStr(String)that replaces "\@[0-9a-f]{4}" hex sequences with the unescaped oritional unescaped character.static StringencodeResourceKey(List pieces) Creates a "~" separated url safe concatenation ofpiecesencodeResourceKey(Map<String, Object> values) Encodes the potentially multiple values of a resources primary index into a url path safe single value.static StringencodeResourceKey(Map values, Index index) Encodes the potentially multiple values of an index into a url path and query string safe single value.static StringEncodes non url safe characters into a friendly "@FOUR_DIGIT_HEX_VALUE" equivalent that itself will not be modified by URLEncoder.encode(String).booleanfindProperty(String jsonOrColumnName) Finds the property with case insensitive jsonOrColumnName.getColumnName(String jsonName) getDb()protected Rule.RuleMatcherDesigned to allow subclasses to provide a default match behavior of no configuration was provided by the developer.Gets an index by case insensitive name.getIndexByType(String indexType) getName()Finds the first unique Index with the fewest number of Properties.getProperty(String jsonOrColumnName) Convenience overload offindProperty(String).getPropertyByColumnName(String columnName) Find the property with case insensitive columnNamegetPropertyByJsonName(String jsonName) Find the property with case insensitive jsonNamegetRelationship(String name) booleanbooleanbooleanReturns true if all columns are foreign keys.static voidvoidremoveIndex(Index index) voidremoveProperty(Property prop) voidremoveRelationship(Relationship relationship) withAliases(String... aliases) withExclude(boolean exclude) Fluent utility method for constructing and adding a new Index.withIndexes(Index... indexes) withManyToOneRelationship(Collection parentCollection, String childPropertyName, Property... childFkProps) Fluent utility method to construct a Relationship and associated Indexes.withManyToOneRelationship(Collection parentCollection, String childPropertyName, String... childFkProps) Fluent utility method to construct a Relationship and associated Indexes.withOneToManyRelationship(String parentPropertyName, Collection childCollection, String childPropertyName, Property... childFkProps) Fluent utility method to construct a Relationship and associated Indexes.withOneToManyRelationship(String parentPropertyName, Collection childCollection, String childPropertyName, String... childFkProps) Fluent utility method to construct a Relationship and associated Indexes.withProperties(Property... props) Adds the property definitions to this Collection.withProperty(String name, String type) Fluent utility method for constructing a new Property and adding it to the Collection.withProperty(String name, String type, boolean nullable) Fluent utility method for constructing a new Property and adding it to the Collection.withRelationship(Relationship relationship) Add a new Relationship if a Relationship with the same name does not already exist.withRelationships(Relationship... relationships) withTableName(String name) Methods inherited from class io.inversion.Rule
checkLazyConfig, compareTo, doLazyConfig, getAllExcludePaths, getAllIncludePaths, getConfig, getConfig, getConfigKeys, getExcludeMatchers, getIncludeMatchers, getOrder, match, matches, matches, toString, withConfig, withExcludeOn, withExcludeOn, withExcludeOn, withIncludeOn, withIncludeOn, withIncludeOn, withName, withOrder
-
Field Details
-
aliases
Additional names that should cause this Collection to match to a Request.For example, in an e-commerce environment, you may overload the "orders" collection with aliases "cart", "basket", and "bag".
-
properties
Properties map database column names to JSON property names. -
indexes
Representation of underlying Db datasource indexes. -
relationships
Relationships like resources in one collection to the resources in another collection. -
db
The backend storage adapter that probably generated this Collection and associated Indexes and Relationships. -
tableName
The backend datasource name that this Collection operates on.The tableName might be "ORDER_DETAIL" but the Collection might be named "orderDetails".
-
exclude
protected boolean excludeSet this to true to prevent it from being automatically exposed through your Api.
-
-
Constructor Details
-
Collection
public Collection() -
Collection
-
-
Method Details
-
encodeResourceKey
Encodes the potentially multiple values of an index into a url path and query string safe single value.In a typical REST Api configuration where you url paths might map to something like "${endpoint}/${collection}/[${resource}][?{querystring}]", ${resource} is the primary index of the resource that has been encoded here.
That might look like "/bookstore/books/12345" or in the case of a compound primary index It might look like "/bookstore/orders/4567~abcde" where the "~" character is used to separate parts of the key.
The names of the index fields are not encoded, only the values, relying on index property order to remain consistent.
This methods is used by various actions when constructing hypermedia urls that allow you to uniquely identify individual resources (records in a Db) or to traverse Relationships.
The inverse of this method is
decodeResourceKeys(Index, String)which is used to decode inbound Url path and query params to determine which resource is being referenced.- Parameters:
values- column name to Property value mapping for a resourceindex- the index identifying the values that should be encoded- Returns:
- a url safe encoding of the index values separated by "~" characters or null if any of the values for an index key is null.
- See Also:
-
encodeResourceKey
Creates a "~" separated url safe concatenation ofpieces- Parameters:
pieces- key parts to be encoded- Returns:
- a url safe encoding of the
piecesseparated by "~" characters - See Also:
-
main
-
encodeStr
Encodes non url safe characters into a friendly "@FOUR_DIGIT_HEX_VALUE" equivalent that itself will not be modified by URLEncoder.encode(String).For example, encodeing "abcd/efg" would result in "abcd@002fefg" where "@002f" is the hex encoding for "/".
While "~" characters are considered url safe, the are specifically included for encoding so that
decodeResourceKeys(Index, String)can split a value on "~" before decoding its parts.- Parameters:
string- the string to encode- Returns:
- a url safe string with non safe characters encoded as '@FOUR_DIGIT_HEX_VALUE'
- See Also:
-
decodeStr
The reciprocal ofencodeStr(String)that replaces "\@[0-9a-f]{4}" hex sequences with the unescaped oritional unescaped character.- Parameters:
string- the string to decode- Returns:
- a string with characters escaped to their hex equivalent replaced with the unescaped value.
- See Also:
-
getDefaultIncludeMatch
Description copied from class:RuleDesigned to allow subclasses to provide a default match behavior of no configuration was provided by the developer.- Overrides:
getDefaultIncludeMatchin classRule<Collection>- Returns:
- the default collection match rule: "{_collection:" + getName() + "}/[:_resource]/[:_relationship]/*"
- See Also:
-
isLinkTbl
public boolean isLinkTbl()Returns true if all columns are foreign keys.In an RDBMS system, this would indicate that the table is used to link both sides of a many-to-many relationship and it should NOT be a public REST Collection.
- Returns:
- the true if all columns are foreign keys.
-
getProperty
Convenience overload offindProperty(String).- Parameters:
jsonOrColumnName- the property to get- Returns:
- the Property with a case insensitive json name or column name match.
- See Also:
-
findProperty
Finds the property with case insensitive jsonOrColumnName.The algo tries to find a matching json property name first before relooping over the props looking of a column name match.
- Parameters:
jsonOrColumnName- the property to find- Returns:
- the Property with a case insensitive json name or column name match.
-
getPropertyByJsonName
Find the property with case insensitive jsonName- Parameters:
jsonName- the name of the property to get- Returns:
- the property with
jsonName
-
getPropertyByColumnName
Find the property with case insensitive columnName- Parameters:
columnName- the name of the property to get- Returns:
- the property with
columnName
-
getColumnName
-
equals
-
getDb
- Returns:
- the underlying Db
-
withDb
- Parameters:
db- the db to set- Returns:
- this
-
getTableName
- Returns:
- the tableName backing this Collection in the Db.
-
withTableName
- Parameters:
name- the name to set- Returns:
- this
-
getName
- Overrides:
getNamein classRule<Collection>- Returns:
- the name of the Collection defaulting to
tableNameifnameis null.
-
getProperties
- Returns:
- a shallow copy of
properties
-
withProperties
Adds the property definitions to this Collection.If there is an existing prop with a json name to json name match or a column name to column name match, the new prop will not be added as it conflicts with the existing one.
- Parameters:
props- the properties to add- Returns:
- this
-
withProperty
Fluent utility method for constructing a new Property and adding it to the Collection.- Parameters:
name- the name of the Property to addtype- the type of the Property to add- Returns:
- this
- See Also:
-
withProperty
Fluent utility method for constructing a new Property and adding it to the Collection.- Parameters:
name- the name of the Property to addtype- the type of the Property to addnullable- is the Property nullable- Returns:
- this
- See Also:
-
removeProperty
-
getPrimaryIndex
Finds the first unique Index with the fewest number of Properties.- Returns:
- the Index that should be treated as the primary key for the Collection
- See Also:
-
getIndexByType
- Parameters:
indexType- the case insensative index type identifier- Returns:
- the first index with type = indexType
-
getIndex
Gets an index by case insensitive name.- Parameters:
indexName- the name of the Index to get- Returns:
- the requested Index
-
getIndexes
- Returns:
- a shallow copy of
indexes
-
withIndexes
-
withIndex
Fluent utility method for constructing and adding a new Index.If an Index with
nameexists it will be updated with the new information.All of the Properties in
propertyNamesmust already exist.- Parameters:
name- the name of the Index to create/addtype- the type of the Index to create/addunique- specifics if Index to create/add is uniquepropertyNames- the Properties that make up the index- Returns:
- this
- See Also:
-
removeIndex
-
isExclude
public boolean isExclude() -
withExclude
-
getRelationship
- Parameters:
name- the name of the Relationship to get- Returns:
- the Relationship with a case insensitve name match
-
getRelationships
- Returns:
- a shallow copy of
relationships.
-
removeRelationship
-
withRelationships
- Parameters:
relationships- the relationships to set- Returns:
- this
-
withRelationship
Add a new Relationship if a Relationship with the same name does not already exist.- Parameters:
relationship- the Relationship to add- Returns:
- this
-
withManyToOneRelationship
public Collection withManyToOneRelationship(Collection parentCollection, String childPropertyName, String... childFkProps) Fluent utility method to construct a Relationship and associated Indexes.- Parameters:
parentCollection- the parent collection of the relationship being createdchildPropertyName- name of the json property that will hold this relationship referencechildFkProps- names of the existing Properties that make up the foreign key- Returns:
- this
- See Also:
-
withManyToOneRelationship
public Collection withManyToOneRelationship(Collection parentCollection, String childPropertyName, Property... childFkProps) Fluent utility method to construct a Relationship and associated Indexes.In addition to the new Relationship a new foreign key Index will be created from
childFkPropstoparentCollection's primary Index.- Parameters:
parentCollection- the related parent CollectionchildPropertyName- what to call this relationship in the json representation of this Collection's resources.childFkProps- the Collections Properties that make up the foreign key- Returns:
- this
-
withOneToManyRelationship
public Collection withOneToManyRelationship(String parentPropertyName, Collection childCollection, String childPropertyName, String... childFkProps) Fluent utility method to construct a Relationship and associated Indexes.This is a convenience overload of withOneToManyRelationship(String, Collection, String, Property...) to be used when code wiring Apis and you don't want to lookup references to the actual Property objects.
- Parameters:
parentPropertyName- the name of the json property for the parent that references the childchildCollection- the target child collectionchildPropertyName- the name of hte json property for the child that references the parentchildFkProps- names of the existing Properties that make up the foreign key- Returns:
- this
- See Also:
-
withOneToManyRelationship
public Collection withOneToManyRelationship(String parentPropertyName, Collection childCollection, String childPropertyName, Property... childFkProps) Fluent utility method to construct a Relationship and associated Indexes.In addition to the new Relationship a new foreign key Index will be created from
childFkPropsto this Collection's primary Index.- Parameters:
parentPropertyName- the name of the json property for the parent that references the childchildCollection- the target child collectionchildPropertyName- the name of hte json property for the child that references the parentchildFkProps- Properties that make up the foreign key- Returns:
- this
-
hasName
- Parameters:
nameOrAlias- the name or alias to check for- Returns:
- true if the name or aliases match
-
getAliases
- Returns:
- a shallow clone of
aliases
-
withAliases
-
encodeResourceKey
Encodes the potentially multiple values of a resources primary index into a url path safe single value.- Parameters:
values- the key value pairs to encode- Returns:
- a url safe encoding of the resources primary index values
- See Also:
-
decodeResourceKey
Decodes a resource key into its columnName / value parts.- Parameters:
inKey- the resource key to decode- Returns:
- the decoded columnName / value pairs.
- See Also:
-
decodeResourceKeys
-
decodeResourceKey
Decodes a resource key into its columnName / value parts.- Parameters:
index- identifies the columnNames by positioninKey- the encoded string to decode- Returns:
- the decoded columnName / value pairs.
- See Also:
-
decodeResourceKeys
Decodes a comma separated list of encoded resource keys.- Parameters:
index- identifies the columnNames to decodeinKeys- a comma separated list of encoded resource keys- Returns:
- a list of decoded columnName value pairs
- See Also:
-
copy
Performs a deep clone operation via object serialization/deserialization.It is useful when you want to manually wire up numerous copies of a collection but tweak each one a bit differently.
For example, if you were connecting to a DynamoDb or CosmosDb where a single table is overloaded to support different domain objects.
This feature requires Collection, Relationship and Index to be Serializable.
The Db reference here is transient and reconnected to the clone so that this instance and the copy reference the same Db.
- Returns:
- a deep copy of this Collection referencing the same underlying Db instance.
-