Wstęp

Dokument w systemie PlusWorkflow zawiera informację o pliku(nazwa, rozmiar, wersja itp.) i indeksach (polach zdefiniowanych w klasie dokumentów). Dokumenty są zawsze zapisywane w archiwum systemowym. Mogą być również przypisywane do zadań. 

W systemie PlusWorkflow wersjonowane są wyłącznie pliki, a nie dokumenty. Plik zawsze posiada wersję, natomiast dokument odnosi się do najnowszej wersji pliku z którym jest powiązany.

Przydatne klasy: 

		DocumentService documentService = ServiceFactory.getDocumentService();
        DocumentFinder documentFinder = FinderFactory.getDocumentFinder();
		ActivityDocumentService activityDocumentService = ServiceFactory.getActivityDocumentService();

Operacje na dokumentach

Do wykonywania operacji na dokumentach należy używać usługi DocumentService. Umożliwia ona dodawania nowych dokumentów, zmianę indeksów, usunięcie, dołączanie lub odłączenie z/do procesu/zadania.

Przykłady:

  		InputStream inputStream = ...
 		DocumentClassService documentClassService=ServiceFactory.getDocumentClassService();
        DocumentService documentService=ServiceFactory.getDocumentService();        
		DocumentClass documentClass = documentClassService.getDocumentClass( "klasa" );
        
        Map<Long, Object> idx = new HashMap<Long, Object>();
        idx.put( 1L, "wartość tekstowa" );
        idx.put( 2L, 555 );
        idx.put( 3L, new Date() );
        DocumentDefinition definition = new DocumentDefinition();
        definition.setDocumentClassId( documentClass.getId() );
        definition.setFileName( "nazwa.pdf" );
        definition.setDescription( "opis" );
        definition.setUserName( "admin" );
        definition.setIndexes( idx );
        definition.setInputStream( inputStream );
        definition.setActivityId( "103_proces1_zadanie1" );//parametry opcjonalne jeżeli nie zostaną podane dokument zostanie dodany tylko do archiwum
        definition.setProcessId( "103_proces1" );// nie będzie dołączony do żadnego procesu
        WfDocument document = documentService.addDocument( definition );
documentService.attachDocumentToProcess( documentId, documentClassId, "admin", "103_proces1", "103_proces1_zadanie1" );// podajemy id dokumentu i id klasy
documentService.attachDocumentToProcess( wfDocument, "admin", "103_proces1", "103_proces1_zadanie1" );// lub obiekt dokumentu 
documentService.detachDocumentFromProcess( doc.getId(), doc.getDocumentClassId(), processId);// podajemy id dokumentu i id klasy
documentService.detachDocumentFromProcess( wfDocument, processId);// lub obiekt dokumentu
		WfDocument document = documentService.getDocument( documentId, documentClassId );
        IndexInfo indexInfo1 = document.getIndexByName( "idx1" );//pobieramy indeks po nazwie
        IndexInfo indexInfo2 = document.getIndexById( 1L );//pobieramy indeks po id
        Long id = indexInfo1.getId();// id indeksu
        String name = indexInfo1.getName();// nazwa indeksu
        IndexType type = indexInfo1.getType();// STRING, INTEGER, LIST, DATE, DOUBLE
        Object value = indexInfo1.getValue();// wartość indeksu, typ odpowiedni do IndexType
        
        if ( type == IndexType.DATE )
        {
            Date dateValue = (Date) value;
        }
        else if ( type == IndexType.LONG )
        {
            Long longValue = (Long) value;
        }
        else if ( type == IndexType.DOUBLE )
        {
            Double doubleValue = (Double) value;
        }
        else
        {// STRING lub LIST
            String stringValue = (String) value;
        }
        
        //Fukncje ułatwiajace dostęp do wartości indeksów:
        String stringValue=(String)document.getIndexValue( "idx1" );
        Date dateValue=(Date)document.getIndexValue( 1L );

 

		 WfDocument document = documentService.getDocument( documentId, documentClassId );
        
         IndexInfo indexInfo1 = document.getIndexByName( "idx1" );// pobieramy indeks po nazwie
         
         //ustawienie wartości indeksów
         indexInfo1.setValue( "abc" );//typ STRING
         document.setIndexValue( 2L,new Date() );//poprzez id, typ DATE
         document.setIndexValue( "idx3",333L );//poprzez nazwę, typ LONG
         document.setIndexValue("idx4",0.4);//type DOUBLE
         //Typy wprowadzanych wartości muszą odpowiadać typom indeksów 

         documentService.updateDocument( document );//funkcja zapisuje zmiany w bazie danych


Wyszukiwanie dokumentów

Do wyszukiwania dokumentów należy używać klasy DocumentFinder

		DocumentFinder documentFinder=FinderFactory.getDocumentFinder();		
 
		Map<Long, Object> idx = new HashMap<Long, Object>();
        idx.put( 1L, "wartość tekstowa" );
        idx.put( 2L, 555 );
        idx.put( 3L, new Date() );//wartości indeksów po których chcemy wyszukiwać
        List<Sorter> sorters=new ArrayList<Sorter>();
        sorters.add( new Sorter("3",SortDirection.DESC) );//sorujemy malejąco po indeksie o id 3
        CountedResult<WfDocument> result=documentFinder.findByIndexes( documentClassId, idx, sorters, start, limit );
        long total=result.getTotal();//liczba wszystkich pasujących dokumentów
        List<WfDocument> documents=result.getData();//lista znalezionych dokumentów ograniczona przez start i limit

Metoda getDocumentsFromProcess pobiera dokumenty dołączone tylko do ostatniego zadania procesu tj. takiego, które ostatnie zmieniło swój stan.

Co może to mieć znaczenie w przypadku występowania zadań równoległych. Bowiem dokumenty zostaną pobrane tylko z jednego zadania tj. tego które było zmienione ostatnie. Natomiast możliwość pobrania dokumentów z więcej niż jednego zadania daje metoda getDocumentsFromOpenedActivities, która pobiera dokumenty z podanego procesu podłączone do wszystkich otwartych zadań.



Przedstawiona wyżej metoda wyszukuje dokumenty o indeksach równych (operator '=' )  podanym wartościom i wszystkie warunki łączy operatorem logicznym AND. Jeżeli chcemy stworzyć bardziej zaawansowane warunki wyszukiwania możemy wykorzystać następującą metodę:

		DocumentFinder documentFinder = FinderFactory.getDocumentFinder();

        List<IndexFilter> filters = new ArrayList<IndexFilter>();
        filters.add( new SimpleIndexFilter( 3L, date, FilterOperator.GT ) );//Greater then '>'
        filters.add( new SimpleIndexFilter( 1L, "%test%", FilterOperator.LIKE ) );//definiujemy operatory wyszukiwania 
        CountedResult<WfDocument> result = documentFinder.findByIndexes( documentClassId, filters, sorters, start, limit );

W powyższym przykładzie zdefiniowaliśmy operatory wyszukiwania, lecz warunki nadal są połączone logicznym operatorem AND. Aby to zmienić możemy wykorzystać grupowanie filtrów:

 		List<IndexFilter> filters = new ArrayList<IndexFilter>();
        GroupIndexFilter gif = new GroupIndexFilter( LogicOperator.OR );//tworzymy grupę warunków połączonych operatorem OR
        gif.addFilter( new SimpleIndexFilter( 3L, date, FilterOperator.GT ) );
        gif.addFilter( new SimpleIndexFilter( 1L, "%test%", FilterOperator.LIKE ) );
        
        GroupIndexFilter subGroup=new GroupIndexFilter(LogicOperator.AND);// tworzymy kolejną grupę warunków
        subGroup.addFilter( new SimpleIndexFilter( 5L, "abc") );
        subGroup.addFilter( new SimpleIndexFilter( 2L, 555 ) );
        gif.addFilter( subGroup );//do grupy warunków możmy dodać inną grupę tworząc drzewo warunków
        
        filters.add( gif );
        CountedResult<WfDocument> result = documentFinder.findByIndexes( documentClassId, filters, sorters, start, limit );

Powyższy przykład utworzy następujący warunek: idx_3 > date OR idx_1 = '%test' OR ( idx_5 = 'abc' AND idx_2 = 555 )

 

        CountedResult<WfDocument> result = documentFinder.findByIndexes( documentClassId, filters, sorters, start, limit, WfDocument.JOIN_DOC_CLASS );
		List<WfDocument> docs= documentFinder.getDocumentsFromActivity( processId, activityId, WfDocument.JOIN_DOC_CLASS );
		WfDocument doc=docs.get(0);
		String documentClassName=doc.getFile().getDocumentClass().getName();//bez podania WfDocument.JOIN_DOC_CLASS wywołanie tej linii spowodowałoby błąd

Podając argument WfDocument.JOIN_DOC_CLASS dołączymy informacje o klasie dokumentów.

  

Wyszukiwanie i zarządzanie dokumentami w zadaniach/procesach

Do zarządzania dokumentami i ich wyszukiwania w zadaniach oraz pobierania szczegółowych informacji o nich można używać usługi ActivityDocumentService.
Umożliwia ona :

  • pobranie informacji o podłączonych dokumentach (w tym informacje o : zadaniach, procesach, plikach, wersji pliku oraz użytkowniku który podłączył)
  • sprawdzenie czy jest podłączony co najmniej jeden dokument
  • odłączenie wszystkich dokumentów
  • odłączanie dokumentu z procesu/zadania
  • odłączenie pliku
  • modyfikację dokumentu
  • przepisanie dokumentu z zadania do kolejnych zadań
  • wyszukiwanie dokumentów wg kryteriów
     
    Szczegóły dostępne w najnowszym javadoc.

ActivityDocumentService ads = ServiceFactory.getActivityDocumentService();
Long fileId = 100L;
List<ActivityDocument> documents = ads.getActivityDocuments( fileId, ActivityDocument.JOIN_USER );

Drugi parametr jest opcjonalny.
Jeśli w zwróconych obiektach, któreś informacje nie są wypełnione to w zależności od potrzeb trzeba jako dodatkowe parametry podać stałe z ActivityDocument: JOIN_USER, JOIN_VERSION, JOIN_FILE, JOIN_PROCESS, JOIN_ACTIVITY.
Można podać więcej niż jedną stałą, dodając je jako kolejne parametry.

Do wyszukiwania dokumentów wg kryteriów dostępne są usługi : findOne, findByCriteria, getAll, getCountedResult itp.

Implementacja

 WfDocument

Klasa WfDocument reprezentuje dokument w systemie. Tworzy powiązanie między klasami WfFileWfFileVersion oraz indeksami dokumentu(wartościami z tabeli pm_idx_000x).

WfFile

Klasa WfFile reprezentuje plik w systemie. Zawiera podstawowe informacje o pliku.

WfFileVersion

Klasa WfFileVersion reprezentuje wersję pliku w systemie. Relacja między obiektami WfFile, a WfFileVersion to 1-do-1

Introduction

A document in PlusWorkflow contains information about the file (name, size, version, etc.) and indexes (fields defined in the document class). Documents are always saved in the system archive. They can also be assigned to tasks.

In PlusWorkflow, only files are versioned, not documents. A file always has a version, while a document refers to the latest version of the file it is associated with.

 Useful classes:

		DocumentService documentService = ServiceFactory.getDocumentService();
        DocumentFinder documentFinder = FinderFactory.getDocumentFinder();
		ActivityDocumentService activityDocumentService = ServiceFactory.getActivityDocumentService();

Operations on documents

Use DocumentService to perform operations on documents. It allows you to add new documents, change indexes, delete, attach or detach from/to a process/task.

Examples:

  		InputStream inputStream = ...
 		DocumentClassService documentClassService=ServiceFactory.getDocumentClassService();
        DocumentService documentService=ServiceFactory.getDocumentService();        
		DocumentClass documentClass = documentClassService.getDocumentClass( "klasa" );
        
        Map<Long, Object> idx = new HashMap<Long, Object>();
        idx.put( 1L, "wartość tekstowa" );
        idx.put( 2L, 555 );
        idx.put( 3L, new Date() );
        DocumentDefinition definition = new DocumentDefinition();
        definition.setDocumentClassId( documentClass.getId() );
        definition.setFileName( "nazwa.pdf" );
        definition.setDescription( "opis" );
        definition.setUserName( "admin" );
        definition.setIndexes( idx );
        definition.setInputStream( inputStream );
        definition.setActivityId( "103_proces1_zadanie1" );//optional parameters if not specified the document will only be added to the archive
        definition.setProcessId( "103_proces1" );// will not be attached to any process
        WfDocument document = documentService.addDocument( definition );
documentService.attachDocumentToProcess( documentId, documentClassId, "admin", "103_proces1", "103_proces1_zadanie1" );// specify document id and class id
documentService.attachDocumentToProcess( wfDocument, "admin", "103_proces1", "103_proces1_zadanie1" );// or document object
documentService.detachDocumentFromProcess( doc.getId(), doc.getDocumentClassId(), processId);// specify document id and class id
documentService.detachDocumentFromProcess( wfDocument, processId);// or document object
		WfDocument document = documentService.getDocument( documentId, documentClassId );
        IndexInfo indexInfo1 = document.getIndexByName( "idx1" );//download the index by name
        IndexInfo indexInfo2 = document.getIndexById( 1L );//download the index by id
        Long id = indexInfo1.getId();// id indeksu
        String name = indexInfo1.getName();// index name
        IndexType type = indexInfo1.getType();// STRING, INTEGER, LIST, DATE, DOUBLE
        Object value = indexInfo1.getValue();// index value, type appropriate to IndexType
        
        if ( type == IndexType.DATE )
        {
            Date dateValue = (Date) value;
        }
        else if ( type == IndexType.LONG )
        {
            Long longValue = (Long) value;
        }
        else if ( type == IndexType.DOUBLE )
        {
            Double doubleValue = (Double) value;
        }
        else
        {// STRING lub LIST
            String stringValue = (String) value;
        }
        
        //Fucnctions to facilitate access to index values:
        String stringValue=(String)document.getIndexValue( "idx1" );
        Date dateValue=(Date)document.getIndexValue( 1L );

 

		 WfDocument document = documentService.getDocument( documentId, documentClassId );
        
         IndexInfo indexInfo1 = document.getIndexByName( "idx1" );// download the index by name
         
         //ustawienie wartości indeksów
         indexInfo1.setValue( "abc" );//typ STRING
         document.setIndexValue( 2L,new Date() );//by id, type DATE
         document.setIndexValue( "idx3",333L );//by name, type LONG
         document.setIndexValue("idx4",0.4);//type DOUBLE
         //The types of values to be entered must match the index types

         documentService.updateDocument( document );//function saves changes to the database


Document Search

Use the DocumentFinder class to search for documents

		DocumentFinder documentFinder=FinderFactory.getDocumentFinder();		
 
		Map<Long, Object> idx = new HashMap<Long, Object>();
        idx.put( 1L, "wartość tekstowa" );
        idx.put( 2L, 555 );
        idx.put( 3L, new Date() );//index values by which we want to search
        List<Sorter> sorters=new ArrayList<Sorter>();
        sorters.add( new Sorter("3",SortDirection.DESC) );//sort descending by index with id 3
        CountedResult<WfDocument> result=documentFinder.findByIndexes( documentClassId, idx, sorters, start, limit );
        long total=result.getTotal();//number of all matching documents
        List<WfDocument> documents=result.getData();//list of documents found limited by start and limit

The getDocumentsFromProcess method retrieves documents attached only to the last process task, i.e. the one that last changed its state.

This may be important if there are parallel tasks. Because the documents will be retrieved only from one task, i.e. the one that was changed last. On the other hand, the ability to retrieve documents from more than one task is provided by the getDocumentsFromOpenedActivities method, which retrieves documents from the specified process connected to all open tasks.



The method presented above searches for documents with indexes equal (operator '=' ) to the given values and combines all conditions with the logical operator AND. If you want to create more advanced search conditions, you can use the following method:

		DocumentFinder documentFinder = FinderFactory.getDocumentFinder();

        List<IndexFilter> filters = new ArrayList<IndexFilter>();
        filters.add( new SimpleIndexFilter( 3L, date, FilterOperator.GT ) );//Greater then '>'
        filters.add( new SimpleIndexFilter( 1L, "%test%", FilterOperator.LIKE ) );//define search operators
        CountedResult<WfDocument> result = documentFinder.findByIndexes( documentClassId, filters, sorters, start, limit );

In the above example, we have defined search operators, but the conditions are still connected by a logical AND operator. To change this, we can use filter grouping:

 		List<IndexFilter> filters = new ArrayList<IndexFilter>();
        GroupIndexFilter gif = new GroupIndexFilter( LogicOperator.OR );//create a group of conditions connected by OR operator
        gif.addFilter( new SimpleIndexFilter( 3L, date, FilterOperator.GT ) );
        gif.addFilter( new SimpleIndexFilter( 1L, "%test%", FilterOperator.LIKE ) );
        
        GroupIndexFilter subGroup=new GroupIndexFilter(LogicOperator.AND);// create another group of conditions
        subGroup.addFilter( new SimpleIndexFilter( 5L, "abc") );
        subGroup.addFilter( new SimpleIndexFilter( 2L, 555 ) );
        gif.addFilter( subGroup );//to a group of conditions we can add another group creating a tree of conditions
        
        filters.add( gif );
        CountedResult<WfDocument> result = documentFinder.findByIndexes( documentClassId, filters, sorters, start, limit );

The above example will create the following condition: idx_3 > date OR idx_1 = '%test' OR ( idx_5 = 'abc' AND idx_2 = 555 )

 

        CountedResult<WfDocument> result = documentFinder.findByIndexes( documentClassId, filters, sorters, start, limit, WfDocument.JOIN_DOC_CLASS );
		List<WfDocument> docs= documentFinder.getDocumentsFromActivity( processId, activityId, WfDocument.JOIN_DOC_CLASS );
		WfDocument doc=docs.get(0);
		String documentClassName=doc.getFile().getDocumentClass().getName();//Without specifying WfDocument.JOIN_DOC_CLASS, calling this line would result in an error

Specifying the WfDocument.JOIN_DOC_CLASS argument will include the document class information.

  

Searching and managing documents in tasks/processes

 

You can use ActivityDocumentService to manage and search for documents in tasks and retrieve detailed information about them.

 

It allows you to :

  • downloading information about connected documents (including information about: tasks, processes, files, file version and user who connected)
  • check if at least one document is connected
  • disconnecting all documents
  • disconnecting a document from a process/task
  • disconnecting a file
  • document modification
  • rewriting a document from a task to subsequent tasks
  • searching for documents according to criteria

 
 
Details available in the latest javadoc.

ActivityDocumentService ads = ServiceFactory.getActivityDocumentService();
Long fileId = 100L;
List<ActivityDocument> documents = ads.getActivityDocuments( fileId, ActivityDocument.JOIN_USER );

The second parameter is optional.

If in the returned objects, some information is not filled in then, depending on your needs, you need to provide constants from ActivityDocument as additional parameters: JOIN_USER, JOIN_VERSION, JOIN_FILE, JOIN_PROCESS, JOIN_ACTIVITY.

You can specify more than one constant by adding them as further parameters.

For searching documents by criteria, services are available : findOne, findByCriteria, getAll, getCountedResult, etc.


Implementation

 WfDocument

 The WfDocument class represents a document in the system. It creates a link between the classes WfFile, WfFileVersion and the indexes of the document(values from the pm_idx_000x table).

WfFile

The WfFile class represents a file in the system. It contains basic information about the file.

WfFileVersion

The WfFileVersion class represents the version of a file in the system. The relationship between WfFile objects and WfFileVersion is 1-to-1.