Class ClarityAPIImpl

java.lang.Object
org.cruk.clarity.api.impl.ClarityAPIImpl
All Implemented Interfaces:
ClarityAPI, ClarityAPIInternal

public class ClarityAPIImpl extends Object implements ClarityAPI, ClarityAPIInternal
Implementation of ClarityAPI using the Clarity REST operations. Uses the Spring REST template for the calls with a Spring Jaxb2Marshaller object for XML/object transformations and a Commons HttpClient to do the actual calls.
See Also:
  • Field Details

    • API_PATH_BASE

      protected static final String API_PATH_BASE
      The first part of the path for API calls. This project is supporting version two of the Clarity API.
      See Also:
    • logger

      protected Logger logger
      Logger.
    • restClient

      protected RestOperations restClient
      The Spring REST client.
    • httpClient

      protected HttpClient httpClient
      The HTTP client.
    • httpRequestFactory

      protected AuthenticatingClientHttpRequestFactory httpRequestFactory
      The request factory for direct communication with the HTTP client.
    • fileUploadClient

      protected RestOperations fileUploadClient
      Adapted REST client for uploading files through the HTTP mechanism.
    • filestoreSessionFactory

      protected DefaultSftpSessionFactory filestoreSessionFactory
      Session factory for JSch connections to the file store over SFTP.
    • serverAddress

      protected URL serverAddress
      The root URL to the Clarity server.
    • apiRoot

      protected String apiRoot
      The root path for all API calls to Clarity server.
    • apiCredentials

      protected UsernamePasswordCredentials apiCredentials
      User name and password credentials for accessing the Clarity API.
    • filestoreCredentials

      protected UsernamePasswordCredentials filestoreCredentials
      User name and password credentials for accessing the file store.
    • uploadOverHttp

      protected boolean uploadOverHttp
      Whether files can be uploaded using HTTP to the files/id/upload API end point.
      See Also:
    • httpUploadSizeLimit

      protected long httpUploadSizeLimit
      The maximum size of file that can be uploaded using HTTP.
      See Also:
    • autoRevertToSFTP

      protected boolean autoRevertToSFTP
      Whether the SFTP mechanism can be used as a fall back for uploading files if a file exceeds the HTTP upload size limit.
      See Also:
    • downloadDirectFromHttpStore

      protected boolean downloadDirectFromHttpStore
      Whether to download files that have an HTTP URL directly from their store, or whether to download via the files/id/download API end point.
      See Also:
    • entityToListClassMap

      protected Map<Class<? extends Locatable>,Class<?>> entityToListClassMap
      Map of Locatable class to the class that provides the list of links returned from listing or searching for objects of that type.

      The key in the pair should be the entity class (e.g. Artifact and the value should be a class that implements the Batch interface and is annotated with the ClarityQueryResult annotation for that entity class (e.g. Artifacts).

    • entityToBatchRetrieveClassMap

      protected Map<Class<? extends Locatable>,Class<?>> entityToBatchRetrieveClassMap
      Map of Locatable class to the class that provides the mass fetch or update operation. Such bulk fetches and updates are only available for a small number of classes.

      The key in the pair should be the entity class (e.g. Artifact and the value should be a class that implements the BatchUpdate interface and is annotated with the ClarityBatchRetrieveResult annotation for that entity class (e.g. ArtifactBatchFetchResult).

    • updaterFields

      protected Map<Class<?>,Map<String,Field>> updaterFields
      Cache of fields to update by reflective examination of an updated object from the server. Maps the artifact class to a map of field names to java.lang.reflect.Field objects.
    • statefulOverride

      protected ThreadLocal<StatefulOverride> statefulOverride
      Thread local flag indicating whether the next call on the thread should fetch stateful entities according to a different rule to the normal.
  • Constructor Details

    • ClarityAPIImpl

      public ClarityAPIImpl()
      Standard constructor.
    • ClarityAPIImpl

      public ClarityAPIImpl(Properties configuration)
      Initialise with an initial configuration from a properties file.
      Parameters:
      configuration - The properties file.
      Throws:
      InvalidURIException - if the server URL is set and the value cannot form a valid URL.
      See Also:
  • Method Details

    • setFilestoreSessionFactory

      @Autowired @Qualifier("clarityFilestoreSFTPSessionFactory") public void setFilestoreSessionFactory(DefaultSftpSessionFactory filestoreSessionFactory)
      Set the file store session factory for SFTP connections.
      Parameters:
      filestoreSessionFactory - The SFTP session factory.
    • setJaxbMarshaller

      @Autowired @Qualifier("clarityJaxbMarshaller") public void setJaxbMarshaller(Jaxb2Marshaller jaxbMarshaller)
      Set the Jaxb marshaller.

      This operation also immediately scans the classes managed by the marshaller to find those supporting classes for retrieving lists of links to a given entity and classes that allow batch fetch and update of entities.

      Parameters:
      jaxbMarshaller - The Jaxb marshaller.
    • setRestClient

      @Autowired @Qualifier("clarityRestTemplate") public void setRestClient(RestOperations restClient)
      Set the REST client.
      Parameters:
      restClient - The REST client.
    • setFileUploadClient

      @Autowired @Qualifier("clarityFileUploadTemplate") public void setFileUploadClient(RestOperations fileUploadClient)
      Set the REST client used for file uploads over HTTP.
      Parameters:
      fileUploadClient - The REST client configured for file upload.
    • setHttpClient

      @Autowired @Qualifier("clarityHttpClient") public void setHttpClient(HttpClient httpClient)
      Set the HTTP client. If the credentials are already known at this point, those are set on the client.
      Parameters:
      httpClient - The HTTP client.
    • setHttpRequestFactory

      @Autowired @Qualifier("clarityClientHttpRequestFactory") public void setHttpRequestFactory(AuthenticatingClientHttpRequestFactory httpRequestFactory)
      Set the factory used for obtaining HTTP requests.
      Parameters:
      httpRequestFactory - The HTTP request factory supporting basic authentication.
    • getServer

      public URL getServer()
      Get the base URL of the Clarity server. This does not include the path to the API, just the protocol, host and port.
      Specified by:
      getServer in interface ClarityAPI
      Returns:
      The server base URL.
    • setServer

      public void setServer(URL serverAddress)
      Set the base URL to the Clarity server.
      Specified by:
      setServer in interface ClarityAPI
      Parameters:
      serverAddress - The base URL. Should just be the protocol, host and port with no path.
    • getServerApiAddress

      public String getServerApiAddress()
      Get the base address of the REST API. This is the server base address plus the API path (/api/v2).
      Specified by:
      getServerApiAddress in interface ClarityAPI
      Returns:
      The API base address.
    • getUsername

      public String getUsername()
      Get the user name of the researcher currently connecting to the server.
      Specified by:
      getUsername in interface ClarityAPI
      Returns:
      The user name used for connections.
    • setCredentials

      public void setCredentials(String username, String password)
      Set the credentials to use to connect to the REST API.
      Specified by:
      setCredentials in interface ClarityAPI
      Parameters:
      username - The researcher's user name.
      password - The researcher's password.
    • setCredentials

      public void setCredentials(Credentials httpCredentials)
      Set the credentials to use to connect to the REST API.
      Specified by:
      setCredentials in interface ClarityAPI
      Parameters:
      httpCredentials - A Credentials object for the HTTP client. Does nothing if this is null.
    • setFilestoreServer

      public void setFilestoreServer(String host)
      Set the name of the file store host.
      Specified by:
      setFilestoreServer in interface ClarityAPI
      Parameters:
      host - The name of the file store server.
    • setFilestoreCredentials

      public void setFilestoreCredentials(String username, String password)
      Set the credentials used to connect to the file store.
      Specified by:
      setFilestoreCredentials in interface ClarityAPI
      Parameters:
      username - The file store user account.
      password - The file store user password.
    • getFilestoreServer

      protected String getFilestoreServer()
      Get the host currently set on the file store.
      Returns:
      The file store host (may be null).
    • setConfiguration

      public void setConfiguration(Properties configuration)
      Set configuration from a properties file. The properties may contain any of the following:

      The properties file does not have to contain all of these values. Any that are missing are simply ignored and, where possible, left as their defaults.

      Specified by:
      setConfiguration in interface ClarityAPI
      Parameters:
      configuration - The properties file to configure from.
    • getBulkOperationBatchSize

      public int getBulkOperationBatchSize()
      Get the size of each batch of objects fetched, updated or created in a bulk operation.
      Returns:
      The number of objects sent or retrieved in each batch.
      See Also:
    • setBulkOperationBatchSize

      public void setBulkOperationBatchSize(int batchSize)
      Set the number of objects that will be fetched, updated or created in each call the Clarity API for the bulk operations (those that use a collection of links or objects).

      It seems that naively asking for or sending all the links or objects in the collections does not sit well with the back end server. Experimentation has shown that the fastest overall operation time (at least for fetching artifacts) occurs when between twenty and thirty links or artifacts are in the POST call to the Clarity API.

      The default is Genologics' recommendation of a "sweet spot" of 500.

      Specified by:
      setBulkOperationBatchSize in interface ClarityAPI
      Parameters:
      batchSize - The number of objects to fetch or send per call to the API. A maximum of 10000 objects per batch is imposed because performance noticeably drops off long before this number of objects is used. If this argument is less than or equal to zero, all object or links in the collection will be sent at once up to the 10000 per call hard limit.
      See Also:
    • setUploadOverHttp

      public void setUploadOverHttp(boolean uploadOverHttp)
      Set whether uploads over HTTP are permitted using the files/id/upload API end point, or whether only SFTP uploads are allowed.

      Note that as of release 2.23, downloads from the regular file store take place through the files/id/download end point. This solves any problems for SFTP access to the file store. Files in a HTTP file store may be handled differently (see ClarityAPI.setDownloadDirectFromHttpStore(boolean)).

      The default is to perform uploads of files no bigger than the limit through HTTP.

      Specified by:
      setUploadOverHttp in interface ClarityAPI
      Parameters:
      uploadOverHttp - true if files can be uploaded using HTTP, false if not.
    • getHttpUploadSizeLimit

      public long getHttpUploadSizeLimit()
      Get the maximum size of file that can be uploaded using HTTP.
      Returns:
      The maximum size of file allowed over HTTP.
      Since:
      2.23
      See Also:
    • setHttpUploadSizeLimit

      public void setHttpUploadSizeLimit(long limit)
      Set the maximum size of file that can be uploaded using HTTP. This must be no greater than the corresponding Clarity configuration property api.artifacts.max.resultfile.upload.size.

      The default file size limit is 10,485,760 bytes (10MB), which is the default setting for the Clarity configuration property.

      Specified by:
      setHttpUploadSizeLimit in interface ClarityAPI
      Parameters:
      limit - The maximum size of file allowed over HTTP.
    • setAutoRevertToSFTPUploads

      public void setAutoRevertToSFTPUploads(boolean autoRevertToSFTP)
      Set whether the SFTP mechanism can be used as a fall back for uploading files if a file exceeds the HTTP upload size limit.

      The default is to allow the SFTP upload mechanism to be used if a file is too large for HTTP.

      Specified by:
      setAutoRevertToSFTPUploads in interface ClarityAPI
      Parameters:
      autoRevertToSFTP - true to use SFTP to transfer files that are too large for HTTP, false to fail if such a file is given.
      See Also:
    • setDownloadDirectFromHttpStore

      public void setDownloadDirectFromHttpStore(boolean downloadDirect)
      For files stored in a HTTP file store, set whether to download these files directly from their HTTP server or whether to fetch them via the API's files/id/download end point (i.e. the same as files in the regular file store).

      The default is to download directly from the HTTP store rather than going through the API. This will save traffic and load on the LIMS server.

      Specified by:
      setDownloadDirectFromHttpStore in interface ClarityAPI
      Parameters:
      downloadDirect - true to fetch HTTP accessible files directly from their HTTP URL, false to fetch them via the Clarity API.
    • afterInitialisation

      @PostConstruct public void afterInitialisation() throws MalformedURLException
      When this bean has finished Spring set up (all properties set), the configuration that may have been supplied during start up needs to be applied correctly to this bean and some objects it depends on.
      Throws:
      MalformedURLException - if the api.server property is set to an invalid URL.
    • getQueryResultsClassForEntity

      public <E extends Locatable, BH extends Batch<? extends LimsLink<E>>> Class<BH> getQueryResultsClassForEntity(Class<E> entityClass)
      Get the class that holds a list of links for the given entity when returned from a list or search operation.

      For example, this is the Artifacts class for the Artifact entity.

      Specified by:
      getQueryResultsClassForEntity in interface ClarityAPIInternal
      Type Parameters:
      E - The type of the entity.
      BH - The type of the object that holds the list of links to these entities.
      Parameters:
      entityClass - The class of the entity.
      Returns:
      The list of links class for the given class of entity.
    • getBatchRetrieveClassForEntity

      protected <E extends Locatable, BH extends Batch<E>> Class<BH> getBatchRetrieveClassForEntity(Class<E> entityClass)
      Get the class that allow mass retrieve or update operations for the given entity class.

      For example, this is the ArtifactBatchFetchResult class for the Artifact entity.

      Type Parameters:
      E - The type of the entity.
      BH - The type of the object that contains the list of entities from a bulk fetch.
      Parameters:
      entityClass - The class of the entity.
      Returns:
      The bulk retrieval/update class for the given class of entity. Will return null if the entity class has no mechanism for bulk operations.
    • checkEntityAnnotated

      protected ClarityEntity checkEntityAnnotated(Class<?> entityClass)
      Check that the class given as an entity class is annotated with the ClarityEntity annotation.
      Parameters:
      entityClass - The class to check.
      Returns:
      The ClarityEntity annotation found.
      Throws:
      IllegalArgumentException - if entityClass is null or is not annotated.
    • checkServerSet

      protected void checkServerSet()
      Check the server's URL has been set.
      Throws:
      IllegalStateException - if the URL has not been set.
    • checkFilestoreSet

      protected void checkFilestoreSet()
      Check the file store's host name and credentials have been set.
      Throws:
      IllegalStateException - if either the host name or the credentials are not set.
    • checkCollectionHomogeneousAndUnique

      protected <E extends Locatable> Class<E> checkCollectionHomogeneousAndUnique(Collection<E> entities, boolean requireUri)
      Check that the given collection contains no nulls, that each item either has a URI or does not have a URI (depending on requireUri, that all objects in the collection are of the same class, and that, if requireUri is true, there are no repeated URIs in the collection (ignoring state).
      Type Parameters:
      E - The type of entity in the collection.
      Parameters:
      entities - The collection of entities to check.
      requireUri - Whether these objects are expected to already have a URI set on them or not.
      Returns:
      The class of the entities in the collection. Will return null if the entities collection is empty.
      Throws:
      IllegalArgumentException - if entities contains a null element; if an object in @{code entities} has a URI when it should not or does not have a URI when it should; if the classes of the objects in entities are not all the same; if an entity appears more than once in the collection (if requireUri is true).
    • checkLinkCollectionHomogeneousAndUnique

      protected <E extends Locatable, L extends LimsLink<E>> Class<E> checkLinkCollectionHomogeneousAndUnique(Collection<L> links)
      Check that the given collection of links contains no nulls, that each link has a URI, that all links in the collection are links to the same entity class, and that there are no repeated URIs in the collection (ignoring state).
      Type Parameters:
      E - The type of entity linked to.
      L - The type of link object.
      Parameters:
      links - The collection of links to check.
      Returns:
      The class of the entities the links in the collection refer to. Will return null if the links collection is empty.
      Throws:
      IllegalArgumentException - if links contains a null element; if a link in @{code links} has no URI set; if the type of the entities indicated by the links in links are not all the same; if an entity is referred to more than once in links.
    • limsIdToUri

      public <E extends Locatable> URI limsIdToUri(String limsid, Class<E> entityClass)
      Convert the given LIMS id to a full URI for that entity.

      This method is for the most common entities in the API where the URIs are simply of the form <endpoint>/<limsid>.

      Specified by:
      limsIdToUri in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      limsid - The LIMS id of the entity required.
      entityClass - The class of the entity.
      Returns:
      The full URI to the entity.
      See Also:
    • makeUri

      protected <E extends Locatable> String makeUri(String limsid, Class<E> entityClass, String method)
      Convert the given LIMS id to a full URI for that entity without creating a URI object.
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      limsid - The LIMS id of the entity required.
      entityClass - The class of the entity.
      method - The name of the calling method.
      Returns:
      The full URI to the entity as a string.
      Throws:
      IllegalArgumentException - if either argument is null, or if entityClass is annotated with a primary section attribute.
      See Also:
    • limsIdToUri

      public <E extends Locatable> URI limsIdToUri(String outerLimsid, String innerLimsid, Class<E> entityClass)
      Convert the given LIMS ids to a full URI for that entity.

      This method is for use on entities that have been annotated to indicate they are part of a larger entity, for example ProtocolStep within Protocol or Stage within Workflow.

      Specified by:
      limsIdToUri in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      outerLimsid - The LIMS id of the outer endpoint of the URI.
      innerLimsid - The LIMS id of the inner endpoint of the URI.
      entityClass - The class of the entity.
      Returns:
      The full URI to the entity.
    • makeUri

      protected <E extends Locatable> String makeUri(String outerLimsid, String innerLimsid, Class<E> entityClass, String method)
      Convert the given LIMS ids to a full URI for that entity without creating a URI object.
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      outerLimsid - The LIMS id of the outer endpoint of the URI.
      innerLimsid - The LIMS id of the inner endpoint of the URI.
      entityClass - The class of the entity.
      method - The name of the calling method.
      Returns:
      The full URI to the entity as a string.
      Throws:
      IllegalArgumentException - if any argument is null, or if entityClass is not annotated with a primary section attribute.
      See Also:
    • nextCallCacheOverride

      @Deprecated public void nextCallCacheOverride(CacheStatefulBehaviour behaviour)
      Deprecated.
      This method was used to overrides the cache behaviour for the next call on the same thread. It has been replaced by ClarityAPI.overrideStateful(StatefulOverride) which does the correct thing. Momentarily changing how the cache worked didn't solve the problem this was intended for (up to date QC flags on artifacts).

      The values map as:

      1. CacheStatefulBehaviour.EXACT becomes StatefulOverride.EXACT.
      2. CacheStatefulBehaviour.LATEST becomes StatefulOverride.LATEST.
      3. CacheStatefulBehaviour.ANY or null clears the override.
      Specified by:
      nextCallCacheOverride in interface ClarityAPI
      Parameters:
      behaviour - The cache behaviour for the next call from the current thread.
    • overrideStateful

      public void overrideStateful(StatefulOverride override)
      Forces the API to fetch stateful entities according to the rule given for the next API call only. Full details on the ClarityAPI description.
      Specified by:
      overrideStateful in interface ClarityAPI
      Parameters:
      override - The behaviour to use in the next call. If null, it will cancel a previously set override.
      See Also:
    • getStatefulOverride

      public StatefulOverride getStatefulOverride()
      Helper method for the cache, this method returns whether the next call on the current thread will need to fetch stateful entities in a special way or not.
      Specified by:
      getStatefulOverride in interface ClarityAPIInternal
      Returns:
      The rule for the next call to the API for stateful entities. Will return null if there is no override.
    • cancelStatefulOverride

      public void cancelStatefulOverride(String calledMethod)
      Undoes the effects of ClarityAPI.overrideStateful(StatefulOverride) after a call to ensure subsequent calls will respect the state parameter for stateful entities. Called by the wrapping aspect after any public method to make sure the behaviour is reset.
      Specified by:
      cancelStatefulOverride in interface ClarityAPIInternal
      Parameters:
      calledMethod - The name of the method that caused this to be called. This is provided by the surrounding join point. It is not important and only used for debug logging.
      See Also:
    • listAll

      public <E extends Locatable> List<LimsLink<E>> listAll(Class<E> entityClass)
      List all the objects of the given entity class.
      Specified by:
      listAll in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      entityClass - The type of entity to list.
      Returns:
      A list of links to the real entities in the LIMS.
    • listSome

      public <E extends Locatable> List<LimsLink<E>> listSome(Class<E> entityClass, int startIndex, int number)
      List an arbitrary number of objects of the given entity class. This is not all that helpful for most real applications but can be very handy for test cases.
      Specified by:
      listSome in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      entityClass - The type of entity to list.
      startIndex - The index of the first item to fetch. This start number is zero-based.
      number - The number of items to fetch.
      Returns:
      A list of links to the real entities in the LIMS. This may be fewer in number than number if there are too few items to fetch.
    • find

      public <E extends Locatable> List<LimsLink<E>> find(Map<String,?> searchTerms, Class<E> entityClass)
      Search for entities of the given type based on name value pairs. The query string is built up from the search terms. Where the term value is an array or collection, the term is added multiple times which Clarity interprets as an OR. For example, if the map contains:
       "projectname" : [ "projectA", "projectB" ]
       
      then the search will be for entities whose projectname attribute is "projectA" or "projectB".
      Specified by:
      find in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      searchTerms - The terms to use for the search.
      entityClass - The type of entity to list.
      Returns:
      A list of links to the real entities in the LIMS.
    • retrieve

      public <E extends Locatable> E retrieve(String uri, Class<E> entityClass)
      Retrieve an entity using a String form of its URI.

      Note that when this method is used (as opposed to its equivalent taking a URI object) Spring's REST template performs escaping on the URI string so that special characters are sent to be literally that character. This is typically what is wanted for a first call, but using this method to navigate from the server's response can cause problems (especially with searches). Subsequent calls using links returned from the server should use the variant of this method that accepts a URI object.

      Specified by:
      retrieve in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      uri - The URI to retrieve, in string form.
      entityClass - The type of entity to list.
      Returns:
      The LIMS entity.
      See Also:
    • retrieve

      public <E extends Locatable> E retrieve(URI uri, Class<E> entityClass)
      Retrieve an entity by its URI.
      Specified by:
      retrieve in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      uri - The URI to retrieve.
      entityClass - The type of entity to list.
      Returns:
      The LIMS entity.
      See Also:
    • load

      public <E extends Locatable> E load(String limsid, Class<E> entityClass)
      Load an entity by its LIMS id. The URI of the object is created based on this interface's currently set server address, the type of the object requested and the LIMS id given.
      Specified by:
      load in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      limsid - The LIMS id of the entity.
      entityClass - The type of entity to list.
      Returns:
      The LIMS entity.
    • load

      public <E extends Locatable> E load(String outerLimsid, String innerLimsid, Class<E> entityClass)
      Load an entity by its two required LIMS ids. The URI of the object is created based on this interface's currently set server address, the type of the object requested and the LIMS ids given.

      This method is for use on entities that have been annotated to indicate they are part of a larger entity, for example ProtocolStep within Protocol or Stage within Workflow.

      Specified by:
      load in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      outerLimsid - The LIMS id of the outer endpoint of the URI.
      innerLimsid - The LIMS id of the inner endpoint of the URI.
      entityClass - The type of entity to list.
      Returns:
      The LIMS entity.
    • load

      public <E extends Locatable> E load(LimsLink<E> link)
      Load an entity using a link to that entity. Typically, the link object will come from a search or another object already fetched from the LIMS.
      Specified by:
      load in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      link - The link to the LIMS entity.
      Returns:
      The LIMS entity.
    • loadAll

      public <E extends Locatable> List<E> loadAll(Collection<? extends LimsLink<E>> links)
      Fetch a collection of LIMS entities given in the collection. The order of the returned entities is the same as the iteration order of the links collection.

      Using this method to fetch several entities at once can be beneficial where the Clarity API allows batch fetching of objects. Rather than making a call for each link, the links are collected into a single call whose response is all the entities for the links. For those entities where this is not possible, a call is made for each link. The end result is the same.

      Specified by:
      loadAll in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      links - The collection of links to the entities.
      Returns:
      A list of the LIMS entities.
    • reload

      public <E extends LimsEntity<E>> void reload(E entity)
      Reload an entity in-situ. The given object is refreshed from the server.
      Specified by:
      reload in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity referred to.
      Parameters:
      entity - The LimsEntity to refresh.
    • create

      public <E extends Locatable> void create(E entity)
      Create an instance of the given entity on the server.

      When successful, the entity's fields are all updated based on the values returned in the call's response, so the entity will accurately reflect the object on the server.

      When used with Sample objects, those objects must have an initial location specified using their Sample.setCreationLocation(com.genologics.ri.Location) method.

      Specified by:
      create in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity.
      Parameters:
      entity - The entity object to create in the LIMS.
    • createAll

      public <E extends Locatable> void createAll(Collection<E> entities)
      Create a batch of entities on the server.

      When successful, the entities' fields are all updated based on the values returned in the call's response, so each entity will accurately reflect the equivalent object on the server.

      When used with Sample objects, those objects must have an initial location specified using their Sample.setCreationLocation(com.genologics.ri.Location) method.

      Using this method to create several entities at once can be beneficial where the Clarity API allows batch creation of objects. Rather than making a call for each object, the objects are collected into a single call whose response is information on the entities now present in the server. For those entities where this is not possible, a call is made for each object. The end result is the same.

      Specified by:
      createAll in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity.
      Parameters:
      entities - The entity objects to create in the LIMS.
    • update

      public <E extends Locatable> void update(E entity)
      Update the given entity on the server. The fields that can be updated differ between entities: refer to the Clarity REST documentation for details.

      When successful, the entity's fields are all updated based on the values returned in the call's response, so the entity will accurately reflect the object on the server.

      Specified by:
      update in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity.
      Parameters:
      entity - The entity to update.
    • updateAll

      public <E extends Locatable> void updateAll(Collection<E> entities)
      Updates a batch of entities.

      When successful, the entities' fields are all updated based on the values returned in the call's response, so each entity will accurately reflect the equivalent object on the server.

      Using this method to update several entities at once can be beneficial where the Clarity API allows batch update of objects. Rather than making a call for each object, the objects are collected into a single call whose response is information on the entities now present in the server. For those entities where this is not possible, a call is made for each object. The end result is the same.

      Specified by:
      updateAll in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity.
      Parameters:
      entities - The entities to update.
    • delete

      public <E extends Locatable> void delete(E entity)
      Deletes an entity from the server.

      When successful, the entity object should no longer be used.

      Specified by:
      delete in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity.
      Parameters:
      entity - The entity to delete.
    • deleteAll

      public <E extends Locatable> void deleteAll(Collection<E> entities)
      Deletes a batch of entities from the server.

      When successful, the entity objects should no longer be used.

      Specified by:
      deleteAll in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity.
      Parameters:
      entities - The entities to delete.
    • executeProcess

      public ClarityProcess executeProcess(ExecutableProcess toExecute)
      Execute a process within the LIMS. The given executable process object needs to be set up carefully for this to work. Refer to the Clarity documentation.
      Specified by:
      executeProcess in interface ClarityAPI
      Parameters:
      toExecute - The executable process with all the information of what is to run.
      Returns:
      The ClarityProcess object reflecting the process record in the LIMS.
      See Also:
    • beginProcessStep

      public ProcessStep beginProcessStep(StepCreation stepCreation)
      Start a protocol step as if running through Clarity.
      Specified by:
      beginProcessStep in interface ClarityAPI
      Parameters:
      stepCreation - The step creation object. See Genologics' API documentation.
      Returns:
      The ProcessStep object for the step started.
      See Also:
    • advanceProcessStep

      public void advanceProcessStep(ProcessStep step)
      Move the process step to its next stage.

      Note that how the step advances is very dependent on the state it is currently in. For example, one may have to set values on the Actions object and update that before a step can advance past "next steps". Again, refer to the API documentation.

      Specified by:
      advanceProcessStep in interface ClarityAPI
      Parameters:
      step - The step to advance. The state of this object is updated in place.
      See Also:
    • startProgram

      public ProgramStatus startProgram(AvailableProgram program)
      Start execution of an EPP as part of a process step moving through Clarity.
      Specified by:
      startProgram in interface ClarityAPI
      Parameters:
      program - The program, as listed in the ProcessStep object.
      Returns:
      An updated program status structure.
      See Also:
    • currentStatus

      public void currentStatus(ProgramStatus status)
      Get an updated program status from Clarity.
      Specified by:
      currentStatus in interface ClarityAPI
      Parameters:
      status - The program status to update. The object is updated in place with the latest values.
    • uploadFile

      public <E extends LimsEntity<E>> ClarityFile uploadFile(LimsEntityLinkable<E> entity, URL fileURL, boolean publishInLablink) throws IOException
      Attach a file to an entity and upload that file to the file store.

      The client can be configured to use either the existing SFTP mechanism for the upload or the HTTP upload end point added in Clarity 4.0. Care should be taken with this choice, as the older mechanism is either safer or more problematic, depending on one's viewpoint.

      Uploading over HTTP has the additional issue that adding a file to a completed process fails. This is not a restriction of the SFTP upload.

      There is a maximum size that Clarity will accept for a file uploaded over HTTP (see ClarityAPI.setHttpUploadSizeLimit(long)). The client can be configured to drop back to SFTP if this size is exceeded. Alternatively it can be configured to never use the HTTP mechanism or to fail if the file is too big.

      Specified by:
      uploadFile in interface ClarityAPI
      Type Parameters:
      E - The type of LIMS entity the file is being attached to.
      Parameters:
      entity - The LIMS entity to attach the file to.
      fileURL - The URL of the file (relative to the local file system where relevant). This forms the original location part of the file record.
      publishInLablink - Whether the file should be displayed in the LabLink interface.
      Returns:
      The file record in the Clarity LIMS.
      Throws:
      IOException - if the file read or write fails.
      See Also:
    • uploadViaHTTP

      protected void uploadViaHTTP(URLInputStreamResource fileURLResource, ClarityFile targetFile) throws IOException
      Upload a file to the Clarity file store. This always uses the HTTP protocol with the file/id/upload end point.
      Parameters:
      fileURLResource - The URL resource of the file on the local machine.
      targetFile - The ClarityFile object that holds the reference to the uploaded file, which was newly created using the API.
      Throws:
      ClarityException - if the server reports a problem with the upload.
      IllegalStateException - if targetFile does not have a LIMS id.
      IOException - if there is a problem with the transfer.
      InvalidURIException - if the upload URI string isn't a valid URI (shouldn't happen).
    • uploadViaSFTP

      protected void uploadViaSFTP(URLInputStreamResource fileURLResource, ClarityFile targetFile) throws IOException
      Upload a file to the Clarity file store. This always uses the SFTP protocol.
      Parameters:
      fileURLResource - The URL resource of the file on the local machine.
      targetFile - The ClarityFile object that holds the reference to the uploaded file, which was newly created using the API.
      Throws:
      IOException - if there is a problem with the transfer.
      IllegalStateException - if the file store host name or credentials are not set.
    • downloadFile

      public void downloadFile(Linkable<ClarityFile> file, OutputStream resultStream) throws IOException
      Download the given file from its source. Its content is written out to resultStream.
      Specified by:
      downloadFile in interface ClarityAPI
      Parameters:
      file - The file to fetch.
      resultStream - The OutputStream to write the file content to.
      Throws:
      IOException - if there is a problem with the download.
    • deleteAndRemoveFile

      public void deleteAndRemoveFile(Linkable<ClarityFile> file) throws IOException
      Delete a file from the file store and remove its record from the LIMS. If the file is not in the file store, only its record is removed.
      Specified by:
      deleteAndRemoveFile in interface ClarityAPI
      Parameters:
      file - The file to delete.
      Throws:
      IOException - if there is a problem removing the file from the file store.
    • routeArtifacts

      public void routeArtifacts(Routing routing)
      Issue a routing request for artifacts into workflows. Routing is a funny object that is post only and doesn't fit with "create".
      Specified by:
      routeArtifacts in interface ClarityAPI
      Parameters:
      routing - The Routing object that has been assembled.
    • listQueue

      public List<LimsEntityLink<Artifact>> listQueue(Linkable<ProtocolStep> protocolStep)
      List the artifacts in the queue for the given protocol step.
      Specified by:
      listQueue in interface ClarityAPI
      Parameters:
      protocolStep - The protocol step of the queue (or a link to it).
      Returns:
      Links to the artifacts currently in the given queue.
    • listQueue

      public List<LimsEntityLink<Artifact>> listQueue(Linkable<ProtocolStep> protocolStep, Map<String,?> searchTerms)
      List the artifacts in the queue for the given protocol step, additionally filtering using the parameters available for the "queues" end point.

      Search terms work the same as for the ClarityAPI.find(Map, Class) method. Also see Genologics' documentation of this end point for the options available.

      Specified by:
      listQueue in interface ClarityAPI
      Parameters:
      protocolStep - The protocol step of the queue (or a link to it).
      searchTerms - The terms to use for the search.
      Returns:
      Links to the artifacts currently in the given queue that meet the criteria of the search terms.
    • toLinks

      protected Links toLinks(Collection<? extends Linkable<?>> entityLinks, boolean stripState)
      Create a Links object containing the URIs of the link objects given. Use in batch fetch operations.
      Parameters:
      entityLinks - The links to the entities.
      stripState - Whether to remove state version parameters from the URIs.
      Returns:
      A Links object containing the URIs.
    • expandSearchTerms

      protected StringBuilder expandSearchTerms(Map<String,?> searchTerms)
      Expand a map of search terms into a query string suitable for a URI. Handles values that are arrays or collections by repeating the parameter for each value.
      Parameters:
      searchTerms - The terms to use for the search. A null value here is the same as an empty map.
      Returns:
      The query string created from the search terms.
      Throws:
      IllegalSearchTermException - if any term in searchTerms is found to be illegal. See IllegalSearchTermException for details of what is illegal.
      See Also:
    • reflectiveCollectionUpdate

      protected <E extends Locatable> void reflectiveCollectionUpdate(Collection<E> originals, List<E> retrieved)
      Update a collection of original entities with the fields from an equivalent list of freshly retrieved versions of the same entities.

      Callers should expect that the collections really do contain the same entities in the same order in both collections. The method will fail if the collections are in a different order (comparison made on URI path).

      Type Parameters:
      E - The type of locatable entity.
      Parameters:
      originals - The collection of original entities.
      retrieved - The freshly retrieved list of the same entities.
      Throws:
      IllegalArgumentException - if either originals or retrieved are null; if the size of these two collections is not the same; if the order of items in retrieved is not the same as the order in originals.
      See Also:
    • reflectiveUpdate

      protected void reflectiveUpdate(Object original, Object updated)
      Reflectively set all the attributes in original to the values given by updated. This has the effect of making original the same as updated but without requiring the client code to change the object reference to original, which may be referenced in many places.

      Where a field is a Collection, the existing collection is emptied and all the objects from that field in updated are added in the same order to the collection in original. Whether this order is maintained depends on the type of collection in original (a list will maintain order, a set typically won't).

      Fields that are static, transient or final are ignored, as are any fields annotated with the @XmlTransient annotation.

      Note that fields within the original object that are objects themselves (as opposed to primitives) are replaced with the new versions. References to sub objects are therefore no longer valid.

      Parameters:
      original - The original object that was provided in the call and needs updating.
      updated - The version of the object returned from the LIMS with the current state.
      Throws:
      IllegalArgumentException - if either original or updated are null, or are of different classes.
    • reorderBatchFetchList

      protected <E extends Locatable> void reorderBatchFetchList(Collection<? extends Locatable> requestLinks, List<E> entities)
      Reorder a collection of entities into the same order given by their request objects. This is important as the batch fetch doesn't guarantee that the entities are returned in the same order as they were requested.

      The entities list is updated in-situ, and when this method returns will be in the same order as requestLinks.

      Type Parameters:
      E - The type of locatable entity.
      Parameters:
      requestLinks - The locatable links that were used to obtain the entities.
      entities - The fresh entities returned from the batch call.
    • idFromUri

      protected String idFromUri(Locatable thing)
      Get an identifier for a locatable object from its URI. This is the last part of the path of the URI and excludes the query string.
      Parameters:
      thing - The Locatable object.
      Returns:
      The id for the object from the URI.
    • removeStateParameter

      protected URI removeStateParameter(URI uri)
      Strip the state parameter from a URI.
      Parameters:
      uri - The original URI.
      Returns:
      The URI minus the state parameter.
      Throws:
      InvalidURIException - if the newly formed URI is somehow invalid. This shouldn't ever happen.
    • removeStateParameter

      protected String removeStateParameter(String uri)
      Strip the state parameter from a URI in string form.
      Parameters:
      uri - The original URI string.
      Returns:
      The URI minus the state parameter.
      Throws:
      InvalidURIException - if there is a problem parsing uri into a URI object.