Skip to content

ERMrest Programmatic API Sketch

robes edited this page Jan 21, 2016 · 21 revisions

ERMrest Programmatic API Sketch

This outline focuses on the application-side APIs, e.g. those used by a data or model-consuming client application. It ignores internal APIs needed to help implement the behaviors.

Some idioms assumed in this sketch:

  1. Using nested object structures to group API behaviors rather than using longer method names.
  • See the entity, attribute, and attributegroup sub-APIs on datapath.
  1. Using container-like objects at branching points in the object tree with common signatures.
  • See schemas, tables, columns, etc.
  • Having .by_position and .by_name member access mechanisms, etc.
  • Assuming idioms for checking length, iterating, etc. (Implied rather than sketched out.)
  1. Putting management methods on the object being managed.
  • Having .delete() on the object itself
  • Having .create() on the container-like object where new members are being added.
  1. Assuming Python-like semantics for sets, lists, tuples. Might need to adapt for Javascript.

Catalog and Model Access Object Signatures

A server is bound to a URL, and session credentials are established. Catalogs can be managed or bound to then work in a particular dataset.

The catalog.datapath() method instantiates a logical data access object. Many such objects can be instantiated from the same catalog to manage different data access tasks concurrently.

  • server = Server(url)
    • .session.client
    • .session.attributes
    • .session.expires
    • .login()
    • .logout()
    • .catalogs.create( catalog_params ) -> catalog
    • .catalogs.by_id[ id ] : catalog
  • catalog
    • .server
    • .id
    • .delete()
    • .introspect()... if not automatic during construction?
    • .schemas.create( schema_params ) -> schema
    • .schemas.by_name[ schema_name ] : schema
    • other catalog management methods or properties?
  • schema
    • .catalog
    • .name
    • .delete()
    • .tables.create( table_params ) -> table
    • .tables.by_name[ table_name ] : table
    • .annotations.create( annotation_params ) -> annotation
    • .annotations.by_uri[ uri ] : annotation
  • table
    • .schema
    • .name
    • .delete()
    • .columns.create ( column_params ) -> column
    • .columns.by_name[ column_name ] : column
    • .columns.by_position[ index ] -> column
    • .keys.create( key_params ) -> key
    • .keys.by_cols[ colset ] -> key
    • .foreignkeys.create( fkey_params ) -> foreignkeyref
    • .foreignkeys[ (from_columns, to_columns) ] : foreignkeyref
    • .annotations.create( annotation_params ) -> annotation
    • .annotations.by_uri[ uri ] : annotation
  • column
    • .table
    • .name
    • .type
    • .delete()
    • .annotations[ uri ] -> annotation
  • type
    • .name
    • .is_array : boolean
    • .base_type
  • key
    • .table
    • .columns : colset
    • .annotations.create( annotation_params ) -> annotation
    • .annotations[ uri ] : annotation
  • foreignkeyref
    • .delete()
    • .from_columns[ index ] : column
    • .to_columns[ index ] : column
    • .annotations.create( annotation_params ) -> annotation
    • .annotations.by_uri[ uri ] : annotation
  • annotation
    • .subject : schema|table|column|key|foreignkeyref
    • .uri
    • .delete()
    • .content

Data Access Object Signatures

The objects above are relatively static, corresponding to server, database, and model resources. The objects below are dynamic views/wrappers over the database. A pathtable is a table instance in a particular query while table is an element of the database schema. A pathcolumn is a column from one table instance, while a column is an element of the database schema.

A datapath represents a particular dataset in an ERMrest catalog. It combines one or more pathtable instances linked into a relational join and filtered by filter expressions and denoting a particular entity context. This dataset has sub-APIs to manipulate whole entities, attributes, or attribute-groups in the entity context of the path.

  • datapath = Datapath(table)
    • .catalog
    • .context : pathtable
    • .filters.add(filter)
    • .extend(table, context=null, link=null) -> pathtable
    • .entity.get()
    • .entity.post()
    • .entity.put()
    • .entity.delete()
    • .attribute[ projection ].get()
    • .attribute[ projection ].delete()
    • .attributegroup[ grouping ][ projection ].get()
    • .attributegroup[ grouping ][ projection ].put()
  • pathtable
    • .datapath
    • .table
    • .columns.by_name[ column_name ] : pathcolumn
    • .columns.by_position[ index ] : pathcolumn
    • .filters.add(filter)
  • pathcolumn
    • .pathtable
    • .column
    • .operators.by_name[ operator ](rvalue=null) -> filter
  • filter
    • .is_junction : boolean
    • When .is_junction is true:
      • .conjunction : boolean
      • .subfilters[ index ] : filter
    • When .is_junction is false:
      • .pathcolumn
      • .operator
      • .rvalue

Facet-based Abstract Data Access Object Signatures

This is a variant or wrapper for datapath that discovers facets automatically and handles the linkage of facet source tables to the main context table rather than the client building up the path structure.

  • facetpath = Facetpath(table)
    • .catalog
    • .context : pathtable
    • .filters.add(filter)
    • .facets.by_name[ facet_name ] : pathcolumn
    • .facets.by_index[ index ] : pathcolumn
    • .entity.get()
    • .entity.post()
    • .entity.put()
    • .entity.delete()
    • .attribute[ projection ].get()
    • .attribute[ projection ].delete()
    • .attributegroup[ grouping ][ projection ].get()
    • .attributegroup[ grouping ][ projection ].put()