Class DocumentService

java.lang.Object
org.imixs.workflow.engine.DocumentService

@DeclareRoles({"org.imixs.ACCESSLEVEL.NOACCESS","org.imixs.ACCESSLEVEL.READERACCESS","org.imixs.ACCESSLEVEL.AUTHORACCESS","org.imixs.ACCESSLEVEL.EDITORACCESS","org.imixs.ACCESSLEVEL.MANAGERACCESS"}) @RolesAllowed({"org.imixs.ACCESSLEVEL.NOACCESS","org.imixs.ACCESSLEVEL.READERACCESS","org.imixs.ACCESSLEVEL.AUTHORACCESS","org.imixs.ACCESSLEVEL.EDITORACCESS","org.imixs.ACCESSLEVEL.MANAGERACCESS"}) public class DocumentService extends Object
The DocumentService is used to save and load instances of ItemCollections into a Database. The DocumentService throws an AccessDeniedException if the CallerPrincipal is not allowed to save or read a specific Document from the database. So the DocumentService can be used to save business objects into a database with individual read- or writeAccess restrictions.

The Bean holds an instance of an EntityPersistenceManager for the persistence unit 'org.imixs.workflow.jpa' to manage the Document entity bean class. The Document entity bean is used to store the attributes of a ItemCollection into the connected database.

The save() method persists any instance of an ItemCollection. If a ItemCollection is saved the first time the DocumentService generates the attribute $uniqueid which will be included in the ItemCollection returned by this method. If a ItemCollection was saved before the method updates the corresponding Document Object.

The load() and find() methods are used to read ItemCollections from the database. The remove() method deletes a saved ItemCollection from the database.

All methods expect and return Instances of the object org.imixs.workflow.ItemCollection which is no entity EJB. So these objects are not managed by any instance of an EntityPersistenceManager.

A collection of ItemCollections can be read using the find() method using EQL syntax.

Additional to the basic functionality to save and load instances of the object org.imixs.workflow.ItemCollection the method also manages the read- and writeAccess for each instance of an ItemCollection. Therefore the save() method scans an ItemCollection for the attributes '$ReadAccess' and '$WriteAccess'. The DocumentService verifies in each call of the save() load(), remove() and find() methods if the current callerPrincipal is granted to the affected entities. If an ItemCollection was saved with read- or writeAccess the access to an Instance of a saved ItemCollection will be protected for a callerPrincipal with missing read- or writeAccess.

Version:
1.0
Author:
rsoika
See Also:
  • Field Details

  • Constructor Details

    • DocumentService

      public DocumentService()
  • Method Details

    • getAccessRoles

      public String getAccessRoles()
      Returns a comma separated list of additional Access-Roles defined for this service
      Returns:
    • setAccessRoles

      public void setAccessRoles(String accessRoles)
    • setDisableOptimisticLocking

      public void setDisableOptimisticLocking(Boolean disableOptimisticLocking)
      returns the disable optimistic locking status
    • getDisableOptimisticLocking

      public Boolean getDisableOptimisticLocking()
    • getUserNameList

      public List<String> getUserNameList()
      This method returns a list of user names, roles and application groups the user belongs to.

      A client can extend the list of user groups associated with a userId by reacting on the CDI event 'UserGrouptEvent'.

      Returns:
      See Also:
    • isUserContained

      public boolean isUserContained(List<?> nameList)
      This method returns true, if at least one element of the current UserNameList is contained in a given name list. The comparison is case sensitive!
      Parameters:
      nameList -
      Returns:
    • isUserInRole

      public boolean isUserInRole(String rolename)
      Test if the caller has a given security role.
      Parameters:
      rolename -
      Returns:
      true if user is in role
    • save

      public ItemCollection save(ItemCollection document) throws AccessDeniedException
      This Method saves an ItemCollection into the database. If the ItemCollection is saved the first time the method generates a uniqueID ('$uniqueid') which can be used to identify the ItemCollection by its ID. If the ItemCollection was saved before, the method updates the existing ItemCollection stored in the database.

      The Method returns an updated instance of the ItemCollection containing the attributes $modified, $created, and $uniqueId

      The method throws an AccessDeniedException if the CallerPrincipal is not allowed to save or update the ItemCollection in the database. The CallerPrincipial should have at least the access Role org.imixs.ACCESSLEVEL.AUTHORACCESS

      The method adds/updates the document into the lucene index.

      The method returns a itemCollection without the $VersionNumber from the persisted entity. (see issue #226)

      issue #230: The document will be marked as 'saved' so that the methods load() and getDocumentsByQuery() can evaluate this flag. Depending on the state, the methods can decide the correct behavior. In general we detach a document in the load() and getDocumentsByQuery() method. This is for performance reasons and the fact, that a ItemCollection can hold byte arrays which will be copied by reference. In cases where these methods are called after a document was saved (document is now managed), in one single transaction, the detach call will discard the changes made by the save() method. For that reason we flag the entity and evaluate this flag in the load method evaluates the save status.

      Parameters:
      ItemCollection - to be saved
      Returns:
      updated ItemCollection
      Throws:
      AccessDeniedException
    • addDocumentToIndex

      public void addDocumentToIndex(ItemCollection document)
      This method adds a single document into the to the Lucene index. Before the document is added to the index, a new eventLog is created. The document will be indexed after the method flushEventLog is called. This method is called by the LuceneSearchService finder methods.

      The method supports committed read. This means that a running transaction will not read an uncommitted document from the Lucene index.

      Parameters:
      documentContext -
    • removeDocumentFromIndex

      public void removeDocumentFromIndex(String uniqueID)
      This method adds a new eventLog for a document to be deleted from the index. The document will be removed from the index after the method fluschEventLog is called. This method is called by the LuceneSearchService finder method only.
      Parameters:
      uniqueID - of the workitem to be removed
      Throws:
      PluginException
    • saveByNewTransaction

      public ItemCollection saveByNewTransaction(ItemCollection itemcol) throws AccessDeniedException
      This method saves a workitem in a new transaction. The method can be used by plugins to isolate a save request from the current transaction context. To call this method a EJB session context is necessary: workitem= sessionContext.getBusinessObject(EntityService.class) .saveByNewTransaction(workitem);
      Parameters:
      itemcol -
      Returns:
      Throws:
      AccessDeniedException
    • load

      public ItemCollection load(String id)
      This method loads an ItemCollection from the Database. The method expects a valid $uniqueID to identify the Document entity saved before into the database. The method returns null if no Document with the corresponding ID exists.

      The method checks if the CallerPrincipal has read access to Document stored in the database. If not, the method returns null.

      Note: The method dose not throw an AccessDeniedException if the user is not allowed to read the entity to prevent a aggressor with informations about the existence of that specific Document.

      The CallerPrincipial need to have at least the access level org.imixs.ACCESSLEVEL.READACCESS

      issue #230 In case a document is not flagged (not saved during same transaction), we detach the loaded entity. In case a document is flagged (saved during save transaction) we may not detach it, but make a deepCopy (clone) of the document instance. This will avoid the effect, that data written to a document get lost in a long running transaction with save and load calls.

      Parameters:
      id - - the $uniqueid of the ItemCollection to be loaded
      Returns:
      ItemCollection object or null if the Document dose not exist or the CallerPrincipal hat insufficient read access.
    • remove

      public void remove(ItemCollection document) throws AccessDeniedException
      This method removes an ItemCollection from the database. If the CallerPrincipal is not allowed to access the ItemColleciton the method throws an AccessDeniedException.

      The CallerPrincipial should have at least the access Role org.imixs.ACCESSLEVEL.AUTHORACCESS

      Also the method removes the document form the lucene index.

      Parameters:
      ItemCollection - to be removed
      Throws:
      AccessDeniedException
    • count

      public int count(String searchTerm) throws QueryException
      Returns the total hits for a given search query. The provided search term will be extended with a users roles to test the read access level of each workitem matching the search term. The usernames and user roles will be search lowercase!
      Parameters:
      sSearchTerm -
      Returns:
      total hits of search result
      Throws:
      QueryException - in case the searchterm is not understandable.
      See Also:
      • search(String, int, int, Sort, Operator)
    • count

      public int count(String sSearchTerm, int maxResult) throws QueryException
      Returns the total hits for a given search query. The provided search term will be extended with a users roles to test the read access level of each workitem matching the search term. The usernames and user roles will be search lowercase! The optional param 'maxResult' can be set to overwrite the DEFAULT_MAX_SEARCH_RESULT.
      Parameters:
      sSearchTerm -
      maxResult - - max search result
      defaultOperator - - optional to change the default search operator
      Returns:
      total hits of search result
      Throws:
      QueryException - in case the searchterm is not understandable.
      See Also:
      • search(String, int, int, Sort, Operator)
    • countPages

      public int countPages(String searchTerm, int pageSize) throws QueryException
      Returns the total pages for a given search term and a given page size.
      Parameters:
      searchTerm -
      pageSize -
      Returns:
      total pages of search result
      Throws:
      QueryException - in case the searchterm is not understandable.
      See Also:
    • find

      public List<ItemCollection> find(String searchTerm, int pageSize, int pageIndex) throws QueryException
      The method returns a list of ItemCollections from the search-index. The method expects an valid Lucene search term.

      The method returns only ItemCollections which are readable by the CallerPrincipal. With the pageSize and pageNumber it is possible to paginate.

      The Transactiontype REQUIRES_NEW ensure that during the processing lifecycle an external service call did not overwrite the current document jpa object (see Issue #634)

      Parameters:
      searchTerm - - Lucene search term
      pageSize - - total docs per page
      pageIndex - - number of page to start (default = 0)
      Returns:
      list of ItemCollection elements
      Throws:
      QueryException
      See Also:
    • find

      public List<ItemCollection> find(String searchTerm, int pageSize, int pageIndex, String sortBy, boolean sortReverse) throws QueryException
      The method returns a sorted list of ItemCollections from the search-index. The result list can be sorted by a sortField and a sort direction.

      The method expects an valid Lucene search term. The method returns only ItemCollections which are readable by the CallerPrincipal. With the pageSize and pageNumber it is possible to paginate.

      The Transactiontype REQUIRES_NEW ensure that during the processing lifecycle an external service call did not overwrite the current document jpa object (see Issue #634)

      Parameters:
      searchTerm - - Lucene search term
      pageSize - - total docs per page
      pageIndex - - number of page to start (default = 0)
      sortBy - -optional field to sort the result
      sortReverse - - optional sort direction
      Returns:
      list of ItemCollection elements
      Throws:
      QueryException
      See Also:
    • findStubs

      public List<ItemCollection> findStubs(String searchTerm, int pageSize, int pageIndex, String sortBy, boolean sortReverse) throws QueryException
      The method returns a sorted list of Document Stubs from the search-index. A document stub contains only the items stored in the search index. These items can be defined by the property lucence.indexFieldListStore. See the LuceneUpdateService for details.

      The result list can be sorted by a sortField and a sort direction.

      The method expects an valid Lucene search term. The method returns only ItemCollections which are readable by the CallerPrincipal. With the pageSize and pageNumber it is possible to paginate.

      Parameters:
      searchTerm - - Lucene search term
      pageSize - - total docs per page
      pageIndex - - number of page to start (default = 0)
      sortBy - -optional field to sort the result
      sortReverse - - optional sort direction
      Returns:
      list of ItemCollection elements
      Throws:
      QueryException
      See Also:
    • findDocumentsByRef

      public List<ItemCollection> findDocumentsByRef(String uniqueIdRef, int pageSize, int pageIndex)
      The method returns a collection of ItemCollections referred by a $uniqueid.

      The method returns only ItemCollections which are readable by the CallerPrincipal. With the pageSize and pageNumber it is possible to paginate.

      The Transactiontype REQUIRES_NEW ensure that during the processing lifecycle an external service call did not overwrite the current document jpa object (see Issue #634)

      Parameters:
      uniqueIdRef - - $uniqueId to be referred by the collected documents
      pageSize - - total docs per page
      pageIndex - - number of page to start (default = 0)
      Returns:
      resultset
    • getDocumentsByType

      public List<ItemCollection> getDocumentsByType(String type)
      Returns an unordered list of all documents of a specific type. The method throws an InvalidAccessException in case no type attribute is defined.

      The Transactiontype REQUIRES_NEW ensure that during the processing lifecycle an external service call did not overwrite the current document jpa object (see Issue #634)

      Parameters:
      type -
      Returns:
      Throws:
      InvalidAccessException
    • getDocumentsByQuery

      public List<ItemCollection> getDocumentsByQuery(String query)
      Returns all documents of by JPQL statement

      The Transactiontype REQUIRES_NEW ensure that during the processing lifecycle an external service call did not overwrite the current document jpa object (see Issue #634)

      Parameters:
      query - - JPQL statement
      Returns:
    • getDocumentsByQuery

      public List<ItemCollection> getDocumentsByQuery(String query, int maxResult)
      Returns all documents of by JPQL statement.

      The Transactiontype REQUIRES_NEW ensure that during the processing lifecycle an external service call did not overwrite the current document jpa object (see Issue #634)

      Parameters:
      query - - JPQL statement
      maxResult - - maximum result set
      Returns:
    • getDocumentsByQuery

      public List<ItemCollection> getDocumentsByQuery(String query, int firstResult, int maxResult)
      Returns all documents of by JPQL statement.

      The Transactiontype REQUIRES_NEW ensure that during the processing lifecycle an external service call did not overwrite the current document jpa object (see Issue #634)

      Parameters:
      query - - JPQL statement
      firstResult - - first result
      maxResult - - maximum result set
      Returns:
      - result set
    • backup

      public void backup(String query, String filePath, boolean snapshots) throws IOException, QueryException
      This method creates a backup of the result set form a Lucene search query. The document list will be stored into the file system. The method stores the Map from the ItemCollection to be independent from version upgrades. To manage large dataSets the method reads the documents in smaller blocks

      The optional parameter 'snapshots' can be set to 'true' to indicate that only the referred snapshot workitem should be stored. The snapshot is referred by the item $snapshotId.

      Parameters:
      query - - a Lucene search statement
      filePath - - the target file path in the server local file system
      snapshots - - optional - if true, than only snapshots will be backuped. Default = false
      Throws:
      IOException
      QueryException
    • backup

      public void backup(String query, String filePath) throws IOException, QueryException
      Throws:
      IOException
      QueryException
    • restore

      public void restore(String filePath) throws IOException
      This method restores a backup from the file system and imports the Documents into the database.
      Parameters:
      filepath -
      Throws:
      IOException
    • isAuthor

      public boolean isAuthor(ItemCollection itemcol)
      Verifies if the caller has write access to the current ItemCollection
      Returns:
    • isEmptyList

      public boolean isEmptyList(List<String> aList)
      This method returns true if the given list is empty or contains only null or '' values.
      Parameters:
      aList -
      Returns:
    • isValidUIDPattern

      public boolean isValidUIDPattern(String uid)
      This method returns true if the given id is a valid UUID or SnapshotID (UUI + timestamp

      We also need to support the old uid formats 4832b09a1a-20c38abd-1519421083952

      Parameters:
      uid -
      Returns: