From d198d8c859463ffc1476a8fb526072ca5f4535c4 Mon Sep 17 00:00:00 2001 From: Ralph Soika Date: Mon, 6 Jan 2020 14:29:11 +0100 Subject: [PATCH] formatting and license --- .../faces/data/AbstractDataController.java | 304 ++-- .../faces/data/DocumentController.java | 264 +-- .../workflow/faces/data/ViewController.java | 364 ++-- .../workflow/faces/data/ViewHandler.java | 170 +- .../faces/data/WorkflowController.java | 678 ++++---- .../workflow/faces/data/WorkflowEvent.java | 80 +- .../fileupload/AjaxFileUploadServlet.java | 590 +++---- .../fileupload/FileUploadController.java | 379 ++--- .../workflow/faces/util/ErrorHandler.java | 314 ++-- .../workflow/faces/util/LoginController.java | 222 +-- .../faces/util/SelectItemComparator.java | 45 +- .../faces/util/ValidationException.java | 48 +- .../workflow/faces/util/VectorConverter.java | 83 +- .../faces/util/VectorIntegerConverter.java | 76 +- .../util/ViewExpiredExceptionHandler.java | 87 +- .../ViewExpiredExceptionHandlerFactory.java | 38 +- .../workflow/jaxrs/AdminPRestService.java | 278 ++-- .../workflow/jaxrs/BPMNUnmarshaller.java | 73 +- .../jaxrs/DocumentCollectionWriter.java | 73 +- .../workflow/jaxrs/DocumentRestService.java | 1033 ++++++------ .../workflow/jaxrs/DocumentTableWriter.java | 132 +- .../workflow/jaxrs/EventLogRestService.java | 106 +- .../workflow/jaxrs/ModelRestService.java | 814 +++++---- .../workflow/jaxrs/ReportRestService.java | 992 ++++++----- .../imixs/workflow/jaxrs/RootRestService.java | 47 +- .../workflow/jaxrs/WorkflowRestService.java | 1461 ++++++++--------- .../jaxrs/XMLItemCollectionWriter.java | 299 ++-- 27 files changed, 4495 insertions(+), 4555 deletions(-) diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/AbstractDataController.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/AbstractDataController.java index 9e423b2a3..f386b9960 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/AbstractDataController.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/AbstractDataController.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.data; @@ -45,12 +44,14 @@ import org.imixs.workflow.engine.DocumentService; /** - * This is the abstract base class for the CDI beans DocumentController and WorkflowController. + * This is the abstract base class for the CDI beans DocumentController and + * WorkflowController. *

- * To load a document the methods load(id) and onLoad() can be used. The method load expects the - * uniqueId of a document to be loaded. The onLoad() method extracts the uniqueid from the query - * parameter 'id'. This is the recommended way to support bookmarkable URLs. To load a document the - * onLoad method can be triggered by an jsf viewAction placed in the header of a JSF page: + * To load a document the methods load(id) and onLoad() can be used. The method + * load expects the uniqueId of a document to be loaded. The onLoad() method + * extracts the uniqueid from the query parameter 'id'. This is the recommended + * way to support bookmarkable URLs. To load a document the onLoad method can be + * triggered by an jsf viewAction placed in the header of a JSF page: * *

  * {@code
@@ -63,7 +64,8 @@
  * 

* {@code /myForm.xthml?id=[UNIQUEID] } *

- * In combination with the viewAction the DocumentController is automatically initialized. + * In combination with the viewAction the DocumentController is automatically + * initialized. *

* https://stackoverflow.com/questions/6377798/what-can-fmetadata-fviewparam-and-fviewaction-be-used-for * @@ -73,149 +75,153 @@ */ public abstract class AbstractDataController implements Serializable { - private static final long serialVersionUID = 1L; - private static Logger logger = Logger.getLogger(AbstractDataController.class.getName()); - - private String defaultType; - - @Inject - private Conversation conversation; - - protected ItemCollection data = null; - - @Inject - private DocumentService documentService; - - /** - * This method returns the Default 'type' attribute of the local workitem. - */ - public String getDefaultType() { - return defaultType; - } - - /** - * This method set the default 'type' attribute of the local workitem. - * - * Subclasses may overwrite the type - * - * @param type - */ - public void setDefaultType(String type) { - this.defaultType = type; - } - - /** - * Reset current document - */ - public void reset() { - data = new ItemCollection(); - data.replaceItemValue("type", getDefaultType()); - } - - /** - * Returns true if the current document was never saved before by the DocumentService. This is - * indicated by the time difference of $modified and $created. - * - * @return - */ - public boolean isNewWorkitem() { - if (data == null) { - return false; - } - Date created = data.getItemValueDate("$created"); - Date modified = data.getItemValueDate("$modified"); - return (modified == null || created == null); - } - - /** - * This method can be used to add a Error Messege to the Application Context during an - * actionListener Call. Typical this method is used in the doProcessWrktiem method to display a - * processing exception to the user. The method expects the Ressoruce bundle name and the message - * key inside the bundle. - * - * @param ressourceBundleName - * @param messageKey - * @param param - */ - public void addMessage(String ressourceBundleName, String messageKey, Object param) { - FacesContext context = FacesContext.getCurrentInstance(); - Locale locale = context.getViewRoot().getLocale(); - - ResourceBundle rb = ResourceBundle.getBundle(ressourceBundleName, locale); - String msgPattern = rb.getString(messageKey); - String msg = msgPattern; - if (param != null) { - Object[] params = {param}; - msg = MessageFormat.format(msgPattern, params); + private static final long serialVersionUID = 1L; + private static Logger logger = Logger.getLogger(AbstractDataController.class.getName()); + + private String defaultType; + + @Inject + private Conversation conversation; + + protected ItemCollection data = null; + + @Inject + private DocumentService documentService; + + /** + * This method returns the Default 'type' attribute of the local workitem. + */ + public String getDefaultType() { + return defaultType; } - FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg); - context.addMessage(null, facesMsg); - } - - /** - * This method extracts a $uniqueid from the query param 'id' and loads the workitem. After the - * workitm was loaded, a new conversation is started. - *

- * The method is not running during a JSF Postback of in case of a JSF validation error. - */ - public void onLoad() { - logger.finest("......onload..."); - FacesContext facesContext = FacesContext.getCurrentInstance(); - if (!facesContext.isPostback() && !facesContext.isValidationFailed()) { - // ... - FacesContext fc = FacesContext.getCurrentInstance(); - Map paramMap = fc.getExternalContext().getRequestParameterMap(); - // try to extract the uniqueid form the query string... - String uniqueid = paramMap.get("id"); - if (uniqueid == null || uniqueid.isEmpty()) { - // alternative 'workitem=...' - uniqueid = paramMap.get("workitem"); - } - load(uniqueid); + + /** + * This method set the default 'type' attribute of the local workitem. + * + * Subclasses may overwrite the type + * + * @param type + */ + public void setDefaultType(String type) { + this.defaultType = type; } - } - - /** - * Loads a workitem by a given $uniqueid and starts a new conversaton. The conversaion will be - * ended after the workitem was processed or after the MaxInactiveInterval from the session. - * - * @param uniqueid - */ - public void load(String uniqueid) { - if (uniqueid != null && !uniqueid.isEmpty()) { - logger.finest("......load uniqueid=" + uniqueid); - data = documentService.load(uniqueid); - if (data == null) { + + /** + * Reset current document + */ + public void reset() { data = new ItemCollection(); - } - startConversation(); + data.replaceItemValue("type", getDefaultType()); + } + + /** + * Returns true if the current document was never saved before by the + * DocumentService. This is indicated by the time difference of $modified and + * $created. + * + * @return + */ + public boolean isNewWorkitem() { + if (data == null) { + return false; + } + Date created = data.getItemValueDate("$created"); + Date modified = data.getItemValueDate("$modified"); + return (modified == null || created == null); + } + + /** + * This method can be used to add a Error Messege to the Application Context + * during an actionListener Call. Typical this method is used in the + * doProcessWrktiem method to display a processing exception to the user. The + * method expects the Ressoruce bundle name and the message key inside the + * bundle. + * + * @param ressourceBundleName + * @param messageKey + * @param param + */ + public void addMessage(String ressourceBundleName, String messageKey, Object param) { + FacesContext context = FacesContext.getCurrentInstance(); + Locale locale = context.getViewRoot().getLocale(); + + ResourceBundle rb = ResourceBundle.getBundle(ressourceBundleName, locale); + String msgPattern = rb.getString(messageKey); + String msg = msgPattern; + if (param != null) { + Object[] params = { param }; + msg = MessageFormat.format(msgPattern, params); + } + FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg); + context.addMessage(null, facesMsg); + } + /** + * This method extracts a $uniqueid from the query param 'id' and loads the + * workitem. After the workitm was loaded, a new conversation is started. + *

+ * The method is not running during a JSF Postback of in case of a JSF + * validation error. + */ + public void onLoad() { + logger.finest("......onload..."); + FacesContext facesContext = FacesContext.getCurrentInstance(); + if (!facesContext.isPostback() && !facesContext.isValidationFailed()) { + // ... + FacesContext fc = FacesContext.getCurrentInstance(); + Map paramMap = fc.getExternalContext().getRequestParameterMap(); + // try to extract the uniqueid form the query string... + String uniqueid = paramMap.get("id"); + if (uniqueid == null || uniqueid.isEmpty()) { + // alternative 'workitem=...' + uniqueid = paramMap.get("workitem"); + } + load(uniqueid); + } } - } - - /** - * Closes the current conversation and reset the data item. A conversation is automatically - * started by the methods load() and onLoad(). You can call the close() method in a actionListener - * on any JSF navigation action. - */ - public void close() { - if (!conversation.isTransient()) { - logger.finest("......stopping conversation, id=" + conversation.getId()); - conversation.end(); + + /** + * Loads a workitem by a given $uniqueid and starts a new conversaton. The + * conversaion will be ended after the workitem was processed or after the + * MaxInactiveInterval from the session. + * + * @param uniqueid + */ + public void load(String uniqueid) { + if (uniqueid != null && !uniqueid.isEmpty()) { + logger.finest("......load uniqueid=" + uniqueid); + data = documentService.load(uniqueid); + if (data == null) { + data = new ItemCollection(); + } + startConversation(); + + } } - } - - /** - * Starts a new conversation - */ - protected void startConversation() { - if (conversation.isTransient()) { - conversation.setTimeout( - ((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()) - .getSession().getMaxInactiveInterval() * 1000); - conversation.begin(); - logger.finest("......start new conversation, id=" + conversation.getId()); + + /** + * Closes the current conversation and reset the data item. A conversation is + * automatically started by the methods load() and onLoad(). You can call the + * close() method in a actionListener on any JSF navigation action. + */ + public void close() { + if (!conversation.isTransient()) { + logger.finest("......stopping conversation, id=" + conversation.getId()); + conversation.end(); + } + } + + /** + * Starts a new conversation + */ + protected void startConversation() { + if (conversation.isTransient()) { + conversation.setTimeout( + ((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()) + .getSession().getMaxInactiveInterval() * 1000); + conversation.begin(); + logger.finest("......start new conversation, id=" + conversation.getId()); + } } - } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/DocumentController.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/DocumentController.java index 1c57dea4e..95c3bac34 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/DocumentController.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/DocumentController.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *

- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.data; @@ -42,18 +41,20 @@ import org.imixs.workflow.exceptions.AccessDeniedException; /** - * The DocumentController is a @ConversationScoped CDI bean to control the life cycle of a - * ItemCollection in an JSF application without any workflow functionality. The bean can be used in - * single page applications, as well for complex page flows. The controller is easy to use and - * supports bookmarkable URLs. + * The DocumentController is a @ConversationScoped CDI bean to control the life + * cycle of a ItemCollection in an JSF application without any workflow + * functionality. The bean can be used in single page applications, as well for + * complex page flows. The controller is easy to use and supports bookmarkable + * URLs. *

- * The DocumentController fires CDI events from the type WorkflowEvent. A CDI bean can observe these - * events to participate in the processing life cycle. + * The DocumentController fires CDI events from the type WorkflowEvent. A CDI + * bean can observe these events to participate in the processing life cycle. *

- * To load a document the methods load(id) and onLoad() can be used. The method load expects the - * uniqueId of a document to be loaded. The onLoad() method extracts the uniqueid from the query - * parameter 'id'. This is the recommended way to support bookmarkable URLs. To load a document the - * onLoad method can be triggered by an jsf viewAction placed in the header of a JSF page: + * To load a document the methods load(id) and onLoad() can be used. The method + * load expects the uniqueId of a document to be loaded. The onLoad() method + * extracts the uniqueid from the query parameter 'id'. This is the recommended + * way to support bookmarkable URLs. To load a document the onLoad method can be + * triggered by an jsf viewAction placed in the header of a JSF page: * *

  * {@code
@@ -66,26 +67,29 @@
  * 

* {@code /myForm.xthml?id=[UNIQUEID] } *

- * In combination with the viewAction the DocumentController is automatically initialized. + * In combination with the viewAction the DocumentController is automatically + * initialized. *

* After a document is loaded, a new conversation is started and the CDI event * WorkflowEvent.DOCUMENT_CHANGED is fired. *

- * After a document was saved, the conversation is automatically closed. Stale conversations will - * automatically timeout with the default session timeout. + * After a document was saved, the conversation is automatically closed. Stale + * conversations will automatically timeout with the default session timeout. *

- * After each call of the method save the Post-Redirect-Get is initialized with the default URL from - * the start of the conversation. This guarantees bookmakrable URLs. + * After each call of the method save the Post-Redirect-Get is initialized with + * the default URL from the start of the conversation. This guarantees + * bookmakrable URLs. *

- * Within a JSF form, the items of a document can be accessed by the getter method getDocument(). + * Within a JSF form, the items of a document can be accessed by the getter + * method getDocument(). * *

  *   #{documentController.document.item['$workflowstatus']}
  * 
* *

- * The default type of a entity created with the DataController is 'workitem'. This property can be - * changed from a client. + * The default type of a entity created with the DataController is 'workitem'. + * This property can be changed from a client. * * * @@ -97,123 +101,119 @@ @ConversationScoped public class DocumentController extends AbstractDataController implements Serializable { - private static final long serialVersionUID = 1L; - private static Logger logger = Logger.getLogger(DocumentController.class.getName()); - - @Inject - protected Event events; + private static final long serialVersionUID = 1L; + private static Logger logger = Logger.getLogger(DocumentController.class.getName()); - @Inject - private DocumentService documentService; + @Inject + protected Event events; - public DocumentController() { - super(); - setDefaultType("workitem"); - } + @Inject + private DocumentService documentService; + public DocumentController() { + super(); + setDefaultType("workitem"); + } + /** + * Returns the current workItem. If no workitem is defined the method + * Instantiates a empty ItemCollection. + * + * @return - current workItem or null if not set + */ + public ItemCollection getDocument() { + // do initialize an empty workItem here if null + if (data == null) { + reset(); + } + return data; + } - /** - * Returns the current workItem. If no workitem is defined the method Instantiates a empty - * ItemCollection. - * - * @return - current workItem or null if not set - */ - public ItemCollection getDocument() { - // do initialize an empty workItem here if null - if (data == null) { - reset(); + /** + * Set the current worktItem + * + * @param workitem - new reference or null to clear the current workItem. + */ + public void setDocument(ItemCollection document) { + this.data = document; } - return data; - } - - /** - * Set the current worktItem - * - * @param workitem - new reference or null to clear the current workItem. - */ - public void setDocument(ItemCollection document) { - this.data = document; - } - - /** - * This method creates an empty workItem with the default type property and the property - * '$Creator' holding the current RemoteUser This method should be overwritten to add additional - * Business logic here. - * - */ - public void create() { - reset(); - // initialize new ItemCollection - FacesContext context = FacesContext.getCurrentInstance(); - ExternalContext externalContext = context.getExternalContext(); - String sUser = externalContext.getRemoteUser(); - data.replaceItemValue("$Creator", sUser); - data.replaceItemValue("namCreator", sUser); // backward compatibility - - startConversation(); - - events.fire(new WorkflowEvent(data, WorkflowEvent.DOCUMENT_CREATED)); - logger.finest("......document created"); - } - - /** - * This method saves the current document. - *

- * The method fires the WorkflowEvents WORKITEM_BEFORE_SAVE and WORKITEM_AFTER_SAVE. - * - * - * @throws AccessDeniedException - if user has insufficient access rights. - */ - public void save() throws AccessDeniedException { - - // save workItem ... - events.fire(new WorkflowEvent(data, WorkflowEvent.DOCUMENT_BEFORE_SAVE)); - data = documentService.save(data); - events.fire(new WorkflowEvent(data, WorkflowEvent.DOCUMENT_AFTER_SAVE)); - - // close conversation - close(); - - logger.finest("......ItemCollection saved"); - } - - - /** - * This action method deletes a workitem. The Method also deletes also all child workitems - * recursive - * - * @param currentSelection - workitem to be deleted - * @throws AccessDeniedException - */ - public void delete(String uniqueID) throws AccessDeniedException { - ItemCollection _workitem = documentService.load(uniqueID); - if (_workitem != null) { - events.fire(new WorkflowEvent(getDocument(), WorkflowEvent.DOCUMENT_BEFORE_DELETE)); - documentService.remove(_workitem); - events.fire(new WorkflowEvent(getDocument(), WorkflowEvent.DOCUMENT_AFTER_DELETE)); - setDocument(null); - logger.fine("......document " + uniqueID + " deleted"); - } else { - logger.fine("......document '" + uniqueID + "' not found (null)"); + + /** + * This method creates an empty workItem with the default type property and the + * property '$Creator' holding the current RemoteUser This method should be + * overwritten to add additional Business logic here. + * + */ + public void create() { + reset(); + // initialize new ItemCollection + FacesContext context = FacesContext.getCurrentInstance(); + ExternalContext externalContext = context.getExternalContext(); + String sUser = externalContext.getRemoteUser(); + data.replaceItemValue("$Creator", sUser); + data.replaceItemValue("namCreator", sUser); // backward compatibility + + startConversation(); + + events.fire(new WorkflowEvent(data, WorkflowEvent.DOCUMENT_CREATED)); + logger.finest("......document created"); } - } - - - /** - * Loads a workitem by a given $uniqueid and starts a new conversaton. The conversaion will be - * ended after the workitem was processed or after the MaxInactiveInterval from the session. - * - * @param uniqueid - */ - public void load(String uniqueid) { - super.load(uniqueid); - if (data != null) { - // fire event - events.fire(new WorkflowEvent(data, WorkflowEvent.DOCUMENT_CHANGED)); + + /** + * This method saves the current document. + *

+ * The method fires the WorkflowEvents WORKITEM_BEFORE_SAVE and + * WORKITEM_AFTER_SAVE. + * + * + * @throws AccessDeniedException - if user has insufficient access rights. + */ + public void save() throws AccessDeniedException { + + // save workItem ... + events.fire(new WorkflowEvent(data, WorkflowEvent.DOCUMENT_BEFORE_SAVE)); + data = documentService.save(data); + events.fire(new WorkflowEvent(data, WorkflowEvent.DOCUMENT_AFTER_SAVE)); + + // close conversation + close(); + + logger.finest("......ItemCollection saved"); } - } + /** + * This action method deletes a workitem. The Method also deletes also all child + * workitems recursive + * + * @param currentSelection - workitem to be deleted + * @throws AccessDeniedException + */ + public void delete(String uniqueID) throws AccessDeniedException { + ItemCollection _workitem = documentService.load(uniqueID); + if (_workitem != null) { + events.fire(new WorkflowEvent(getDocument(), WorkflowEvent.DOCUMENT_BEFORE_DELETE)); + documentService.remove(_workitem); + events.fire(new WorkflowEvent(getDocument(), WorkflowEvent.DOCUMENT_AFTER_DELETE)); + setDocument(null); + logger.fine("......document " + uniqueID + " deleted"); + } else { + logger.fine("......document '" + uniqueID + "' not found (null)"); + } + } + /** + * Loads a workitem by a given $uniqueid and starts a new conversaton. The + * conversaion will be ended after the workitem was processed or after the + * MaxInactiveInterval from the session. + * + * @param uniqueid + */ + public void load(String uniqueid) { + super.load(uniqueid); + if (data != null) { + // fire event + events.fire(new WorkflowEvent(data, WorkflowEvent.DOCUMENT_CHANGED)); + } + } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/ViewController.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/ViewController.java index e33704e77..0e7d003f2 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/ViewController.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/ViewController.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *

- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.data; @@ -42,13 +41,15 @@ import org.imixs.workflow.exceptions.QueryException; /** - * The ViewController can be used in JSF Applications to manage lists of ItemCollections. + * The ViewController can be used in JSF Applications to manage lists of + * ItemCollections. *

- * The view property defines the view type returned by a method call of loadData. The ViewController - * implements a lazy loading mechanism to cache the result. + * The view property defines the view type returned by a method call of + * loadData. The ViewController implements a lazy loading mechanism to cache the + * result. *

- * The property 'loadStubs' can be used to define if only the Document Stubs (default) or the full - * Document should be loaded. + * The property 'loadStubs' can be used to define if only the Document Stubs + * (default) or the full Document should be loaded. *

* The ViewController bean should be used in ViewScope. * @@ -59,177 +60,174 @@ @ViewScoped public class ViewController implements Serializable { - private static final long serialVersionUID = 1L; - - private String query = null; - private String sortBy = null; - private boolean sortReverse = false; - private int pageSize = 10; - private int pageIndex = 0; - private boolean endOfList = false; - private boolean loadStubs = true; - - - private static Logger logger = Logger.getLogger(ViewController.class.getName()); - - @Inject - private DocumentService documentService; - - public ViewController() { - super(); - logger.finest("...construct..."); - } - - @PostConstruct - public void init() { - logger.finest("init..."); - } - - /** - * Returns the search Query - * - * @return - */ - public String getQuery() { - return query; - } - - /** - * set the search query - * - * @param query - */ - public void setQuery(String query) { - this.query = query; - } - - public String getSortBy() { - return sortBy; - } - - public void setSortBy(String sortBy) { - this.sortBy = sortBy; - } - - public boolean isSortReverse() { - return sortReverse; - } - - public void setSortReverse(boolean sortReverse) { - this.sortReverse = sortReverse; - } - - /** - * returns the maximum size of a search result - * - * @return - */ - public int getPageSize() { - return pageSize; - } - - /** - * set the maximum size of a search result - * - * @param searchCount - */ - public void setPageSize(int pageSize) { - this.pageSize = pageSize; - } - - public boolean isLoadStubs() { - return loadStubs; - } - - public void setLoadStubs(boolean loadStubs) { - this.loadStubs = loadStubs; - } - - /** - * resets the current result and set the page pointer to 0. - * - * @return - */ - public void reset() { - pageIndex = 0; - } - - @Deprecated - public List getWorkitems() throws QueryException { - logger.warning("getWorkitems is deprected - replace with viewHandler#getData(viewController)"); - return null; - } - - /*************************************************************************** - * Navigation - */ - - public int getPageIndex() { - return pageIndex; - } - - public void setPageIndex(int pageIndex) { - this.pageIndex = pageIndex; - } - - public boolean isEndOfList() { - return endOfList; - } - - public void setEndOfList(boolean endOfList) { - this.endOfList = endOfList; - } - - /** - * Returns the current view result. The returned result set is defined by the current query - * definition. - *

- * The method implements a lazy loading mechanism and caches the result locally. - * - * @return view result - * @throws QueryException - */ - public List loadData() throws QueryException { - - String _query = getQuery(); - - if (_query == null || _query.isEmpty()) { - // no query defined - logger.warning("no query defined!"); - return new ArrayList(); - } - - // load data - logger.finest("...... load data - query=" + _query + " pageIndex=" + getPageIndex()); - - List result = null; - if (this.isLoadStubs()) { - result = documentService.findStubs(_query, getPageSize(), getPageIndex(), getSortBy(), - isSortReverse()); - - } else { - result = - documentService.find(_query, getPageSize(), getPageIndex(), getSortBy(), isSortReverse()); - - } - - // The end of a list is reached when the size is below or equal the - // pageSize. See issue #287 - if (result.size() < getPageSize()) { - setEndOfList(true); - } else { - // look ahead if we have more entries... - int iAhead = (getPageSize() * (getPageIndex() + 1)) + 1; - if (documentService.count(_query, iAhead) < iAhead) { - // there is no more data - setEndOfList(true); - } else { - setEndOfList(false); - } - } - - return result; - - } + private static final long serialVersionUID = 1L; + + private String query = null; + private String sortBy = null; + private boolean sortReverse = false; + private int pageSize = 10; + private int pageIndex = 0; + private boolean endOfList = false; + private boolean loadStubs = true; + + private static Logger logger = Logger.getLogger(ViewController.class.getName()); + + @Inject + private DocumentService documentService; + + public ViewController() { + super(); + logger.finest("...construct..."); + } + + @PostConstruct + public void init() { + logger.finest("init..."); + } + + /** + * Returns the search Query + * + * @return + */ + public String getQuery() { + return query; + } + + /** + * set the search query + * + * @param query + */ + public void setQuery(String query) { + this.query = query; + } + + public String getSortBy() { + return sortBy; + } + + public void setSortBy(String sortBy) { + this.sortBy = sortBy; + } + + public boolean isSortReverse() { + return sortReverse; + } + + public void setSortReverse(boolean sortReverse) { + this.sortReverse = sortReverse; + } + + /** + * returns the maximum size of a search result + * + * @return + */ + public int getPageSize() { + return pageSize; + } + + /** + * set the maximum size of a search result + * + * @param searchCount + */ + public void setPageSize(int pageSize) { + this.pageSize = pageSize; + } + + public boolean isLoadStubs() { + return loadStubs; + } + + public void setLoadStubs(boolean loadStubs) { + this.loadStubs = loadStubs; + } + + /** + * resets the current result and set the page pointer to 0. + * + * @return + */ + public void reset() { + pageIndex = 0; + } + + @Deprecated + public List getWorkitems() throws QueryException { + logger.warning("getWorkitems is deprected - replace with viewHandler#getData(viewController)"); + return null; + } + + /*************************************************************************** + * Navigation + */ + + public int getPageIndex() { + return pageIndex; + } + + public void setPageIndex(int pageIndex) { + this.pageIndex = pageIndex; + } + + public boolean isEndOfList() { + return endOfList; + } + + public void setEndOfList(boolean endOfList) { + this.endOfList = endOfList; + } + + /** + * Returns the current view result. The returned result set is defined by the + * current query definition. + *

+ * The method implements a lazy loading mechanism and caches the result locally. + * + * @return view result + * @throws QueryException + */ + public List loadData() throws QueryException { + + String _query = getQuery(); + + if (_query == null || _query.isEmpty()) { + // no query defined + logger.warning("no query defined!"); + return new ArrayList(); + } + + // load data + logger.finest("...... load data - query=" + _query + " pageIndex=" + getPageIndex()); + + List result = null; + if (this.isLoadStubs()) { + result = documentService.findStubs(_query, getPageSize(), getPageIndex(), getSortBy(), isSortReverse()); + + } else { + result = documentService.find(_query, getPageSize(), getPageIndex(), getSortBy(), isSortReverse()); + + } + + // The end of a list is reached when the size is below or equal the + // pageSize. See issue #287 + if (result.size() < getPageSize()) { + setEndOfList(true); + } else { + // look ahead if we have more entries... + int iAhead = (getPageSize() * (getPageIndex() + 1)) + 1; + if (documentService.count(_query, iAhead) < iAhead) { + // there is no more data + setEndOfList(true); + } else { + setEndOfList(false); + } + } + + return result; + + } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/ViewHandler.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/ViewHandler.java index 5601c2b97..b6f9f31ae 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/ViewHandler.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/ViewHandler.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *

- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.data; @@ -42,7 +41,8 @@ import org.imixs.workflow.exceptions.QueryException; /** - * The ViewHandler is a @RequestScoped CDI bean computing the result defined by a ViewController. + * The ViewHandler is a @RequestScoped CDI bean computing the result defined by + * a ViewController. * * @author rsoika * @version 0.0.1 @@ -51,94 +51,92 @@ @RequestScoped public class ViewHandler implements Serializable { - private static final long serialVersionUID = 1L; - - private Map> data = null; - - private static Logger logger = Logger.getLogger(ViewHandler.class.getName()); - - public ViewHandler() { - super(); - } - - @PostConstruct - public void init() { - logger.finest("......init data map"); - data = new HashMap>(); - } - - /** - * This method can be used in ajax forms to pre-compute the result set for further rendering. - * - * @param viewController - * @throws QueryException - */ - public void onLoad(ViewController viewController) throws QueryException { - getData(viewController); - } - - public void forward(ViewController viewController) { - data.remove(getHashKey(viewController)); - viewController.setPageIndex(viewController.getPageIndex() + 1); - } - - public void back(ViewController viewController) { - data.remove(getHashKey(viewController)); - int i = viewController.getPageIndex(); - i--; - if (i < 0) { - i = 0; - } - viewController.setPageIndex(i); - } - - /** - * Returns the current view result. The returned result set is defined by the current query - * definition. - *

- * The method implements a lazy loading mechanism and caches the result locally. - * - * @return view result - * @throws QueryException - */ - public List getData(ViewController viewController) throws QueryException { - - if (viewController == null) { - return new ArrayList(); - } + private static final long serialVersionUID = 1L; + + private Map> data = null; - String _query = viewController.getQuery(); - if (_query == null || _query.isEmpty()) { - // no query defined - logger.finest("......ViewController - no query defined!"); - return new ArrayList(); + private static Logger logger = Logger.getLogger(ViewHandler.class.getName()); + + public ViewHandler() { + super(); } - // Caching mechanism - verify if data is already cached - List result = data.get(getHashKey(viewController)); - if (result != null) { - // return a cached result set - return result; + @PostConstruct + public void init() { + logger.finest("......init data map"); + data = new HashMap>(); } - // load data - result = viewController.loadData(); - logger.finest("......cache with hash=" + getHashKey(viewController)); - // cache result - data.put(getHashKey(viewController), result); + /** + * This method can be used in ajax forms to pre-compute the result set for + * further rendering. + * + * @param viewController + * @throws QueryException + */ + public void onLoad(ViewController viewController) throws QueryException { + getData(viewController); + } - return result; - } + public void forward(ViewController viewController) { + data.remove(getHashKey(viewController)); + viewController.setPageIndex(viewController.getPageIndex() + 1); + } - private int getHashKey(ViewController viewController) { - if (viewController == null) { - return -1; + public void back(ViewController viewController) { + data.remove(getHashKey(viewController)); + int i = viewController.getPageIndex(); + i--; + if (i < 0) { + i = 0; + } + viewController.setPageIndex(i); } - String h = - viewController.getQuery() + viewController.getPageIndex() + viewController.getPageSize(); - return h.hashCode(); - } + /** + * Returns the current view result. The returned result set is defined by the + * current query definition. + *

+ * The method implements a lazy loading mechanism and caches the result locally. + * + * @return view result + * @throws QueryException + */ + public List getData(ViewController viewController) throws QueryException { + + if (viewController == null) { + return new ArrayList(); + } + + String _query = viewController.getQuery(); + if (_query == null || _query.isEmpty()) { + // no query defined + logger.finest("......ViewController - no query defined!"); + return new ArrayList(); + } + + // Caching mechanism - verify if data is already cached + List result = data.get(getHashKey(viewController)); + if (result != null) { + // return a cached result set + return result; + } + + // load data + result = viewController.loadData(); + logger.finest("......cache with hash=" + getHashKey(viewController)); + // cache result + data.put(getHashKey(viewController), result); + + return result; + } + private int getHashKey(ViewController viewController) { + if (viewController == null) { + return -1; + } + String h = viewController.getQuery() + viewController.getPageIndex() + viewController.getPageSize(); + return h.hashCode(); + } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/WorkflowController.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/WorkflowController.java index ac51eab39..789d663da 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/WorkflowController.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/WorkflowController.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *

- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.data; @@ -56,17 +55,19 @@ /** * - * The WorkflowController is a @ConversationScoped CDI bean to control the processing life cycle of - * a workitem in JSF an application. The bean can be used in single page applications, as well for - * complex page flows. The controller supports bookmarkable URLs. + * The WorkflowController is a @ConversationScoped CDI bean to control the + * processing life cycle of a workitem in JSF an application. The bean can be + * used in single page applications, as well for complex page flows. The + * controller supports bookmarkable URLs. *

- * The WorkflowController fires CDI events from the type WorkflowEvent. A CDI bean can observe these - * events to participate in the processing life cycle. + * The WorkflowController fires CDI events from the type WorkflowEvent. A CDI + * bean can observe these events to participate in the processing life cycle. *

- * To load a workitem the methods load(id) and onLoad() can be used. The method load expects a valid - * uniqueId of a workItem to be loaded. The onLoad() method extracts the uniqueid from the query - * parameter 'id'. This is the recommended way to support bookmarkable URLs when opening a JSF page - * with the data of a workitem. The onLoad method can be triggered by an jsf viewAction placed in + * To load a workitem the methods load(id) and onLoad() can be used. The method + * load expects a valid uniqueId of a workItem to be loaded. The onLoad() method + * extracts the uniqueid from the query parameter 'id'. This is the recommended + * way to support bookmarkable URLs when opening a JSF page with the data of a + * workitem. The onLoad method can be triggered by an jsf viewAction placed in * the header of a JSF page: * *

@@ -80,22 +81,26 @@
  * 

* {@code /myForm.xthml?id=[UNIQUEID] } *

- * In combination with the viewAction the WorkflowController is automatically initialized. + * In combination with the viewAction the WorkflowController is automatically + * initialized. *

* After a workitem is loaded, a new conversation is started and the CDI event * WorkflowEvent.WORKITEM_CHANGED is fired. *

- * After a workitem was processed, the conversation is automatically closed. Stale conversations - * will automatically timeout with the default session timeout. + * After a workitem was processed, the conversation is automatically closed. + * Stale conversations will automatically timeout with the default session + * timeout. *

- * After each call of the method process the Post-Redirect-Get is initialized with the default URL - * from the start of the conversation. If an alternative action result is provided by the workflow - * engine, the WorkflowController automatically redirects the user to the new form outcome. This - * guarantees bookmarkable URLs. + * After each call of the method process the Post-Redirect-Get is initialized + * with the default URL from the start of the conversation. If an alternative + * action result is provided by the workflow engine, the WorkflowController + * automatically redirects the user to the new form outcome. This guarantees + * bookmarkable URLs. *

* Call the close() method when the workitem data is no longer needed. *

- * Within a JSF form, the items of a workitem can be accessed by the getter method getWorkitem(). + * Within a JSF form, the items of a workitem can be accessed by the getter + * method getWorkitem(). * *

  *   #{workflowController.workitem.item['$workflowstatus']}
@@ -108,347 +113,346 @@
 @ConversationScoped
 public class WorkflowController extends AbstractDataController implements Serializable {
 
-  private static final long serialVersionUID = 1L;
-  private static Logger logger = Logger.getLogger(WorkflowController.class.getName());
-
-  @Inject
-  ModelService modelService;
+    private static final long serialVersionUID = 1L;
+    private static Logger logger = Logger.getLogger(WorkflowController.class.getName());
 
-  @Inject
-  WorkflowService workflowService;
+    @Inject
+    ModelService modelService;
 
-  @Inject
-  Event events;
+    @Inject
+    WorkflowService workflowService;
 
-  @Inject
-  LoginController loginController;
+    @Inject
+    Event events;
 
-  public static final String DEFAULT_TYPE = "workitem";
+    @Inject
+    LoginController loginController;
 
-  public WorkflowController() {
-    super();
-    setDefaultType("workitem");
-  }
+    public static final String DEFAULT_TYPE = "workitem";
 
-  /**
-   * Returns the current workItem. If no workitem is defined the method Instantiates a empty
-   * ItemCollection.
-   * 
-   * @return - current workItem or an emtpy workitem if not set
-   */
-  public ItemCollection getWorkitem() {
-    // do initialize an empty workItem here if null
-    if (data == null) {
-      reset();
+    public WorkflowController() {
+        super();
+        setDefaultType("workitem");
     }
-    return data;
-  }
-
-  /**
-   * Set the current worktItem
-   * 
-   * @param workitem - new reference or null to clear the current workItem.
-   */
-  public void setWorkitem(ItemCollection workitem) {
-    this.data = workitem;
-  }
-
-  /**
-   * This action method is used to initialize a new workitem with the initial values of the assigned
-   * workflow task. The method updates the Workflow attributes '$WriteAccess','$workflowgroup',
-   * '$workflowStatus', 'txtWorkflowImageURL' and 'txtWorkflowEditorid'.
-   * 
-   * @param action - the action returned by this method
-   * @return - action
-   * @throws ModelException is thrown in case not valid worklfow task if defined by the current
-   *                        model.
-   */
-  public void create() throws ModelException {
-
-    if (data == null) {
-      return;
+
+    /**
+     * Returns the current workItem. If no workitem is defined the method
+     * Instantiates a empty ItemCollection.
+     * 
+     * @return - current workItem or an emtpy workitem if not set
+     */
+    public ItemCollection getWorkitem() {
+        // do initialize an empty workItem here if null
+        if (data == null) {
+            reset();
+        }
+        return data;
     }
 
-    ItemCollection startProcessEntity = null;
-    // if no process id was set fetch the first start workitem
-    if (data.getTaskID() <= 0) {
-      // get ProcessEntities by version
-      List col;
-      col = modelService.getModelByWorkitem(getWorkitem()).findAllTasks();
-      if (!col.isEmpty()) {
-        startProcessEntity = col.iterator().next();
-        getWorkitem().setTaskID(startProcessEntity.getItemValueInteger("numProcessID"));
-      }
+    /**
+     * Set the current worktItem
+     * 
+     * @param workitem - new reference or null to clear the current workItem.
+     */
+    public void setWorkitem(ItemCollection workitem) {
+        this.data = workitem;
     }
 
-    // find the ProcessEntity
-    startProcessEntity = modelService.getModelByWorkitem(data).getTask(data.getTaskID());
+    /**
+     * This action method is used to initialize a new workitem with the initial
+     * values of the assigned workflow task. The method updates the Workflow
+     * attributes '$WriteAccess','$workflowgroup', '$workflowStatus',
+     * 'txtWorkflowImageURL' and 'txtWorkflowEditorid'.
+     * 
+     * @param action - the action returned by this method
+     * @return - action
+     * @throws ModelException is thrown in case not valid worklfow task if defined
+     *                        by the current model.
+     */
+    public void create() throws ModelException {
+
+        if (data == null) {
+            return;
+        }
 
-    // ProcessEntity found?
-    if (startProcessEntity == null) {
-      throw new InvalidAccessException(ModelException.INVALID_MODEL_ENTRY,
-          "unable to find ProcessEntity in model version " + data.getModelVersion() + " for ID="
-              + data.getTaskID());
-    }
+        ItemCollection startProcessEntity = null;
+        // if no process id was set fetch the first start workitem
+        if (data.getTaskID() <= 0) {
+            // get ProcessEntities by version
+            List col;
+            col = modelService.getModelByWorkitem(getWorkitem()).findAllTasks();
+            if (!col.isEmpty()) {
+                startProcessEntity = col.iterator().next();
+                getWorkitem().setTaskID(startProcessEntity.getItemValueInteger("numProcessID"));
+            }
+        }
 
-    // get type...
-    String type = startProcessEntity.getItemValueString("txttype");
-    if (type.isEmpty()) {
-      type = DEFAULT_TYPE;
-    }
-    data.replaceItemValue("type", type);
-
-    if (loginController != null) {
-      String user = loginController.getUserPrincipal();
-      // set creator
-      data.replaceItemValue(WorkflowKernel.CREATOR, user);
-      // support deprecated field
-      data.replaceItemValue("namcreator", user);
-
-      // set default owner
-      data.replaceItemValue(OwnerPlugin.OWNER, user);
-      // support deprecated field
-      data.replaceItemValue("namowner", user);
-    }
+        // find the ProcessEntity
+        startProcessEntity = modelService.getModelByWorkitem(data).getTask(data.getTaskID());
+
+        // ProcessEntity found?
+        if (startProcessEntity == null) {
+            throw new InvalidAccessException(ModelException.INVALID_MODEL_ENTRY,
+                    "unable to find ProcessEntity in model version " + data.getModelVersion() + " for ID="
+                            + data.getTaskID());
+        }
+
+        // get type...
+        String type = startProcessEntity.getItemValueString("txttype");
+        if (type.isEmpty()) {
+            type = DEFAULT_TYPE;
+        }
+        data.replaceItemValue("type", type);
+
+        if (loginController != null) {
+            String user = loginController.getUserPrincipal();
+            // set creator
+            data.replaceItemValue(WorkflowKernel.CREATOR, user);
+            // support deprecated field
+            data.replaceItemValue("namcreator", user);
+
+            // set default owner
+            data.replaceItemValue(OwnerPlugin.OWNER, user);
+            // support deprecated field
+            data.replaceItemValue("namowner", user);
+        }
+
+        // update $WriteAccess
+        data.replaceItemValue("$writeaccess", data.getItemValue(WorkflowKernel.CREATOR));
+
+        // assign WorkflowGroup and editor
+        data.replaceItemValue("$workflowgroup", startProcessEntity.getItemValueString("txtworkflowgroup"));
+        data.replaceItemValue("$workflowStatus", startProcessEntity.getItemValueString("txtname"));
+        data.replaceItemValue("txtWorkflowImageURL", startProcessEntity.getItemValueString("txtimageurl"));
+        data.replaceItemValue("txtWorkflowEditorid", startProcessEntity.getItemValueString("txteditorid"));
+
+        // deprecated field
+        data.replaceItemValue("txtworkflowgroup", startProcessEntity.getItemValueString("txtworkflowgroup"));
+        data.replaceItemValue("txtworkflowStatus", startProcessEntity.getItemValueString("txtname"));
 
-    // update $WriteAccess
-    data.replaceItemValue("$writeaccess", data.getItemValue(WorkflowKernel.CREATOR));
-
-    // assign WorkflowGroup and editor
-    data.replaceItemValue("$workflowgroup",
-        startProcessEntity.getItemValueString("txtworkflowgroup"));
-    data.replaceItemValue("$workflowStatus", startProcessEntity.getItemValueString("txtname"));
-    data.replaceItemValue("txtWorkflowImageURL",
-        startProcessEntity.getItemValueString("txtimageurl"));
-    data.replaceItemValue("txtWorkflowEditorid",
-        startProcessEntity.getItemValueString("txteditorid"));
-
-    // deprecated field
-    data.replaceItemValue("txtworkflowgroup",
-        startProcessEntity.getItemValueString("txtworkflowgroup"));
-    data.replaceItemValue("txtworkflowStatus", startProcessEntity.getItemValueString("txtname"));
-
-    startConversation();
-    // fire event
-    events.fire(new WorkflowEvent(getWorkitem(), WorkflowEvent.WORKITEM_CREATED));
-  }
-
-  /**
-   * This method creates a new empty workitem. An existing workitem and optional conversation
-   * context will be reset.
-   * 
-   * The method assigns the initial values '$ModelVersion', '$ProcessID' and '$UniqueIDRef' to the
-   * new workitem. The method creates the empty field '$workitemID' and the item '$owner' which is
-   * assigned to the current user. This data can be used in case that a workitem is not processed
-   * but saved (e.g. by the dmsController).
-   * 
-   * The method starts a new conversation context. Finally the method fires the WorkfowEvent
-   * WORKITEM_CREATED.
-   * 
-   * @param modelVersion - model version
-   * @param processID    - processID
-   * @param processRef   - uniqueid ref
-   */
-
-  public void create(String modelVersion, int taskID, String uniqueIdRef) throws ModelException {
-    // set model information..
-    data = new ItemCollection();
-    data.model(modelVersion).task(taskID);
-
-    // set optional uniqueidRef
-    if (uniqueIdRef != null && !uniqueIdRef.isEmpty()) {
-      data.replaceItemValue(WorkflowService.UNIQUEIDREF, uniqueIdRef);
+        startConversation();
+        // fire event
+        events.fire(new WorkflowEvent(getWorkitem(), WorkflowEvent.WORKITEM_CREATED));
     }
 
-    // set empty $workitemid
-    data.replaceItemValue("$workitemid", "");
-
-    this.create();
-  }
-
-  /**
-   * This method processes the current workItem and returns a new action result. The action result
-   * redirects the user to the default action result or to a new result provided by the workflow
-   * model. The 'action' property is typically evaluated from the ResultPlugin. Alternatively the
-   * property can be provided by an application. If no 'action' property is provided the method
-   * returns null.
-   * 

- * The method fires the WorkflowEvents WORKITEM_BEFORE_PROCESS and WORKITEM_AFTER_PROCESS. - *

- * The Method also catches PluginExceptions and adds the corresponding Faces Error Message into - * the FacesContext. In case of an exception the WorkflowEvent WORKITEM_AFTER_PROCESS will not be - * fired. - *

- * In case the processing was successful, the current conversation will be closed. In Case of an - * Exception (e.g PluginException) the conversation will not be closed, so that the current - * workitem data is still available. - * - * @return the action result provided in the 'action' property or evaluated from the default - * property 'txtworkflowResultmessage' from the ActivityEntity - * @throws PluginException - * @throws ModelException - */ - public String process() throws PluginException, ModelException { - String actionResult = null; - long lTotal = System.currentTimeMillis(); - - if (data == null) { - logger.warning("Unable to process workitem == null!"); - return actionResult; + /** + * This method creates a new empty workitem. An existing workitem and optional + * conversation context will be reset. + * + * The method assigns the initial values '$ModelVersion', '$ProcessID' and + * '$UniqueIDRef' to the new workitem. The method creates the empty field + * '$workitemID' and the item '$owner' which is assigned to the current user. + * This data can be used in case that a workitem is not processed but saved + * (e.g. by the dmsController). + * + * The method starts a new conversation context. Finally the method fires the + * WorkfowEvent WORKITEM_CREATED. + * + * @param modelVersion - model version + * @param processID - processID + * @param processRef - uniqueid ref + */ + + public void create(String modelVersion, int taskID, String uniqueIdRef) throws ModelException { + // set model information.. + data = new ItemCollection(); + data.model(modelVersion).task(taskID); + + // set optional uniqueidRef + if (uniqueIdRef != null && !uniqueIdRef.isEmpty()) { + data.replaceItemValue(WorkflowService.UNIQUEIDREF, uniqueIdRef); + } + + // set empty $workitemid + data.replaceItemValue("$workitemid", ""); + + this.create(); } - // clear last action - data.replaceItemValue("action", ""); - - try { - long l1 = System.currentTimeMillis(); - events.fire(new WorkflowEvent(getWorkitem(), WorkflowEvent.WORKITEM_BEFORE_PROCESS)); - logger.finest("......fire WORKITEM_BEFORE_PROCESS event: ' in " - + (System.currentTimeMillis() - l1) + "ms"); - - // process workItem now... - data = workflowService.processWorkItem(data); - - // test if the property 'action' is provided - actionResult = data.getItemValueString("action"); - - // If no action was defined computed it from the current viewID... - if (actionResult == null || actionResult.isEmpty()) { - FacesContext facesContext = FacesContext.getCurrentInstance(); - actionResult = facesContext.getViewRoot().getViewId(); - actionResult = actionResult + "?id=" + getWorkitem().getUniqueID() + "&faces-redirect=true"; - } - - // test if 'faces-redirect' is included in actionResult - if (!actionResult.startsWith("http") && actionResult.contains("/") - && !actionResult.contains("faces-redirect=")) { - // append faces-redirect=true - if (!actionResult.contains("?")) { - actionResult = actionResult + "?faces-redirect=true"; - } else { - actionResult = actionResult + "&faces-redirect=true"; + /** + * This method processes the current workItem and returns a new action result. + * The action result redirects the user to the default action result or to a new + * result provided by the workflow model. The 'action' property is typically + * evaluated from the ResultPlugin. Alternatively the property can be provided + * by an application. If no 'action' property is provided the method returns + * null. + *

+ * The method fires the WorkflowEvents WORKITEM_BEFORE_PROCESS and + * WORKITEM_AFTER_PROCESS. + *

+ * The Method also catches PluginExceptions and adds the corresponding Faces + * Error Message into the FacesContext. In case of an exception the + * WorkflowEvent WORKITEM_AFTER_PROCESS will not be fired. + *

+ * In case the processing was successful, the current conversation will be + * closed. In Case of an Exception (e.g PluginException) the conversation will + * not be closed, so that the current workitem data is still available. + * + * @return the action result provided in the 'action' property or evaluated from + * the default property 'txtworkflowResultmessage' from the + * ActivityEntity + * @throws PluginException + * @throws ModelException + */ + public String process() throws PluginException, ModelException { + String actionResult = null; + long lTotal = System.currentTimeMillis(); + + if (data == null) { + logger.warning("Unable to process workitem == null!"); + return actionResult; } - } - logger.fine("... new actionResult=" + actionResult); - - // fire event - long l2 = System.currentTimeMillis(); - events.fire(new WorkflowEvent(getWorkitem(), WorkflowEvent.WORKITEM_AFTER_PROCESS)); - logger.finest("......[process] fire WORKITEM_AFTER_PROCESS event: ' in " - + (System.currentTimeMillis() - l2) + "ms"); - - if (logger.isLoggable(Level.FINEST)) { - logger - .finest("......[process] '" + getWorkitem().getItemValueString(WorkflowKernel.UNIQUEID) - + "' completed in " + (System.currentTimeMillis() - lTotal) + "ms"); - } - // Finally we close the converstaion. In case of an exception, the conversation - // will stay open - close(); - - } catch (ObserverException oe) { - actionResult = null; - // test if we can handle the exception... - if (oe.getCause() instanceof PluginException) { - // add error message into current form - ErrorHandler.addErrorMessage((PluginException) oe.getCause()); - } else { - if (oe.getCause() instanceof ValidationException) { - // add error message into current form - ErrorHandler.addErrorMessage((ValidationException) oe.getCause()); - } else { - // throw unknown exception - throw oe; + + // clear last action + data.replaceItemValue("action", ""); + + try { + long l1 = System.currentTimeMillis(); + events.fire(new WorkflowEvent(getWorkitem(), WorkflowEvent.WORKITEM_BEFORE_PROCESS)); + logger.finest("......fire WORKITEM_BEFORE_PROCESS event: ' in " + (System.currentTimeMillis() - l1) + "ms"); + + // process workItem now... + data = workflowService.processWorkItem(data); + + // test if the property 'action' is provided + actionResult = data.getItemValueString("action"); + + // If no action was defined computed it from the current viewID... + if (actionResult == null || actionResult.isEmpty()) { + FacesContext facesContext = FacesContext.getCurrentInstance(); + actionResult = facesContext.getViewRoot().getViewId(); + actionResult = actionResult + "?id=" + getWorkitem().getUniqueID() + "&faces-redirect=true"; + } + + // test if 'faces-redirect' is included in actionResult + if (!actionResult.startsWith("http") && actionResult.contains("/") + && !actionResult.contains("faces-redirect=")) { + // append faces-redirect=true + if (!actionResult.contains("?")) { + actionResult = actionResult + "?faces-redirect=true"; + } else { + actionResult = actionResult + "&faces-redirect=true"; + } + } + logger.fine("... new actionResult=" + actionResult); + + // fire event + long l2 = System.currentTimeMillis(); + events.fire(new WorkflowEvent(getWorkitem(), WorkflowEvent.WORKITEM_AFTER_PROCESS)); + logger.finest("......[process] fire WORKITEM_AFTER_PROCESS event: ' in " + (System.currentTimeMillis() - l2) + + "ms"); + + if (logger.isLoggable(Level.FINEST)) { + logger.finest("......[process] '" + getWorkitem().getItemValueString(WorkflowKernel.UNIQUEID) + + "' completed in " + (System.currentTimeMillis() - lTotal) + "ms"); + } + // Finally we close the converstaion. In case of an exception, the conversation + // will stay open + close(); + + } catch (ObserverException oe) { + actionResult = null; + // test if we can handle the exception... + if (oe.getCause() instanceof PluginException) { + // add error message into current form + ErrorHandler.addErrorMessage((PluginException) oe.getCause()); + } else { + if (oe.getCause() instanceof ValidationException) { + // add error message into current form + ErrorHandler.addErrorMessage((ValidationException) oe.getCause()); + } else { + // throw unknown exception + throw oe; + } + } + } catch (PluginException pe) { + actionResult = null; + // add a new FacesMessage into the FacesContext + ErrorHandler.handlePluginException(pe); + } catch (ModelException me) { + actionResult = null; + // add a new FacesMessage into the FacesContext + ErrorHandler.handleModelException(me); } - } - } catch (PluginException pe) { - actionResult = null; - // add a new FacesMessage into the FacesContext - ErrorHandler.handlePluginException(pe); - } catch (ModelException me) { - actionResult = null; - // add a new FacesMessage into the FacesContext - ErrorHandler.handleModelException(me); - } - // test if the action result is an external URL. In this case initiate a - // redirect - if (actionResult != null && actionResult.startsWith("http")) { - // clear action result and start redirect - String externalURL = actionResult; - actionResult = ""; - try { - ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext(); - externalContext.redirect(externalURL); - } catch (IOException e) { - logger.warning( - "Failed to redirect action result: " + externalURL + " - Error: " + e.getMessage()); - e.printStackTrace(); - } - } + // test if the action result is an external URL. In this case initiate a + // redirect + if (actionResult != null && actionResult.startsWith("http")) { + // clear action result and start redirect + String externalURL = actionResult; + actionResult = ""; + try { + ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext(); + externalContext.redirect(externalURL); + } catch (IOException e) { + logger.warning("Failed to redirect action result: " + externalURL + " - Error: " + e.getMessage()); + e.printStackTrace(); + } + } - // return the action result (Post-Redirect-Get). - // can be null in case of an exception - return actionResult; - } - - /** - * This method processes the current workItem with the provided eventID. The method can be used as - * an action or actionListener. - * - * @param id - activityID to be processed - * @throws PluginException - * - * @see WorkflowController#process() - */ - public String process(int id) throws ModelException, PluginException { - // update the eventID - if (data == null) { - logger.finest("......process workitem is null"); - } else { - logger.finest("......process workitem id: " + data.getUniqueID()); - } - this.getWorkitem().setEventID(id); - return process(); - } - - /** - * This method returns a List of workflow events assigned to the corresponding '$taskid' and - * '$modelversion' of the current WorkItem. - * - * @return - */ - public List getEvents() { - List activityList = new ArrayList(); - - if (getWorkitem() == null || (getWorkitem().getModelVersion().isEmpty() - && getWorkitem().getItemValueString(WorkflowKernel.WORKFLOWGROUP).isEmpty())) { - return activityList; + // return the action result (Post-Redirect-Get). + // can be null in case of an exception + return actionResult; } - // get Events form workflowService - try { - activityList = workflowService.getEvents(getWorkitem()); - } catch (ModelException e) { - logger.warning("Unable to get workflow event list: " + e.getMessage()); + /** + * This method processes the current workItem with the provided eventID. The + * method can be used as an action or actionListener. + * + * @param id - activityID to be processed + * @throws PluginException + * + * @see WorkflowController#process() + */ + public String process(int id) throws ModelException, PluginException { + // update the eventID + if (data == null) { + logger.finest("......process workitem is null"); + } else { + logger.finest("......process workitem id: " + data.getUniqueID()); + } + this.getWorkitem().setEventID(id); + return process(); } - return activityList; - } - - /** - * Loads a workitem by a given $uniqueid and starts a new conversaton. The conversaion will be - * ended after the workitem was processed or after the MaxInactiveInterval from the session. - * - * @param uniqueid - */ - public void load(String uniqueid) { - super.load(uniqueid); - if (data != null) { - // fire event - events.fire(new WorkflowEvent(data, WorkflowEvent.WORKITEM_CHANGED)); + /** + * This method returns a List of workflow events assigned to the corresponding + * '$taskid' and '$modelversion' of the current WorkItem. + * + * @return + */ + public List getEvents() { + List activityList = new ArrayList(); + + if (getWorkitem() == null || (getWorkitem().getModelVersion().isEmpty() + && getWorkitem().getItemValueString(WorkflowKernel.WORKFLOWGROUP).isEmpty())) { + return activityList; + } + + // get Events form workflowService + try { + activityList = workflowService.getEvents(getWorkitem()); + } catch (ModelException e) { + logger.warning("Unable to get workflow event list: " + e.getMessage()); + } + + return activityList; } - } + /** + * Loads a workitem by a given $uniqueid and starts a new conversaton. The + * conversaion will be ended after the workitem was processed or after the + * MaxInactiveInterval from the session. + * + * @param uniqueid + */ + public void load(String uniqueid) { + super.load(uniqueid); + if (data != null) { + // fire event + events.fire(new WorkflowEvent(data, WorkflowEvent.WORKITEM_CHANGED)); + } + + } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/WorkflowEvent.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/WorkflowEvent.java index fb953ef79..17e78bb03 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/WorkflowEvent.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/data/WorkflowEvent.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *

- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,65 +22,71 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.data; import org.imixs.workflow.ItemCollection; /** - * The WorkflowEvent provides a CDI event fired by the DocumentController and WorkflowController. - * This event can be used in a observer pattern of a CDI bean to react on UI events in a jsf page. + * The WorkflowEvent provides a CDI event fired by the DocumentController and + * WorkflowController. This event can be used in a observer pattern of a CDI + * bean to react on UI events in a jsf page. *

- * The WorkflowEvent defines the following event types fired by the WorkflowController: + * The WorkflowEvent defines the following event types fired by the + * WorkflowController: *

    - *
  • WORKITEM_BEFORE_PROCESS - is send immediately before a workitem will be processed - *
  • WORKITEM_AFTER_PROCESS - is send immediately after a workitem was processed + *
  • WORKITEM_BEFORE_PROCESS - is send immediately before a workitem will be + * processed + *
  • WORKITEM_AFTER_PROCESS - is send immediately after a workitem was + * processed *
  • WORKITEM_CHANGED - is send immediately after a workitem was loaded *
*

* The following event types are fired by the DocumentController: *

    - *
  • DOCUMENT_BEFORE_SAVE - is send immediately before the document will be saved + *
  • DOCUMENT_BEFORE_SAVE - is send immediately before the document will be + * saved *
  • DOCUMENT_AFTER_SAVE - is send immediately after the document was saved *
  • DOCUMENT_CHANGED - is send immediately after the document was loaded - *
  • DOCUMENT_BEFORE_DELETE - is send immediately before the document will be deleted - *
  • DOCUMENT_AFTER_DELETE - is send immediately after the document was deleted + *
  • DOCUMENT_BEFORE_DELETE - is send immediately before the document will be + * deleted + *
  • DOCUMENT_AFTER_DELETE - is send immediately after the document was + * deleted *
* */ public class WorkflowEvent { - public static final int DOCUMENT_CREATED = 1; - public static final int DOCUMENT_INITIALIZED = 2; - public static final int DOCUMENT_CHANGED = 3; - public static final int DOCUMENT_BEFORE_SAVE = 4; - public static final int DOCUMENT_AFTER_SAVE = 5; - public static final int DOCUMENT_BEFORE_DELETE = 6; - public static final int DOCUMENT_AFTER_DELETE = 7; + public static final int DOCUMENT_CREATED = 1; + public static final int DOCUMENT_INITIALIZED = 2; + public static final int DOCUMENT_CHANGED = 3; + public static final int DOCUMENT_BEFORE_SAVE = 4; + public static final int DOCUMENT_AFTER_SAVE = 5; + public static final int DOCUMENT_BEFORE_DELETE = 6; + public static final int DOCUMENT_AFTER_DELETE = 7; - public static final int WORKITEM_CREATED = 20; - public static final int WORKITEM_CHANGED = 21; - public static final int WORKITEM_BEFORE_PROCESS = 22; - public static final int WORKITEM_AFTER_PROCESS = 23; + public static final int WORKITEM_CREATED = 20; + public static final int WORKITEM_CHANGED = 21; + public static final int WORKITEM_BEFORE_PROCESS = 22; + public static final int WORKITEM_AFTER_PROCESS = 23; - private int eventType; - private ItemCollection workitem; + private int eventType; + private ItemCollection workitem; - public WorkflowEvent(ItemCollection workitem, int eventType) { - this.eventType = eventType; - this.workitem = workitem; - } + public WorkflowEvent(ItemCollection workitem, int eventType) { + this.eventType = eventType; + this.workitem = workitem; + } - public int getEventType() { - return eventType; - } + public int getEventType() { + return eventType; + } - public ItemCollection getWorkitem() { - return workitem; - } + public ItemCollection getWorkitem() { + return workitem; + } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/fileupload/AjaxFileUploadServlet.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/fileupload/AjaxFileUploadServlet.java index 39b7942c8..f22d27039 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/fileupload/AjaxFileUploadServlet.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/fileupload/AjaxFileUploadServlet.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.fileupload; @@ -49,317 +48,320 @@ import org.imixs.workflow.FileData; /** - * The AjaxFileUploadServlet is a Multipart-Servlet 3.0. It is used by the imixsFileUplad widget. - * The widget is using a jQuery component to handle the upload of multiple files and supports drag & - * drop functionality. The servlet is configured with a max file size to 10MB, and a max request - * size of 50MB. + * The AjaxFileUploadServlet is a Multipart-Servlet 3.0. It is used by the + * imixsFileUplad widget. The widget is using a jQuery component to handle the + * upload of multiple files and supports drag & drop functionality. The servlet + * is configured with a max file size to 10MB, and a max request size of 50MB. * * @author rsoika * */ -@WebServlet(urlPatterns = {"/fileupload/*"}) -@MultipartConfig(fileSizeThreshold = 1024 * 1024, maxFileSize = 1024 * 1024 * 10, - maxRequestSize = 1024 * 1024 * 50) +@WebServlet(urlPatterns = { "/fileupload/*" }) +@MultipartConfig(fileSizeThreshold = 1024 * 1024, maxFileSize = 1024 * 1024 * 10, maxRequestSize = 1024 * 1024 * 50) public class AjaxFileUploadServlet extends HttpServlet { - private static final long serialVersionUID = 1L; - private static final String REQUEST_METHOD_POST = "POST"; - private static final String REQUEST_METHOD_GET = "GET"; - private static final String CONTENT_TYPE_MULTIPART = "multipart/"; - private static final String CONTENT_DISPOSITION = "content-disposition"; - private static final String CONTENT_DISPOSITION_FILENAME = "filename"; - public static final String IMIXS_FILEDATA_LIST = "IMIXS_FILEDATA_LIST"; - - private static Logger logger = Logger.getLogger(AjaxFileUploadServlet.class.getName()); - - @Inject - FileUploadController fileUploadController; - - /** - * Upload files to stored in the current user session - */ - @Override - protected void doPost(HttpServletRequest httpRequest, HttpServletResponse response) - throws ServletException, IOException { - if (isPostFileUploadRequest(httpRequest)) { - logger.finest("......add files..."); - List fileDataList = getFilesFromRequest(httpRequest); - // now update the workitem.... - if (fileUploadController != null) { - // check workitem... issue - if (fileUploadController.getWorkitem() != null) { - logger.finest("......add new fileData object..."); - for (FileData filedata : fileDataList) { - fileUploadController.addAttachedFile(filedata); - } + private static final long serialVersionUID = 1L; + private static final String REQUEST_METHOD_POST = "POST"; + private static final String REQUEST_METHOD_GET = "GET"; + private static final String CONTENT_TYPE_MULTIPART = "multipart/"; + private static final String CONTENT_DISPOSITION = "content-disposition"; + private static final String CONTENT_DISPOSITION_FILENAME = "filename"; + public static final String IMIXS_FILEDATA_LIST = "IMIXS_FILEDATA_LIST"; + + private static Logger logger = Logger.getLogger(AjaxFileUploadServlet.class.getName()); + + @Inject + FileUploadController fileUploadController; + + /** + * Upload files to stored in the current user session + */ + @Override + protected void doPost(HttpServletRequest httpRequest, HttpServletResponse response) + throws ServletException, IOException { + if (isPostFileUploadRequest(httpRequest)) { + logger.finest("......add files..."); + List fileDataList = getFilesFromRequest(httpRequest); + // now update the workitem.... + if (fileUploadController != null) { + // check workitem... issue + if (fileUploadController.getWorkitem() != null) { + logger.finest("......add new fileData object..."); + for (FileData filedata : fileDataList) { + fileUploadController.addAttachedFile(filedata); + } + } + } + writeJsonMetadata(response, httpRequest.getRequestURI()); } - } - writeJsonMetadata(response, httpRequest.getRequestURI()); } - } - - /** - * Delete a existing file form the fileData list stored in the current user session - */ - @Override - protected void doDelete(HttpServletRequest httpRequest, HttpServletResponse response) - throws ServletException, IOException { - - // List fileDataList = getFileList(httpRequest); - int iCancel = httpRequest.getRequestURI().indexOf("/fileupload/"); - String filename = httpRequest.getRequestURI().substring(iCancel + 12); - - // now update the fileUploadController and the list of uploaded files.... - if (fileUploadController != null) { - fileUploadController.removeAttachedFile(filename); + + /** + * Delete a existing file form the fileData list stored in the current user + * session + */ + @Override + protected void doDelete(HttpServletRequest httpRequest, HttpServletResponse response) + throws ServletException, IOException { + + // List fileDataList = getFileList(httpRequest); + int iCancel = httpRequest.getRequestURI().indexOf("/fileupload/"); + String filename = httpRequest.getRequestURI().substring(iCancel + 12); + + // now update the fileUploadController and the list of uploaded files.... + if (fileUploadController != null) { + fileUploadController.removeAttachedFile(filename); + } + + String contextURL = httpRequest.getRequestURI(); + // cut last /.... + contextURL = contextURL.substring(0, contextURL.lastIndexOf('/') + 1); + writeJsonMetadata(response, contextURL); } - String contextURL = httpRequest.getRequestURI(); - // cut last /.... - contextURL = contextURL.substring(0, contextURL.lastIndexOf('/') + 1); - writeJsonMetadata(response, contextURL); - } - - /** - * Getter method to return the file content from the fileData list stored in the current user - */ - @Override - protected void doGet(HttpServletRequest httpRequest, HttpServletResponse httpResponse) - throws ServletException, IOException { - - // check cancel upload... - if (isGetFileUploadRequest(httpRequest)) { - int iCancel = httpRequest.getRequestURI().indexOf("/fileupload/"); - String filename = httpRequest.getRequestURI().substring(iCancel + 12); - - // urldecoding... - filename = URLDecoder.decode(filename, "UTF-8"); - - if (fileUploadController != null) { - // check workitem... issue - if (fileUploadController.getWorkitem() != null) { - FileData fileData = fileUploadController.getWorkitem().getFileData(filename); - // write contenremoveFile(filename); - if (fileData != null) { - writeFileContent(httpResponse, fileData); - } else { - httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND); - } + /** + * Getter method to return the file content from the fileData list stored in the + * current user + */ + @Override + protected void doGet(HttpServletRequest httpRequest, HttpServletResponse httpResponse) + throws ServletException, IOException { + + // check cancel upload... + if (isGetFileUploadRequest(httpRequest)) { + int iCancel = httpRequest.getRequestURI().indexOf("/fileupload/"); + String filename = httpRequest.getRequestURI().substring(iCancel + 12); + + // urldecoding... + filename = URLDecoder.decode(filename, "UTF-8"); + + if (fileUploadController != null) { + // check workitem... issue + if (fileUploadController.getWorkitem() != null) { + FileData fileData = fileUploadController.getWorkitem().getFileData(filename); + // write contenremoveFile(filename); + if (fileData != null) { + writeFileContent(httpResponse, fileData); + } else { + httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND); + } + } + } + } - } + // request just the currently uploaded files in json format + if (isGetRefreshFileUploadRequest(httpRequest)) { + String contextURL = httpRequest.getRequestURI(); + writeJsonMetadata(httpResponse, contextURL); + } } - // request just the currently uploaded files in json format - if (isGetRefreshFileUploadRequest(httpRequest)) { - String contextURL = httpRequest.getRequestURI(); - writeJsonMetadata(httpResponse, contextURL); + /** + * checks if the httpRequest is a fileupload + * + * @param httpRequest + * @return + */ + private boolean isPostFileUploadRequest(HttpServletRequest httpRequest) { + String sContentType = httpRequest.getContentType(); + logger.finest("......contentType=" + sContentType); + + return (REQUEST_METHOD_POST.equalsIgnoreCase(httpRequest.getMethod()) && httpRequest.getContentType() != null + && sContentType.toLowerCase().startsWith(CONTENT_TYPE_MULTIPART)); } - } - - /** - * checks if the httpRequest is a fileupload - * - * @param httpRequest - * @return - */ - private boolean isPostFileUploadRequest(HttpServletRequest httpRequest) { - String sContentType = httpRequest.getContentType(); - logger.finest("......contentType=" + sContentType); - - return (REQUEST_METHOD_POST.equalsIgnoreCase(httpRequest.getMethod()) - && httpRequest.getContentType() != null - && sContentType.toLowerCase().startsWith(CONTENT_TYPE_MULTIPART)); - } - - /** - * checks if the httpRequest is a fileupload get request... - * - * @param httpRequest - * @return - */ - private boolean isGetFileUploadRequest(HttpServletRequest httpRequest) { - String uri = httpRequest.getRequestURI(); - - return (REQUEST_METHOD_GET.equalsIgnoreCase(httpRequest.getMethod()) - && !(uri.endsWith("/fileupload") || uri.endsWith("/fileupload/"))); - - } - - /** - * checks if the httpRequest is a fileupload get request... - * - * @param httpRequest - * @return - */ - private boolean isGetRefreshFileUploadRequest(HttpServletRequest httpRequest) { - - String uri = httpRequest.getRequestURI(); - return (REQUEST_METHOD_GET.equalsIgnoreCase(httpRequest.getMethod()) - && (uri.endsWith("/fileupload") || uri.endsWith("/fileupload/"))); - - } - - /** - * Returns a file attachment located in the property $file of the specified workitem - * - * The file name will be encoded. With a URLDecode the filename is decoded in different formats - * and searched in the file list. This is not a nice solution. - * - * @param uniqueid - * @return - * @throws IOException - */ - private void writeFileContent(ServletResponse response, FileData fileData) throws IOException { - logger.finest("......write file content..."); - ServletOutputStream output = response.getOutputStream(); - output.write(fileData.getContent()); - // now return json string of uploaded files.... - response.setContentType(fileData.getContentType()); - output.close(); - } - - /** - * test and extracts the filename of a http request part. The method returns null if the part dose - * not contain a file - * - * @param part - * @return - filename or null if not a file content - */ - private String getFilename(Part part) { - for (String cd : part.getHeader(CONTENT_DISPOSITION).split(";")) { - if (cd.trim().startsWith(CONTENT_DISPOSITION_FILENAME)) { - return cd.substring(cd.indexOf('=') + 1).trim().replace("\"", ""); - } + + /** + * checks if the httpRequest is a fileupload get request... + * + * @param httpRequest + * @return + */ + private boolean isGetFileUploadRequest(HttpServletRequest httpRequest) { + String uri = httpRequest.getRequestURI(); + + return (REQUEST_METHOD_GET.equalsIgnoreCase(httpRequest.getMethod()) + && !(uri.endsWith("/fileupload") || uri.endsWith("/fileupload/"))); + } - return null; - } - - /** - * This method converts mulitple files from the httpRequest into a list of FileData objects. - * - * @param httpRequest - * @return list of FileData objects - */ - private List getFilesFromRequest(HttpServletRequest httpRequest) { - logger.finest("......Looping parts"); - - List fileDataList = new ArrayList(); - try { - for (Part p : httpRequest.getParts()) { - byte[] b = new byte[(int) p.getSize()]; - p.getInputStream().read(b); - p.getInputStream().close(); - // params.put(p.getName(), new String[] { new String(b) }); - - // test if part contains a file - String fileName = getFilename(p); - if (fileName != null) { - - /* - * issue #106 - * - * https://developer.jboss.org/message/941661#941661 - * - * Here we test of the encoding and try to convert to utf-8. - */ - byte fileNameISOBytes[] = fileName.getBytes("iso-8859-1"); - String fileNameUTF8 = new String(fileNameISOBytes, "UTF-8"); - if (fileName.length() != fileNameUTF8.length()) { - // convert to utf-8 - logger.finest("......filename seems to be ISO-8859-1 encoded"); - fileName = new String(fileName.getBytes("iso-8859-1"), "utf-8"); - } - - // extract the file content... - FileData fileData = null; - logger.finest("......filename : " + fileName + ", contentType " + p.getContentType()); - fileData = new FileData(fileName, b, p.getContentType(), null); - fileDataList.add(fileData); - } - } + /** + * checks if the httpRequest is a fileupload get request... + * + * @param httpRequest + * @return + */ + private boolean isGetRefreshFileUploadRequest(HttpServletRequest httpRequest) { - } catch (IOException ex) { - logger.log(Level.SEVERE, null, ex); - } catch (ServletException ex) { - logger.log(Level.SEVERE, null, ex); + String uri = httpRequest.getRequestURI(); + return (REQUEST_METHOD_GET.equalsIgnoreCase(httpRequest.getMethod()) + && (uri.endsWith("/fileupload") || uri.endsWith("/fileupload/"))); + + } + + /** + * Returns a file attachment located in the property $file of the specified + * workitem + * + * The file name will be encoded. With a URLDecode the filename is decoded in + * different formats and searched in the file list. This is not a nice solution. + * + * @param uniqueid + * @return + * @throws IOException + */ + private void writeFileContent(ServletResponse response, FileData fileData) throws IOException { + logger.finest("......write file content..."); + ServletOutputStream output = response.getOutputStream(); + output.write(fileData.getContent()); + // now return json string of uploaded files.... + response.setContentType(fileData.getContentType()); + output.close(); + } + + /** + * test and extracts the filename of a http request part. The method returns + * null if the part dose not contain a file + * + * @param part + * @return - filename or null if not a file content + */ + private String getFilename(Part part) { + for (String cd : part.getHeader(CONTENT_DISPOSITION).split(";")) { + if (cd.trim().startsWith(CONTENT_DISPOSITION_FILENAME)) { + return cd.substring(cd.indexOf('=') + 1).trim().replace("\"", ""); + } + } + return null; } - return fileDataList; - } - - /** - * This method write a JSON meta data structure for uploaded files into the httpResponse. This - * structure is used by the ajax jquery file control. (see the imixs-faces.js file) - * - * - * - { - "files": [ - { - "url": "0:0:0:0:0:0:0:1", - "thumbnail_url": "", - "name": "start.gif", - "type": "image/gif", - "size": 128, - "delete_url": "", - "delete_type": "DELETE" - } - ] - } - * - * - * - * - * - * * @see https://github.com/blueimp/jQuery-File-Upload/wiki/JSON-Response - * - * @throws IOException - * - */ - private void writeJsonMetadata(ServletResponse response, String context_url) throws IOException { - - response.setContentType("application/json;charset=UTF-8"); - PrintWriter out = response.getWriter(); - - // look if we have a worktiem with filedata.... - if (fileUploadController != null) { - // check workitem... issue - if (fileUploadController.getWorkitem() != null) { - // List fileDataList = - // fileUploadController.getWorkitem().getFileData();// .removeFile(filename); - - List fileDataList = fileUploadController.getAttachedFiles(); - logger.finest("......write JSON meta data..."); - - String result = "{ \"files\":["; - for (int i = 0; i < fileDataList.size(); i++) { - - FileData fileData = fileDataList.get(i); - // we construct a temp file url with the current converstion id.... - result += "{ \"url\": \"" + context_url + fileData.getName() + "?cid=" - + fileUploadController.getCID() + "\","; - result += "\"thumbnail_url\": \"\","; - result += "\"name\": \"" + fileData.getName() + "\","; - result += "\"type\": \"" + fileData.getContentType() + "\","; - result += "\"size\": " + fileData.getContent().length + ","; - result += "\"delete_url\": \"\","; - result += "\"delete_type\": \"DELETE\""; - - // last element? - if (i < fileDataList.size() - 1) - result += "},"; - else - result += "}"; + /** + * This method converts mulitple files from the httpRequest into a list of + * FileData objects. + * + * @param httpRequest + * @return list of FileData objects + */ + private List getFilesFromRequest(HttpServletRequest httpRequest) { + logger.finest("......Looping parts"); + + List fileDataList = new ArrayList(); + try { + for (Part p : httpRequest.getParts()) { + byte[] b = new byte[(int) p.getSize()]; + p.getInputStream().read(b); + p.getInputStream().close(); + // params.put(p.getName(), new String[] { new String(b) }); + + // test if part contains a file + String fileName = getFilename(p); + if (fileName != null) { + + /* + * issue #106 + * + * https://developer.jboss.org/message/941661#941661 + * + * Here we test of the encoding and try to convert to utf-8. + */ + byte fileNameISOBytes[] = fileName.getBytes("iso-8859-1"); + String fileNameUTF8 = new String(fileNameISOBytes, "UTF-8"); + if (fileName.length() != fileNameUTF8.length()) { + // convert to utf-8 + logger.finest("......filename seems to be ISO-8859-1 encoded"); + fileName = new String(fileName.getBytes("iso-8859-1"), "utf-8"); + } + + // extract the file content... + FileData fileData = null; + logger.finest("......filename : " + fileName + ", contentType " + p.getContentType()); + fileData = new FileData(fileName, b, p.getContentType(), null); + fileDataList.add(fileData); + + } + } + + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } catch (ServletException ex) { + logger.log(Level.SEVERE, null, ex); } - result += "]}"; - out.write(result); - } + + return fileDataList; } - out.close(); + /** + * This method write a JSON meta data structure for uploaded files into the + * httpResponse. This structure is used by the ajax jquery file control. (see + * the imixs-faces.js file) + * + * + * + { + "files": [ + { + "url": "0:0:0:0:0:0:0:1", + "thumbnail_url": "", + "name": "start.gif", + "type": "image/gif", + "size": 128, + "delete_url": "", + "delete_type": "DELETE" + } + ] + } + * + * + * + * + * + * * @see https://github.com/blueimp/jQuery-File-Upload/wiki/JSON-Response + * + * @throws IOException + * + */ + private void writeJsonMetadata(ServletResponse response, String context_url) throws IOException { + + response.setContentType("application/json;charset=UTF-8"); + PrintWriter out = response.getWriter(); + + // look if we have a worktiem with filedata.... + if (fileUploadController != null) { + // check workitem... issue + if (fileUploadController.getWorkitem() != null) { + // List fileDataList = + // fileUploadController.getWorkitem().getFileData();// .removeFile(filename); + + List fileDataList = fileUploadController.getAttachedFiles(); + logger.finest("......write JSON meta data..."); + + String result = "{ \"files\":["; + for (int i = 0; i < fileDataList.size(); i++) { + + FileData fileData = fileDataList.get(i); + // we construct a temp file url with the current converstion id.... + result += "{ \"url\": \"" + context_url + fileData.getName() + "?cid=" + + fileUploadController.getCID() + "\","; + result += "\"thumbnail_url\": \"\","; + result += "\"name\": \"" + fileData.getName() + "\","; + result += "\"type\": \"" + fileData.getContentType() + "\","; + result += "\"size\": " + fileData.getContent().length + ","; + result += "\"delete_url\": \"\","; + result += "\"delete_type\": \"DELETE\""; + + // last element? + if (i < fileDataList.size() - 1) + result += "},"; + else + result += "}"; + } + result += "]}"; + out.write(result); + } + } - } + out.close(); + + } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/fileupload/FileUploadController.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/fileupload/FileUploadController.java index f28051c6d..5068e38d6 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/fileupload/FileUploadController.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/fileupload/FileUploadController.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.fileupload; @@ -48,9 +47,9 @@ import org.imixs.workflow.faces.data.WorkflowEvent; /** - * The FileUploadController is a conversation scoped bean and used to hold the upladed files and - * transfere the to the accoicated workitem. The AjaxFileUploadServlet injects this bean to provide - * new file data. + * The FileUploadController is a conversation scoped bean and used to hold the + * upladed files and transfere the to the accoicated workitem. The + * AjaxFileUploadServlet injects this bean to provide new file data. * * @see AjaxFileUploadServlet.doPost * @author rsoika @@ -60,214 +59,216 @@ @ConversationScoped public class FileUploadController implements Serializable { - private static final long serialVersionUID = 1L; - - private ItemCollection workitem = null; + private static final long serialVersionUID = 1L; - private List _tmpFiles = null; // temporarly file list. - private List _persistedFiles = null; // persisted file list. + private ItemCollection workitem = null; - private static Logger logger = Logger.getLogger(FileUploadController.class.getName()); + private List _tmpFiles = null; // temporarly file list. + private List _persistedFiles = null; // persisted file list. - @Inject - private Conversation conversation; + private static Logger logger = Logger.getLogger(FileUploadController.class.getName()); + @Inject + private Conversation conversation; - /** - * Setter method to get an instance of the current workitem the FileData should be stored. - * - * @return - */ - public ItemCollection getWorkitem() { - return workitem; - } + /** + * Setter method to get an instance of the current workitem the FileData should + * be stored. + * + * @return + */ + public ItemCollection getWorkitem() { + return workitem; + } - /** - * This method set the current workitem and starts a new conversation. With this mechanism the - * fileUploadController bean can be used in multiple browser tabs or browser sessions. - * - * @param workitem - */ - public void setWorkitem(ItemCollection workitem) { - this.workitem = workitem; + /** + * This method set the current workitem and starts a new conversation. With this + * mechanism the fileUploadController bean can be used in multiple browser tabs + * or browser sessions. + * + * @param workitem + */ + public void setWorkitem(ItemCollection workitem) { + this.workitem = workitem; - if (workitem != null) { - // start new conversation... - if (conversation.isTransient()) { - conversation.setTimeout(((HttpServletRequest) FacesContext.getCurrentInstance() - .getExternalContext().getRequest()).getSession().getMaxInactiveInterval() * 1000); - conversation.begin(); - logger.finest("......starting new conversation, id=" + conversation.getId()); - } - reset(); - for (FileData fileData : workitem.getFileData()) { - _persistedFiles.add(fileData); - } + if (workitem != null) { + // start new conversation... + if (conversation.isTransient()) { + conversation.setTimeout( + ((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()) + .getSession().getMaxInactiveInterval() * 1000); + conversation.begin(); + logger.finest("......starting new conversation, id=" + conversation.getId()); + } + reset(); + for (FileData fileData : workitem.getFileData()) { + _persistedFiles.add(fileData); + } + } } - } - /** - * Returns the current conversation id. This id is passed to the AjaxFileUploadServelt URIs so - * make sure that the correct FileUploadController is injected. - * - * @return - */ - public String getCID() { - if (conversation != null) { - return conversation.getId(); - } else { - // no conversation injected! - return ""; + /** + * Returns the current conversation id. This id is passed to the + * AjaxFileUploadServelt URIs so make sure that the correct FileUploadController + * is injected. + * + * @return + */ + public String getCID() { + if (conversation != null) { + return conversation.getId(); + } else { + // no conversation injected! + return ""; + } } - } - /** - * WorkflowEvent listener - *

- * If a new WorkItem was created the file upload will be reset. - * - * - * @param workflowEvent - */ - public void onWorkflowEvent(@Observes WorkflowEvent workflowEvent) { - if (workflowEvent == null) - return; + /** + * WorkflowEvent listener + *

+ * If a new WorkItem was created the file upload will be reset. + * + * + * @param workflowEvent + */ + public void onWorkflowEvent(@Observes WorkflowEvent workflowEvent) { + if (workflowEvent == null) + return; - if (WorkflowEvent.WORKITEM_CREATED == workflowEvent.getEventType()) { - // reset file data... - reset(); - } - - } + if (WorkflowEvent.WORKITEM_CREATED == workflowEvent.getEventType()) { + // reset file data... + reset(); + } - /** - * This method is called by the AjaxFileUpload Servlet. The method adds the file to the workitem - * but also updates the list of temporary files, which are not yet persisted. - * - * @param document - * @param aFilename - */ - public void addAttachedFile(FileData filedata) { - if (workitem != null) { - _tmpFiles.add(filedata); - workitem.addFileData(filedata); } - } - /** - * Removes a attached file object from the tmp list of uploaded files. - * - * @param sFilename - filename to be removed - * @return - null - */ - public void removeAttachedFile(String aFilename) { - if (workitem != null) { - workitem.removeFile(aFilename); - // remove from tmp list - for (Iterator iterator = _tmpFiles.iterator(); iterator.hasNext();) { - FileData tmp = iterator.next(); - if (tmp.getName().equals(aFilename)) { - iterator.remove(); + /** + * This method is called by the AjaxFileUpload Servlet. The method adds the file + * to the workitem but also updates the list of temporary files, which are not + * yet persisted. + * + * @param document + * @param aFilename + */ + public void addAttachedFile(FileData filedata) { + if (workitem != null) { + _tmpFiles.add(filedata); + workitem.addFileData(filedata); } - } } - } + /** + * Removes a attached file object from the tmp list of uploaded files. + * + * @param sFilename - filename to be removed + * @return - null + */ + public void removeAttachedFile(String aFilename) { + if (workitem != null) { + workitem.removeFile(aFilename); + // remove from tmp list + for (Iterator iterator = _tmpFiles.iterator(); iterator.hasNext();) { + FileData tmp = iterator.next(); + if (tmp.getName().equals(aFilename)) { + iterator.remove(); + } + } + } - /** - * Removes a file object from a given workitem. Here we operate on a given workitem as the - * imixsFileUpload.xhtml has no idea of he current conversation scoped controller. - * - * @param sFilename - filename to be removed - * @return - null - */ - public void removePersistedFile(String aFilename) { - if (workitem != null) { - workitem.removeFile(aFilename); - } - // remove from persisted list - for (Iterator iterator = _persistedFiles.iterator(); iterator.hasNext();) { - FileData tmp = iterator.next(); - if (tmp.getName().equals(aFilename)) { - iterator.remove(); - } } - } - - /** - * returns the list of currently new attached files. This list is not equal the $file item! - * - * @return - */ - public List getAttachedFiles() { - if (_tmpFiles == null) { - _tmpFiles = new ArrayList(); + /** + * Removes a file object from a given workitem. Here we operate on a given + * workitem as the imixsFileUpload.xhtml has no idea of he current conversation + * scoped controller. + * + * @param sFilename - filename to be removed + * @return - null + */ + public void removePersistedFile(String aFilename) { + if (workitem != null) { + workitem.removeFile(aFilename); + } + // remove from persisted list + for (Iterator iterator = _persistedFiles.iterator(); iterator.hasNext();) { + FileData tmp = iterator.next(); + if (tmp.getName().equals(aFilename)) { + iterator.remove(); + } + } } - return _tmpFiles; - } - - /** - * returns the list of already persisted files. This list is not equal the $file item! - * - * @return - */ - public List getPersistedFiles() { - if (_persistedFiles == null) { - _persistedFiles = new ArrayList(); + /** + * returns the list of currently new attached files. This list is not equal the + * $file item! + * + * @return + */ + public List getAttachedFiles() { + if (_tmpFiles == null) { + _tmpFiles = new ArrayList(); + } + return _tmpFiles; } - return _persistedFiles; - } - - /** - * reset the temp and persisted file variables. - */ - public void reset() { - _tmpFiles = new ArrayList(); - _persistedFiles = new ArrayList(); - } - + /** + * returns the list of already persisted files. This list is not equal the $file + * item! + * + * @return + */ + public List getPersistedFiles() { + if (_persistedFiles == null) { + _persistedFiles = new ArrayList(); + } + return _persistedFiles; + } - /** - * get the file size for a given filename in human readable format - * - * @param sFilename - filename to be removed - * @return - filsize in human readable string - */ - public String getFileSize(String aFilename) { - if (workitem != null) { - FileData fileData = workitem.getFileData(aFilename); - double bytes = fileData.getContent().length; - if (bytes >= 1000000000) { - bytes = (bytes / 1000000000); - return round(bytes) + " GB"; - } else if (bytes >= 1000000) { - bytes = (bytes / 1000000); - return round(bytes) + " MB"; - } else if (bytes >= 1000) { - bytes = (bytes / 1000); - return round(bytes) + " KB"; - } else { - return round(bytes) + " bytes"; - } + /** + * reset the temp and persisted file variables. + */ + public void reset() { + _tmpFiles = new ArrayList(); + _persistedFiles = new ArrayList(); } - return ""; - } + /** + * get the file size for a given filename in human readable format + * + * @param sFilename - filename to be removed + * @return - filsize in human readable string + */ + public String getFileSize(String aFilename) { + if (workitem != null) { + FileData fileData = workitem.getFileData(aFilename); + double bytes = fileData.getContent().length; + if (bytes >= 1000000000) { + bytes = (bytes / 1000000000); + return round(bytes) + " GB"; + } else if (bytes >= 1000000) { + bytes = (bytes / 1000000); + return round(bytes) + " MB"; + } else if (bytes >= 1000) { + bytes = (bytes / 1000); + return round(bytes) + " KB"; + } else { + return round(bytes) + " bytes"; + } + } + return ""; + } - /** - * helper method to round for 2 digits. - * - * @param value - * @param places - * @return - */ - public static double round(double value) { - BigDecimal bd = new BigDecimal(value); - bd = bd.setScale(2, RoundingMode.HALF_UP); - return bd.doubleValue(); - } + /** + * helper method to round for 2 digits. + * + * @param value + * @param places + * @return + */ + public static double round(double value) { + BigDecimal bd = new BigDecimal(value); + bd = bd.setScale(2, RoundingMode.HALF_UP); + return bd.doubleValue(); + } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ErrorHandler.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ErrorHandler.java index c9a76eb6b..6349e3e26 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ErrorHandler.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ErrorHandler.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *

- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.util; @@ -43,171 +42,172 @@ public class ErrorHandler { - private static Logger logger = Logger.getLogger(ErrorHandler.class.getName()); - - /** - * The Method expects a PluginException and adds the corresponding Faces Error Message into the - * FacesContext. - * - * If the PluginException was thrown from the RulePLugin then the method test this exception for - * ErrorParams and generate separate Faces Error Messages for each param. - */ - public static void handlePluginException(PluginException pe) { - // if the PluginException was throws from the RulePlugin then test - // for VALIDATION_ERROR and ErrorParams - if (RulePlugin.class.getName().equals(pe.getErrorContext()) - && (RulePlugin.VALIDATION_ERROR.equals(pe.getErrorCode())) - && pe.getErrorParameters() != null && pe.getErrorParameters().length > 0) { - - String errorCode = pe.getErrorCode(); - // try to find the message text in resource bundle... - try { - Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); - ResourceBundle rb = ResourceBundle.getBundle("bundle.app", browserLocale); - errorCode = rb.getString(pe.getErrorCode()); - } catch (MissingResourceException mre) { - logger.warning("ErrorHandler: " + mre.getMessage()); - } - // create a faces message for each parameter - Object[] messages = pe.getErrorParameters(); - for (Object aMessage : messages) { - - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, errorCode, aMessage.toString())); - } - } else { - // default behavior - addErrorMessage(pe); - } + private static Logger logger = Logger.getLogger(ErrorHandler.class.getName()); + + /** + * The Method expects a PluginException and adds the corresponding Faces Error + * Message into the FacesContext. + * + * If the PluginException was thrown from the RulePLugin then the method test + * this exception for ErrorParams and generate separate Faces Error Messages for + * each param. + */ + public static void handlePluginException(PluginException pe) { + // if the PluginException was throws from the RulePlugin then test + // for VALIDATION_ERROR and ErrorParams + if (RulePlugin.class.getName().equals(pe.getErrorContext()) + && (RulePlugin.VALIDATION_ERROR.equals(pe.getErrorCode())) && pe.getErrorParameters() != null + && pe.getErrorParameters().length > 0) { + + String errorCode = pe.getErrorCode(); + // try to find the message text in resource bundle... + try { + Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); + ResourceBundle rb = ResourceBundle.getBundle("bundle.app", browserLocale); + errorCode = rb.getString(pe.getErrorCode()); + } catch (MissingResourceException mre) { + logger.warning("ErrorHandler: " + mre.getMessage()); + } + // create a faces message for each parameter + Object[] messages = pe.getErrorParameters(); + for (Object aMessage : messages) { + + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, errorCode, aMessage.toString())); + } + } else { + // default behavior + addErrorMessage(pe); + } - logger.warning("ErrorHandler cauth PluginException - error code=" + pe.getErrorCode() + " - " - + pe.getMessage()); - if (logger.isLoggable(Level.FINE)) { + logger.warning( + "ErrorHandler cauth PluginException - error code=" + pe.getErrorCode() + " - " + pe.getMessage()); + if (logger.isLoggable(Level.FINE)) { - pe.printStackTrace(); // Or use a logger. - } - } - - /** - * The Method expects a ModelException and adds the corresponding Faces Error Message into the - * FacesContext. - * - * In case of a model exception, the exception message will become part of the error message. - * ErrorParams are not supported by a ModelException. - */ - public static void handleModelException(ModelException me) { - - // try to get the message code... - String message = me.getErrorCode(); - // try to find the message text in resource bundle... - try { - Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); - ResourceBundle rb = ResourceBundle.getBundle("bundle.app", browserLocale); - message = rb.getString(me.getErrorCode()); - } catch (MissingResourceException mre) { - logger.warning("ErrorHandler: " + mre.getMessage()); + pe.printStackTrace(); // Or use a logger. + } } - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, message, me.getMessage())); + /** + * The Method expects a ModelException and adds the corresponding Faces Error + * Message into the FacesContext. + * + * In case of a model exception, the exception message will become part of the + * error message. ErrorParams are not supported by a ModelException. + */ + public static void handleModelException(ModelException me) { + + // try to get the message code... + String message = me.getErrorCode(); + // try to find the message text in resource bundle... + try { + Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); + ResourceBundle rb = ResourceBundle.getBundle("bundle.app", browserLocale); + message = rb.getString(me.getErrorCode()); + } catch (MissingResourceException mre) { + logger.warning("ErrorHandler: " + mre.getMessage()); + } - logger.warning("ErrorHandler cauth ModelException - error code=" + me.getErrorCode() + " - " - + me.getMessage()); - if (logger.isLoggable(Level.FINE)) { - me.printStackTrace(); // Or use a logger. - } - } - - /** - * This helper method adds a error message to the faces context, based on the data in a - * WorkflowException. This kind of error message can be displayed in a page using: - * - * - * - * - * - * If a PluginException or ValidationException contains an optional object array the message is - * parsed for params to be replaced - * - * Example: - * - * - * ERROR_MESSAGE=Value should not be greater than {0} or lower as {1}. - * - * - * @param pe - */ - public static void addErrorMessage(WorkflowException pe) { - - String errorCode = pe.getErrorCode(); - String message = pe.getMessage(); - // try to find the message text in resource bundle... - try { - String messageFromBundle = getMessageFromBundle(pe.getErrorCode()); - if (messageFromBundle != null && !messageFromBundle.isEmpty()) { - message = messageFromBundle; - } - } catch (MissingResourceException mre) { - logger.warning("ErrorHandler: " + mre.getMessage()); - } + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, message, me.getMessage())); - // parse message for params - if (pe instanceof PluginException) { - PluginException p = (PluginException) pe; - if (p.getErrorParameters() != null && p.getErrorParameters().length > 0) { - for (int i = 0; i < p.getErrorParameters().length; i++) { - message = message.replace("{" + i + "}", p.getErrorParameters()[i].toString()); - } - } - } else { - if (pe instanceof ValidationException) { - ValidationException p = (ValidationException) pe; - if (p.getErrorParameters() != null && p.getErrorParameters().length > 0) { - for (int i = 0; i < p.getErrorParameters().length; i++) { - message = message.replace("{" + i + "}", p.getErrorParameters()[i].toString()); - } + logger.warning("ErrorHandler cauth ModelException - error code=" + me.getErrorCode() + " - " + me.getMessage()); + if (logger.isLoggable(Level.FINE)) { + me.printStackTrace(); // Or use a logger. } - } } - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, errorCode, message)); - - } - - /** - * Returns a message string from one of the following bundles: - * - * app custom - * - * @return - */ - private static String getMessageFromBundle(String messageFromBundle) { - String result = ""; - - if (messageFromBundle != null && !messageFromBundle.isEmpty()) { - Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); - try { - - ResourceBundle rb = ResourceBundle.getBundle("bundle.custom", browserLocale); - if (rb != null) { - result = rb.getString(messageFromBundle); + /** + * This helper method adds a error message to the faces context, based on the + * data in a WorkflowException. This kind of error message can be displayed in a + * page using: + * + * + * + * + * + * If a PluginException or ValidationException contains an optional object array + * the message is parsed for params to be replaced + * + * Example: + * + * + * ERROR_MESSAGE=Value should not be greater than {0} or lower as {1}. + * + * + * @param pe + */ + public static void addErrorMessage(WorkflowException pe) { + + String errorCode = pe.getErrorCode(); + String message = pe.getMessage(); + // try to find the message text in resource bundle... + try { + String messageFromBundle = getMessageFromBundle(pe.getErrorCode()); + if (messageFromBundle != null && !messageFromBundle.isEmpty()) { + message = messageFromBundle; + } + } catch (MissingResourceException mre) { + logger.warning("ErrorHandler: " + mre.getMessage()); } - if (result == null || result.isEmpty()) { - // try second bundle - rb = ResourceBundle.getBundle("bundle.app", browserLocale); - if (rb != null) { - result = rb.getString(messageFromBundle); - } + // parse message for params + if (pe instanceof PluginException) { + PluginException p = (PluginException) pe; + if (p.getErrorParameters() != null && p.getErrorParameters().length > 0) { + for (int i = 0; i < p.getErrorParameters().length; i++) { + message = message.replace("{" + i + "}", p.getErrorParameters()[i].toString()); + } + } + } else { + if (pe instanceof ValidationException) { + ValidationException p = (ValidationException) pe; + if (p.getErrorParameters() != null && p.getErrorParameters().length > 0) { + for (int i = 0; i < p.getErrorParameters().length; i++) { + message = message.replace("{" + i + "}", p.getErrorParameters()[i].toString()); + } + } + } } + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, errorCode, message)); - } catch (MissingResourceException mre) { - logger.warning("ErrorHandler: " + mre.getMessage()); - } } - return result; - } + /** + * Returns a message string from one of the following bundles: + * + * app custom + * + * @return + */ + private static String getMessageFromBundle(String messageFromBundle) { + String result = ""; + + if (messageFromBundle != null && !messageFromBundle.isEmpty()) { + Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); + + try { + + ResourceBundle rb = ResourceBundle.getBundle("bundle.custom", browserLocale); + if (rb != null) { + result = rb.getString(messageFromBundle); + } + + if (result == null || result.isEmpty()) { + // try second bundle + rb = ResourceBundle.getBundle("bundle.app", browserLocale); + if (rb != null) { + result = rb.getString(messageFromBundle); + } + } + + } catch (MissingResourceException mre) { + logger.warning("ErrorHandler: " + mre.getMessage()); + } + } + + return result; + } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/LoginController.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/LoginController.java index eb1070f2a..1b0c50f35 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/LoginController.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/LoginController.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.util; @@ -41,7 +40,8 @@ import org.imixs.workflow.engine.DocumentService; /** - * This Backing Bean acts as a Login Helper Class. Can be used to identify the login state + * This Backing Bean acts as a Login Helper Class. Can be used to identify the + * login state * * @author rsoika * @@ -50,110 +50,110 @@ @RequestScoped public class LoginController { - @Inject - private DocumentService documentService; - - /** - * returns true if user is authenticated and has at least on of the Imixs Access Roles - * - * @return - */ - public boolean isAuthenticated() { - if (getUserPrincipal() == null) - return false; - else { - ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext(); - // test if at least one of the Imixs Acces Roles are granted - if (ectx.isUserInRole("org.imixs.ACCESSLEVEL.AUTHORACCESS")) - return true; - if (ectx.isUserInRole("org.imixs.ACCESSLEVEL.EDITORACCESS")) - return true; - if (ectx.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS")) - return true; - if (ectx.isUserInRole("org.imixs.ACCESSLEVEL.READERACCESS")) - return true; + @Inject + private DocumentService documentService; + + /** + * returns true if user is authenticated and has at least on of the Imixs Access + * Roles + * + * @return + */ + public boolean isAuthenticated() { + if (getUserPrincipal() == null) + return false; + else { + ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext(); + // test if at least one of the Imixs Acces Roles are granted + if (ectx.isUserInRole("org.imixs.ACCESSLEVEL.AUTHORACCESS")) + return true; + if (ectx.isUserInRole("org.imixs.ACCESSLEVEL.EDITORACCESS")) + return true; + if (ectx.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS")) + return true; + if (ectx.isUserInRole("org.imixs.ACCESSLEVEL.READERACCESS")) + return true; + } + return false; + } + + /** + * Test security context isUserInRole + * + * @param aRoleName + * @return + */ + public boolean isUserInRole(String aRoleName) { + ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext(); + + if (aRoleName == null || aRoleName.isEmpty()) + return false; + + return ectx.isUserInRole(aRoleName); + } + + /** + * returns the userPrincipal Name + * + * @return + */ + public String getUserPrincipal() { + FacesContext context = FacesContext.getCurrentInstance(); + ExternalContext externalContext = context.getExternalContext(); + return externalContext.getUserPrincipal() != null ? externalContext.getUserPrincipal().toString() : null; + } + + /** + * returns the remote user Name + * + * @return + */ + public String getRemoteUser() { + FacesContext context = FacesContext.getCurrentInstance(); + ExternalContext externalContext = context.getExternalContext(); + String remoteUser = externalContext.getRemoteUser(); + return remoteUser; + } + + /** + * Returns the current user name list including userId, roles and context + * groups. + * + * @return + */ + public List getUserNameList() { + return documentService.getUserNameList(); + } + + /** + * returns the full qualified server URI from the current web context + * + * @return + */ + public String getServerURI() { + HttpServletRequest servletRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext() + .getRequest(); + + String port = "" + servletRequest.getLocalPort(); + + String server = servletRequest.getServerName(); + return "http://" + server + ":" + port + ""; + + } + + /** + * invalidates the current user session + * + * @param event + */ + public void doLogout(ActionEvent event) { + FacesContext context = FacesContext.getCurrentInstance(); + ExternalContext externalContext = context.getExternalContext(); + + HttpSession session = (HttpSession) externalContext.getSession(false); + + session.invalidate(); + } - return false; - } - - /** - * Test security context isUserInRole - * - * @param aRoleName - * @return - */ - public boolean isUserInRole(String aRoleName) { - ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext(); - - if (aRoleName == null || aRoleName.isEmpty()) - return false; - - return ectx.isUserInRole(aRoleName); - } - - /** - * returns the userPrincipal Name - * - * @return - */ - public String getUserPrincipal() { - FacesContext context = FacesContext.getCurrentInstance(); - ExternalContext externalContext = context.getExternalContext(); - return externalContext.getUserPrincipal() != null - ? externalContext.getUserPrincipal().toString() - : null; - } - - /** - * returns the remote user Name - * - * @return - */ - public String getRemoteUser() { - FacesContext context = FacesContext.getCurrentInstance(); - ExternalContext externalContext = context.getExternalContext(); - String remoteUser = externalContext.getRemoteUser(); - return remoteUser; - } - - /** - * Returns the current user name list including userId, roles and context groups. - * - * @return - */ - public List getUserNameList() { - return documentService.getUserNameList(); - } - - /** - * returns the full qualified server URI from the current web context - * - * @return - */ - public String getServerURI() { - HttpServletRequest servletRequest = - (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest(); - - String port = "" + servletRequest.getLocalPort(); - - String server = servletRequest.getServerName(); - return "http://" + server + ":" + port + ""; - - } - - /** - * invalidates the current user session - * - * @param event - */ - public void doLogout(ActionEvent event) { - FacesContext context = FacesContext.getCurrentInstance(); - ExternalContext externalContext = context.getExternalContext(); - - HttpSession session = (HttpSession) externalContext.getSession(false); - - session.invalidate(); - - } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/SelectItemComparator.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/SelectItemComparator.java index 8f075db7a..8a3d5633b 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/SelectItemComparator.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/SelectItemComparator.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.util; @@ -42,27 +41,27 @@ * */ public class SelectItemComparator implements Comparator { - private final Collator collator; + private final Collator collator; - private final boolean ascending; + private final boolean ascending; - public SelectItemComparator(boolean ascending) { - Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); - this.collator = Collator.getInstance(locale); - this.ascending = ascending; - } + public SelectItemComparator(boolean ascending) { + Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); + this.collator = Collator.getInstance(locale); + this.ascending = ascending; + } - public SelectItemComparator(Locale locale, boolean ascending) { - this.collator = Collator.getInstance(locale); - this.ascending = ascending; - } + public SelectItemComparator(Locale locale, boolean ascending) { + this.collator = Collator.getInstance(locale); + this.ascending = ascending; + } - public int compare(SelectItem a, SelectItem b) { - int result = this.collator.compare(a.getLabel(), b.getLabel()); - if (!this.ascending) { - result = -result; + public int compare(SelectItem a, SelectItem b) { + int result = this.collator.compare(a.getLabel(), b.getLabel()); + if (!this.ascending) { + result = -result; + } + return result; } - return result; - } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ValidationException.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ValidationException.java index a97961551..39b8fd0cf 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ValidationException.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ValidationException.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.util; @@ -40,29 +39,28 @@ */ public class ValidationException extends WorkflowException { - private static final long serialVersionUID = 1L; - private java.lang.Object[] params = null; + private static final long serialVersionUID = 1L; + private java.lang.Object[] params = null; - public ValidationException(String aErrorContext, String aErrorCode, String message) { - super(aErrorContext, aErrorCode, message); - } + public ValidationException(String aErrorContext, String aErrorCode, String message) { + super(aErrorContext, aErrorCode, message); + } - public ValidationException(String aErrorContext, String aErrorCode, String message, Exception e) { - super(aErrorContext, aErrorCode, message, e); - } + public ValidationException(String aErrorContext, String aErrorCode, String message, Exception e) { + super(aErrorContext, aErrorCode, message, e); + } - public ValidationException(String aErrorContext, String aErrorCode, String message, - Object[] params) { - super(aErrorContext, aErrorCode, message); - this.params = params; - } + public ValidationException(String aErrorContext, String aErrorCode, String message, Object[] params) { + super(aErrorContext, aErrorCode, message); + this.params = params; + } - public java.lang.Object[] getErrorParameters() { - return params; - } + public java.lang.Object[] getErrorParameters() { + return params; + } - protected void setErrorParameters(Object[] aparams) { - this.params = aparams; - } + protected void setErrorParameters(Object[] aparams) { + this.params = aparams; + } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/VectorConverter.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/VectorConverter.java index 2b79dfffc..1daada5b2 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/VectorConverter.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/VectorConverter.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.util; @@ -38,57 +37,57 @@ import javax.faces.convert.FacesConverter; /** - * für ConfigItem benutzter Converter, der einen Komma-separierten String in einen Vektor umwandelt - * und umgekehrt. + * für ConfigItem benutzter Converter, der einen Komma-separierten String in + * einen Vektor umwandelt und umgekehrt. * - * Noch dringend zu tun: - Dem Converter im Fehlerfall noch eine eigene Fehlermeldung mitgeben - - * müssen da nicht noch eine Menge try-catch blöcke und Typ-Prüfungen rein? Derzeit geht das alles - * sehr optimistisch davon aus, dass in dem Vektor wirklich auch Strings drin sind; was eigentlich - * auch der Fall ist. Interessant wird es, wenn man bestehende Felder umbiegt. + * Noch dringend zu tun: - Dem Converter im Fehlerfall noch eine eigene + * Fehlermeldung mitgeben - müssen da nicht noch eine Menge try-catch blöcke und + * Typ-Prüfungen rein? Derzeit geht das alles sehr optimistisch davon aus, dass + * in dem Vektor wirklich auch Strings drin sind; was eigentlich auch der Fall + * ist. Interessant wird es, wenn man bestehende Felder umbiegt. * - * Schön wäre noch folgendes: - Den Separator im converter-tag der JSP Seite definieren. Das wird - * allerdings ein Act (Vorgehen beschrieben in Kap. 20.4 in "Kito Mann - JSF in Action") + * Schön wäre noch folgendes: - Den Separator im converter-tag der JSP Seite + * definieren. Das wird allerdings ein Act (Vorgehen beschrieben in Kap. 20.4 in + * "Kito Mann - JSF in Action") */ @SuppressWarnings("rawtypes") @FacesConverter(value = "org.imixs.VectorConverter") public class VectorConverter implements Converter { - private String separator = "\n"; + private String separator = "\n"; - @SuppressWarnings({"unchecked"}) - public Object getAsObject(FacesContext context, UIComponent component, String value) - throws ConverterException { + @SuppressWarnings({ "unchecked" }) + public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException { - Vector v = new Vector(); - String[] tokens = value.split(separator); - for (int i = 0; i < tokens.length; i++) { - v.addElement(tokens[i].trim()); - } + Vector v = new Vector(); + String[] tokens = value.split(separator); + for (int i = 0; i < tokens.length; i++) { + v.addElement(tokens[i].trim()); + } - return v; + return v; - } + } - public String getAsString(FacesContext context, UIComponent component, Object value) - throws ConverterException { + public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException { - String s = ""; - Vector vValues = null; + String s = ""; + Vector vValues = null; - if (value instanceof Vector) - vValues = (Vector) value; - else - vValues = new Vector(); - ListIterator li = vValues.listIterator(); - while (li.hasNext()) { - if (li.hasPrevious()) { - s += separator; - } - s += li.next(); - } + if (value instanceof Vector) + vValues = (Vector) value; + else + vValues = new Vector(); + ListIterator li = vValues.listIterator(); + while (li.hasNext()) { + if (li.hasPrevious()) { + s += separator; + } + s += li.next(); + } - return s; + return s; - } + } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/VectorIntegerConverter.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/VectorIntegerConverter.java index e8f688c90..611c062de 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/VectorIntegerConverter.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/VectorIntegerConverter.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
- *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + * Imixs Software Solutions GmbH - Project Management + * Volker Probst, Ralph Soika - Software Developer + */ package org.imixs.workflow.faces.util; @@ -36,57 +35,44 @@ import javax.faces.convert.Converter; import javax.faces.convert.ConverterException; -/* - * für ConfigItem benutzter Converter, der einen Komma-separierten String in einen Vektor umwandelt - * und umgekehrt. Das ist alles noch sehr basic und ich fürchte auch nicht sehr defensiv - * programmiert. - * - * Noch dringend zu tun: - Dem Converter im Fehlerfall noch eine eigene Fehlermeldung mitgeben - - * müssen da nicht noch eine Menge try-catch blöcke und Typ-Prüfungen rein? Derzeit geht das alles - * sehr optimistisch davon aus, dass in dem Vektor wirklich auch Strings drin sind; was eigentlich - * auch der Fall ist. Interessant wird es, wenn man bestehende Felder umbiegt. - * - * Schön wäre noch folgendes: - Den Separator im converter-tag der JSP Seite definieren. Das wird - * allerdings ein Act (Vorgehen beschrieben in Kap. 20.4 in "Kito Mann - JSF in Action") +/** + * Converts a vector of integer values into a string an vice versa. */ @SuppressWarnings("rawtypes") public class VectorIntegerConverter implements Converter { - String separator = "\n"; + String separator = "\n"; + + @SuppressWarnings({ "unchecked" }) + public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException { - @SuppressWarnings({"unchecked"}) - public Object getAsObject(FacesContext context, UIComponent component, String value) - throws ConverterException { + Vector v = new Vector(); + String[] tokens = value.split(separator); + for (int i = 0; i < tokens.length; i++) { + String sValue = tokens[i].trim(); + Integer intValue = new Integer(sValue); + v.addElement(intValue); + } + return v; - Vector v = new Vector(); - String[] tokens = value.split(separator); - for (int i = 0; i < tokens.length; i++) { - String sValue = tokens[i].trim(); - Integer intValue = new Integer(sValue); - v.addElement(intValue); } - return v; + public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException { - } + String s = ""; + Vector vValues = (Vector) value; + ListIterator li = vValues.listIterator(); + while (li.hasNext()) { + if (li.hasPrevious()) { + s += "" + separator; + } + s += li.next(); + } - public String getAsString(FacesContext context, UIComponent component, Object value) - throws ConverterException { + return s; - String s = ""; - Vector vValues = (Vector) value; - ListIterator li = vValues.listIterator(); - while (li.hasNext()) { - if (li.hasPrevious()) { - s += "" + separator; - } - s += li.next(); } - return s; - - } - } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ViewExpiredExceptionHandler.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ViewExpiredExceptionHandler.java index e81ece0a0..aaa708a23 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ViewExpiredExceptionHandler.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ViewExpiredExceptionHandler.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.util; @@ -41,10 +40,11 @@ import javax.faces.event.ExceptionQueuedEventContext; /** - * This class is used to handle expired sessions. In case a session was expired the handler caught - * the ViewExpiredException and redirects into a new page. + * This class is used to handle expired sessions. In case a session was expired + * the handler caught the ViewExpiredException and redirects into a new page. * - * This class expects a jsf page called 'sessionexpired.xhtml' in the web root context! + * This class expects a jsf page called 'sessionexpired.xhtml' in the web root + * context! * * * @see ed burns ' dealing_gracefully_with_viewexpiredexception' @@ -57,46 +57,45 @@ */ public class ViewExpiredExceptionHandler extends ExceptionHandlerWrapper { - private ExceptionHandler wrapped; + private ExceptionHandler wrapped; - @SuppressWarnings("deprecation") - public ViewExpiredExceptionHandler(ExceptionHandler wrapped) { - this.wrapped = wrapped; - } + @SuppressWarnings("deprecation") + public ViewExpiredExceptionHandler(ExceptionHandler wrapped) { + this.wrapped = wrapped; + } - @Override - public ExceptionHandler getWrapped() { - return this.wrapped; - } + @Override + public ExceptionHandler getWrapped() { + return this.wrapped; + } - @Override - public void handle() throws FacesException { - for (Iterator i = getUnhandledExceptionQueuedEvents().iterator(); i - .hasNext();) { - ExceptionQueuedEvent event = i.next(); - ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource(); - Throwable t = context.getException(); - if (t instanceof ViewExpiredException) { - ViewExpiredException vee = (ViewExpiredException) t; - FacesContext fc = FacesContext.getCurrentInstance(); - Map requestMap = fc.getExternalContext().getRequestMap(); - NavigationHandler nav = fc.getApplication().getNavigationHandler(); - try { - // Push some useful stuff to the request scope for - // use in the page - requestMap.put("currentViewId", vee.getViewId()); + @Override + public void handle() throws FacesException { + for (Iterator i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) { + ExceptionQueuedEvent event = i.next(); + ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource(); + Throwable t = context.getException(); + if (t instanceof ViewExpiredException) { + ViewExpiredException vee = (ViewExpiredException) t; + FacesContext fc = FacesContext.getCurrentInstance(); + Map requestMap = fc.getExternalContext().getRequestMap(); + NavigationHandler nav = fc.getApplication().getNavigationHandler(); + try { + // Push some useful stuff to the request scope for + // use in the page + requestMap.put("currentViewId", vee.getViewId()); - nav.handleNavigation(fc, null, "sessionexpired"); - fc.renderResponse(); + nav.handleNavigation(fc, null, "sessionexpired"); + fc.renderResponse(); - } finally { - i.remove(); + } finally { + i.remove(); + } + } } - } - } - // At this point, the queue will not contain any ViewExpiredEvents. - // Therefore, let the parent handle them. - getWrapped().handle(); + // At this point, the queue will not contain any ViewExpiredEvents. + // Therefore, let the parent handle them. + getWrapped().handle(); - } + } } diff --git a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ViewExpiredExceptionHandlerFactory.java b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ViewExpiredExceptionHandlerFactory.java index 605124cad..993ed3999 100644 --- a/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ViewExpiredExceptionHandlerFactory.java +++ b/imixs-workflow-faces/src/main/java/org/imixs/workflow/faces/util/ViewExpiredExceptionHandlerFactory.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.faces.util; @@ -33,10 +32,11 @@ import javax.faces.context.ExceptionHandlerFactory; /** - * This class is used to handle expired sessions. In case a session was expired the handler caught - * the ViewExpiredException and redirects into a new page. + * This class is used to handle expired sessions. In case a session was expired + * the handler caught the ViewExpiredException and redirects into a new page. * - * This class expects a jsf page called 'sessionexpired.xhtml' in the web root context! + * This class expects a jsf page called 'sessionexpired.xhtml' in the web root + * context! * * * @see ed burns ' dealing_gracefully_with_viewexpiredexception' @@ -48,17 +48,17 @@ * */ public class ViewExpiredExceptionHandlerFactory extends ExceptionHandlerFactory { - private ExceptionHandlerFactory parent; + private ExceptionHandlerFactory parent; - public ViewExpiredExceptionHandlerFactory(ExceptionHandlerFactory parent) { - this.parent = parent; - } + public ViewExpiredExceptionHandlerFactory(ExceptionHandlerFactory parent) { + this.parent = parent; + } - @Override - public ExceptionHandler getExceptionHandler() { - ExceptionHandler result = parent.getExceptionHandler(); - result = new ViewExpiredExceptionHandler(result); + @Override + public ExceptionHandler getExceptionHandler() { + ExceptionHandler result = parent.getExceptionHandler(); + result = new ViewExpiredExceptionHandler(result); - return result; - } + return result; + } } diff --git a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/AdminPRestService.java b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/AdminPRestService.java index c03bfd618..d8cc57abd 100644 --- a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/AdminPRestService.java +++ b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/AdminPRestService.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.jaxrs; @@ -64,151 +63,146 @@ * */ @Path("/adminp") -@Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, - MediaType.TEXT_XML}) +@Produces({ MediaType.TEXT_HTML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) @Stateless public class AdminPRestService { - @Inject - private DocumentService documentService; - - @Inject - private AdminPService adminPService; - - @javax.ws.rs.core.Context - private HttpServletRequest servletRequest; - - private static Logger logger = Logger.getLogger(AdminPRestService.class.getName()); - - @GET - @Produces("text/html") - @Path("/help") - public StreamingOutput getHelpHTML() { - - return new StreamingOutput() { - public void write(OutputStream out) throws IOException, WebApplicationException { - - out.write("".getBytes()); - out.write("".getBytes()); - out.write("".getBytes()); - - // body - out.write("

Imixs-AdminP REST Service

".getBytes()); - out.write( - "

See the Imixs REST Service API for more information about this Service.

" - .getBytes()); - - // end - out.write("".getBytes()); - } - }; - - } - - /** - * Returns all existing jobs - * - * @param query - * @param pageSize - * @param pageIndex - * @param items - * @return - */ - @GET - @Path("/jobs") - public XMLDataCollection getAllJobs() { - Collection col = null; - try { - col = documentService.getDocumentsByType("adminp"); - return XMLDataCollectionAdapter.getDataCollection(col); - } catch (Exception e) { - e.printStackTrace(); - } - return new XMLDataCollection(); - } - - /** - * This method saves a entity provided in xml format - * - * Note: the method merges the content of the given entity into an existing one because the - * EntityService method save() did not merge an entity. But the rest service typically consumes - * only a subset of attributes. So this is the reason why we merge the entity here. In different - * to the behavior of the EntityService the WorkflowService method process() did this merge - * automatically. - * - * @param xmlworkitem - entity to be saved - * @return - */ - @POST - @Path("/jobs/") - @Produces(MediaType.APPLICATION_XML) - @Consumes({MediaType.APPLICATION_XML, "text/xml"}) - public Response putJob(XMLDocument xmlworkitem) { - if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { - return Response.status(Response.Status.UNAUTHORIZED).build(); - } - ItemCollection workitem; - workitem = XMLDocumentAdapter.putDocument(xmlworkitem); + @Inject + private DocumentService documentService; - if (workitem == null) { - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); - } + @Inject + private AdminPService adminPService; + + @javax.ws.rs.core.Context + private HttpServletRequest servletRequest; + + private static Logger logger = Logger.getLogger(AdminPRestService.class.getName()); + + @GET + @Produces("text/html") + @Path("/help") + public StreamingOutput getHelpHTML() { + + return new StreamingOutput() { + public void write(OutputStream out) throws IOException, WebApplicationException { + + out.write("".getBytes()); + out.write("".getBytes()); + out.write("".getBytes()); + + // body + out.write("

Imixs-AdminP REST Service

".getBytes()); + out.write( + "

See the Imixs REST Service API for more information about this Service.

" + .getBytes()); + + // end + out.write("".getBytes()); + } + }; - try { - adminPService.createJob(workitem); - } catch (AccessDeniedException e) { - logger.severe(e.getMessage()); - workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); - } catch (RuntimeException e) { - logger.severe(e.getMessage()); - workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); } - // return workitem - try { - if (workitem.hasItem("$error_code")) - return Response - .ok(XMLDataCollectionAdapter.getDataCollection(workitem), MediaType.APPLICATION_XML) - .status(Response.Status.NOT_ACCEPTABLE).build(); - else - return Response - .ok(XMLDataCollectionAdapter.getDataCollection(workitem), MediaType.APPLICATION_XML) - .build(); - } catch (Exception e) { - e.printStackTrace(); - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + /** + * Returns all existing jobs + * + * @param query + * @param pageSize + * @param pageIndex + * @param items + * @return + */ + @GET + @Path("/jobs") + public XMLDataCollection getAllJobs() { + Collection col = null; + try { + col = documentService.getDocumentsByType("adminp"); + return XMLDataCollectionAdapter.getDataCollection(col); + } catch (Exception e) { + e.printStackTrace(); + } + return new XMLDataCollection(); } - } - - /** - * This method deletes an entity - * - */ - @DELETE - @Path("/jobs/{uniqueid}") - public Response deleteJob(@PathParam("uniqueid") String uniqueid) { - if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { - return Response.status(Response.Status.UNAUTHORIZED).build(); + + /** + * This method saves a entity provided in xml format + * + * Note: the method merges the content of the given entity into an existing one + * because the EntityService method save() did not merge an entity. But the rest + * service typically consumes only a subset of attributes. So this is the reason + * why we merge the entity here. In different to the behavior of the + * EntityService the WorkflowService method process() did this merge + * automatically. + * + * @param xmlworkitem - entity to be saved + * @return + */ + @POST + @Path("/jobs/") + @Produces(MediaType.APPLICATION_XML) + @Consumes({ MediaType.APPLICATION_XML, "text/xml" }) + public Response putJob(XMLDocument xmlworkitem) { + if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { + return Response.status(Response.Status.UNAUTHORIZED).build(); + } + ItemCollection workitem; + workitem = XMLDocumentAdapter.putDocument(xmlworkitem); + + if (workitem == null) { + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } + + try { + adminPService.createJob(workitem); + } catch (AccessDeniedException e) { + logger.severe(e.getMessage()); + workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); + } catch (RuntimeException e) { + logger.severe(e.getMessage()); + workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); + } + + // return workitem + try { + if (workitem.hasItem("$error_code")) + return Response.ok(XMLDataCollectionAdapter.getDataCollection(workitem), MediaType.APPLICATION_XML) + .status(Response.Status.NOT_ACCEPTABLE).build(); + else + return Response.ok(XMLDataCollectionAdapter.getDataCollection(workitem), MediaType.APPLICATION_XML) + .build(); + } catch (Exception e) { + e.printStackTrace(); + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } } - adminPService.deleteJob(uniqueid); - return Response.status(Response.Status.OK).build(); - } + /** + * This method deletes an entity + * + */ + @DELETE + @Path("/jobs/{uniqueid}") + public Response deleteJob(@PathParam("uniqueid") String uniqueid) { + if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { + return Response.status(Response.Status.UNAUTHORIZED).build(); + } + adminPService.deleteJob(uniqueid); + return Response.status(Response.Status.OK).build(); + } } diff --git a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/BPMNUnmarshaller.java b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/BPMNUnmarshaller.java index 3f30c8ea6..1dea23a69 100644 --- a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/BPMNUnmarshaller.java +++ b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/BPMNUnmarshaller.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.jaxrs; @@ -54,44 +53,42 @@ * @author rsoika */ @Provider -@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN}) +@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN }) public class BPMNUnmarshaller implements MessageBodyReader { - private static Logger logger = Logger.getLogger(BPMNUnmarshaller.class.getName()); + private static Logger logger = Logger.getLogger(BPMNUnmarshaller.class.getName()); - @SuppressWarnings("rawtypes") - @Override - public boolean isReadable(Class aClass, Type type, Annotation[] annotations, - MediaType mediaType) { - if (aClass == BPMNModel.class) - return true; + @SuppressWarnings("rawtypes") + @Override + public boolean isReadable(Class aClass, Type type, Annotation[] annotations, MediaType mediaType) { + if (aClass == BPMNModel.class) + return true; - return false; - } + return false; + } - @SuppressWarnings("rawtypes") - @Override - public BPMNModel readFrom(Class aClass, Type type, Annotation[] annotations, MediaType mediaType, - MultivaluedMap multivaluedMap, InputStream bpmnInputStream) - throws IOException, WebApplicationException { + @SuppressWarnings("rawtypes") + @Override + public BPMNModel readFrom(Class aClass, Type type, Annotation[] annotations, MediaType mediaType, + MultivaluedMap multivaluedMap, InputStream bpmnInputStream) throws IOException, WebApplicationException { - try { - return BPMNParser.parseModel(bpmnInputStream, "UTF-8"); - } catch (ModelException e) { - logger.warning("Invalid Model: " + e.getMessage()); - e.printStackTrace(); - } catch (ParseException e) { - logger.warning("Invalid Model: " + e.getMessage()); - e.printStackTrace(); - } catch (ParserConfigurationException e) { - logger.warning("Invalid Model: " + e.getMessage()); - e.printStackTrace(); - } catch (SAXException e) { - logger.warning("Invalid Model: " + e.getMessage()); - e.printStackTrace(); - } + try { + return BPMNParser.parseModel(bpmnInputStream, "UTF-8"); + } catch (ModelException e) { + logger.warning("Invalid Model: " + e.getMessage()); + e.printStackTrace(); + } catch (ParseException e) { + logger.warning("Invalid Model: " + e.getMessage()); + e.printStackTrace(); + } catch (ParserConfigurationException e) { + logger.warning("Invalid Model: " + e.getMessage()); + e.printStackTrace(); + } catch (SAXException e) { + logger.warning("Invalid Model: " + e.getMessage()); + e.printStackTrace(); + } - return null; + return null; - } + } } diff --git a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/DocumentCollectionWriter.java b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/DocumentCollectionWriter.java index d58f58e9c..95b10c992 100644 --- a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/DocumentCollectionWriter.java +++ b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/DocumentCollectionWriter.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.jaxrs; @@ -45,7 +44,8 @@ import org.imixs.workflow.xml.XMLDocument; /** - * This MessageBodyWriter generates an HTML representation from a DocumetCollection + * This MessageBodyWriter generates an HTML representation from a + * DocumetCollection * * @author rsoika * @@ -54,46 +54,39 @@ @Produces(MediaType.TEXT_HTML) public class DocumentCollectionWriter implements MessageBodyWriter { - public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, - MediaType mediaType) { - return XMLDataCollection.class.isAssignableFrom(type); - } + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return XMLDataCollection.class.isAssignableFrom(type); + } - public void writeTo(XMLDataCollection entityCollection, Class type, Type genericType, - Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, - OutputStream entityStream) throws IOException, WebApplicationException { - BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(entityStream)); + public void writeTo(XMLDataCollection entityCollection, Class type, Type genericType, Annotation[] annotations, + MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) + throws IOException, WebApplicationException { + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(entityStream)); + bw.write(""); + XMLItemCollectionWriter.printHead(bw, mediaType.toString(), null); + bw.write(""); + try { + bw.write("

EntityCollection

"); + bw.write("

" + entityCollection.getDocument().length + " Entries

"); + for (XMLDocument xmlworkItem : entityCollection.getDocument()) { + XMLItemCollectionWriter.printXMLItemCollectionHTML(bw, xmlworkItem); - bw.write(""); - XMLItemCollectionWriter.printHead(bw, mediaType.toString(), null); - bw.write(""); - try { - bw.write("

EntityCollection

"); - bw.write("

" + entityCollection.getDocument().length + " Entries

"); + } + } catch (Exception e) { + bw.write("ERROR
"); + // e.printStackTrace(bw.); + } - for (XMLDocument xmlworkItem : entityCollection.getDocument()) { - XMLItemCollectionWriter.printXMLItemCollectionHTML(bw, xmlworkItem); + bw.write(""); + bw.write(""); - } - } catch (Exception e) { - bw.write("ERROR
"); - // e.printStackTrace(bw.); + bw.flush(); } - - bw.write(""); - bw.write(""); - - bw.flush(); - } - - public long getSize(XMLDataCollection arg0, Class arg1, Type arg2, Annotation[] arg3, - MediaType arg4) { - return -1; - } - - + public long getSize(XMLDataCollection arg0, Class arg1, Type arg2, Annotation[] arg3, MediaType arg4) { + return -1; + } } diff --git a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/DocumentRestService.java b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/DocumentRestService.java index 34a5b4135..43c20c177 100644 --- a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/DocumentRestService.java +++ b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/DocumentRestService.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.jaxrs; @@ -76,554 +75,542 @@ * */ @Path("/documents") -@Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, - MediaType.TEXT_XML}) +@Produces({ MediaType.TEXT_HTML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) @Stateless public class DocumentRestService { - @Inject - private DocumentService documentService; - - @Inject - private SchemaService schemaService; - - @javax.ws.rs.core.Context - private HttpServletRequest servletRequest; - - private static Logger logger = Logger.getLogger(DocumentRestService.class.getName()); - - @GET - @Produces(MediaType.APPLICATION_XHTML_XML) - // @Path("/") generates jersey warning - public StreamingOutput getRoot() { - - return new StreamingOutput() { - public void write(OutputStream out) throws IOException, WebApplicationException { - - out.write("
".getBytes()); - out.write( - "".getBytes()); - - out.write("
".getBytes()); - } - }; - - } - - @GET - @Produces("text/html") - @Path("/help") - public StreamingOutput getHelpHTML() { - - return new StreamingOutput() { - public void write(OutputStream out) throws IOException, WebApplicationException { - - out.write("".getBytes()); - out.write("".getBytes()); - out.write("".getBytes()); - - // body - out.write("

Imixs-Document REST Service

".getBytes()); - out.write( - "

See the Imixs REST Service API for more information about this Service.

" - .getBytes()); - - // end - out.write("".getBytes()); - } - }; - - } - - /** - * returns a single document defined by $uniqueid - * - * Regex for - * - * UID - e.g: bcc776f9-4e5a-4272-a613-9f5ebf35354d - * - * Snapshot: bcc776f9-4e5a-4272-a613-9f5ebf35354d-9b6655 - * - * deprecated format : 132d37bfd51-9a7868 - * - * @param uniqueid - * @return - */ - @GET - @Path("/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") - public Response getDocument(@PathParam("uniqueid") String uniqueid, - @QueryParam("items") String items, @QueryParam("format") String format) { - ItemCollection document = null; - try { - document = documentService.load(uniqueid); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - return convertResult(document, items, format); - } - - /** - * Returns a resultset for a lucene Search Query - * - * @param query - * @param pageSize - * @param pageIndex - * @param items - * @return - */ - @GET - @Path("/search/{query}") - public Response findDocumentsByQuery(@PathParam("query") String query, - @DefaultValue("-1") @QueryParam("pageSize") int pageSize, - @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @QueryParam("sortBy") String sortBy, @QueryParam("sortReverse") boolean sortReverse, - @QueryParam("items") String items, @QueryParam("format") String format) { - List result = null; - try { - // decode query... - String decodedQuery = URLDecoder.decode(query, "UTF-8"); - result = documentService.find(decodedQuery, pageSize, pageIndex, sortBy, sortReverse); - - } catch (Exception e) { - logger.warning("Invalid Search Query: " + e.getMessage()); - - ItemCollection error = new ItemCollection(); - error.setItemValue("$error_message", e.getMessage()); - error.setItemValue("$error_code", "" + Response.Status.NOT_ACCEPTABLE); - return Response.ok(XMLDataCollectionAdapter.getDataCollection(error)) - .status(Response.Status.NOT_ACCEPTABLE).build(); + @Inject + private DocumentService documentService; - } + @Inject + private SchemaService schemaService; - return convertResultList(result, items, format); - } - - /** - * Returns a resultset for a JPQL statement - * - * @param query - * @param pageSize - * @param pageIndex - * @param items - * @return - */ - @GET - @Path("/jpql/{query}") - public Response findDocumentsByJPQL(@PathParam("query") String query, - @DefaultValue("" + SearchService.DEFAULT_PAGE_SIZE) @QueryParam("pageSize") int pageSize, - @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, @QueryParam("items") String items, - @QueryParam("format") String format) { - List result = null; - try { - // decode query... - String decodedQuery = URLDecoder.decode(query, "UTF-8"); - // compute first result.... - int firstResult = pageIndex * pageSize; - result = documentService.getDocumentsByQuery(decodedQuery, firstResult, pageSize); - } catch (Exception e) { - e.printStackTrace(); - } - return convertResultList(result, items, format); - } - - /** - * Returns a total hits for a lucene Search Query - * - * @param query - * @param pageSize - * @param pageIndex - * @param items - * @return - */ - @GET - @Path("/count/{query}") - public Response countTotalHitsByQuery(@PathParam("query") String query, - @DefaultValue("-1") @QueryParam("maxResult") int maxResult, - @QueryParam("format") String format) { - XMLCount xmlcount = new XMLCount(); - String decodedQuery; - try { - decodedQuery = URLDecoder.decode(query, "UTF-8"); - xmlcount.count = (long) documentService.count(decodedQuery, maxResult); - } catch (UnsupportedEncodingException | QueryException e) { - xmlcount.count = 0l; - logger.severe(e.getMessage()); - } + @javax.ws.rs.core.Context + private HttpServletRequest servletRequest; - if ("json".equals(format)) { - return Response - // Set the status and Put your entity here. - .ok(xmlcount) - // Add the Content-Type header to tell Jersey which format it should marshall - // the entity into. - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON).build(); - } else if ("xml".equals(format)) { - return Response - // Set the status and Put your entity here. - .ok(xmlcount) - // Add the Content-Type header to tell Jersey which format it should marshall - // the entity into. - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML).build(); - } else { - // default header param - return Response - // Set the status and Put your entity here. - .ok(xmlcount).build(); - } - } - - /** - * Returns the total pages for a lucene Search Query and a given page size. - * - * @param query - * @param pageSize - * @param pageIndex - * @param items - * @return - */ - @GET - @Path("/countpages/{query}") - public Response countTotalPagesByQuery(@PathParam("query") String query, - @DefaultValue("-1") @QueryParam("pageSize") int pageSize, - @QueryParam("format") String format) { - XMLCount xmlcount = new XMLCount(); - String decodedQuery; - try { - decodedQuery = URLDecoder.decode(query, "UTF-8"); - xmlcount.count = (long) documentService.countPages(decodedQuery, pageSize); - } catch (UnsupportedEncodingException | QueryException e) { - xmlcount.count = 0l; - logger.severe(e.getMessage()); + private static Logger logger = Logger.getLogger(DocumentRestService.class.getName()); + + @GET + @Produces(MediaType.APPLICATION_XHTML_XML) + // @Path("/") generates jersey warning + public StreamingOutput getRoot() { + + return new StreamingOutput() { + public void write(OutputStream out) throws IOException, WebApplicationException { + + out.write("
".getBytes()); + out.write("".getBytes()); + + out.write("
".getBytes()); + } + }; } - if ("json".equals(format)) { - return Response - // Set the status and Put your entity here. - .ok(xmlcount) - // Add the Content-Type header to tell Jersey which format it should marshall - // the entity into. - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON).build(); - } else if ("xml".equals(format)) { - return Response - // Set the status and Put your entity here. - .ok(xmlcount) - // Add the Content-Type header to tell Jersey which format it should marshall - // the entity into. - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML).build(); - } else { - // default header param - return Response - // Set the status and Put your entity here. - .ok(xmlcount).build(); + @GET + @Produces("text/html") + @Path("/help") + public StreamingOutput getHelpHTML() { + + return new StreamingOutput() { + public void write(OutputStream out) throws IOException, WebApplicationException { + + out.write("".getBytes()); + out.write("".getBytes()); + out.write("".getBytes()); + + // body + out.write("

Imixs-Document REST Service

".getBytes()); + out.write( + "

See the Imixs REST Service API for more information about this Service.

" + .getBytes()); + + // end + out.write("".getBytes()); + } + }; + } - } - - /** - * The method saves a document provided in xml format. The caller need to be assigned to the - * access role 'org.imixs.ACCESSLEVEL.MANAGERACCESS' - * - * Note: the method merges the content of the given document into an existing one because the - * DocumentService method save() did not merge an entity. But the rest service typically consumes - * only a subset of attributes. So this is the reason why we merge the entity here. In different - * to the behavior of the DocumentService the WorkflowService method process() did this merge - * automatically. - * - * @param xmlworkitem - document to be saved - * @param items - optional item list to be returned in the result - * @return - */ - @POST - // @Path("/") generates jersey warning - @Produces(MediaType.APPLICATION_XML) - @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON,}) - public Response postDocument(XMLDocument xmlworkitem, @QueryParam("items") String items) { - if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { - return Response.status(Response.Status.UNAUTHORIZED).build(); + + /** + * returns a single document defined by $uniqueid + * + * Regex for + * + * UID - e.g: bcc776f9-4e5a-4272-a613-9f5ebf35354d + * + * Snapshot: bcc776f9-4e5a-4272-a613-9f5ebf35354d-9b6655 + * + * deprecated format : 132d37bfd51-9a7868 + * + * @param uniqueid + * @return + */ + @GET + @Path("/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") + public Response getDocument(@PathParam("uniqueid") String uniqueid, @QueryParam("items") String items, + @QueryParam("format") String format) { + ItemCollection document = null; + try { + document = documentService.load(uniqueid); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + return convertResult(document, items, format); } - ItemCollection workitem; - workitem = XMLDocumentAdapter.putDocument(xmlworkitem); - if (workitem == null) { - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + /** + * Returns a resultset for a lucene Search Query + * + * @param query + * @param pageSize + * @param pageIndex + * @param items + * @return + */ + @GET + @Path("/search/{query}") + public Response findDocumentsByQuery(@PathParam("query") String query, + @DefaultValue("-1") @QueryParam("pageSize") int pageSize, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, @QueryParam("sortBy") String sortBy, + @QueryParam("sortReverse") boolean sortReverse, @QueryParam("items") String items, + @QueryParam("format") String format) { + List result = null; + try { + // decode query... + String decodedQuery = URLDecoder.decode(query, "UTF-8"); + result = documentService.find(decodedQuery, pageSize, pageIndex, sortBy, sortReverse); + + } catch (Exception e) { + logger.warning("Invalid Search Query: " + e.getMessage()); + + ItemCollection error = new ItemCollection(); + error.setItemValue("$error_message", e.getMessage()); + error.setItemValue("$error_code", "" + Response.Status.NOT_ACCEPTABLE); + return Response.ok(XMLDataCollectionAdapter.getDataCollection(error)).status(Response.Status.NOT_ACCEPTABLE) + .build(); + + } + + return convertResultList(result, items, format); } - try { - - // try to load current instance of this entity - ItemCollection currentInstance = - documentService.load(workitem.getItemValueString(WorkflowKernel.UNIQUEID)); - if (currentInstance != null) { - // merge entity into current instance - // an instance of this Entity still exists! so we update the - // new values here.... - currentInstance.replaceAllItems(workitem.getAllItems()); - workitem = currentInstance; - } - - workitem.removeItem("$error_code"); - workitem.removeItem("$error_message"); - // now lets try to process the workitem... - workitem = documentService.save(workitem); - - } catch (AccessDeniedException e) { - logger.severe(e.getMessage()); - workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); - } catch (RuntimeException e) { - logger.severe(e.getMessage()); - workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); + /** + * Returns a resultset for a JPQL statement + * + * @param query + * @param pageSize + * @param pageIndex + * @param items + * @return + */ + @GET + @Path("/jpql/{query}") + public Response findDocumentsByJPQL(@PathParam("query") String query, + @DefaultValue("" + SearchService.DEFAULT_PAGE_SIZE) @QueryParam("pageSize") int pageSize, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, @QueryParam("items") String items, + @QueryParam("format") String format) { + List result = null; + try { + // decode query... + String decodedQuery = URLDecoder.decode(query, "UTF-8"); + // compute first result.... + int firstResult = pageIndex * pageSize; + result = documentService.getDocumentsByQuery(decodedQuery, firstResult, pageSize); + } catch (Exception e) { + e.printStackTrace(); + } + return convertResultList(result, items, format); } - // return workitem - try { - if (workitem.hasItem("$error_code")) { - logger.severe(workitem.getItemValueString("$error_code") + ": " - + workitem.getItemValueString("$error_message")); - return Response - .ok(XMLDataCollectionAdapter.getDataCollection(workitem), MediaType.APPLICATION_XML) - .status(Response.Status.NOT_ACCEPTABLE).build(); - } else { - return Response.ok(XMLDataCollectionAdapter.getDataCollection(workitem, - DocumentRestService.getItemList(items)), MediaType.APPLICATION_XML).build(); - } - - } catch (Exception e) { - e.printStackTrace(); - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + /** + * Returns a total hits for a lucene Search Query + * + * @param query + * @param pageSize + * @param pageIndex + * @param items + * @return + */ + @GET + @Path("/count/{query}") + public Response countTotalHitsByQuery(@PathParam("query") String query, + @DefaultValue("-1") @QueryParam("maxResult") int maxResult, @QueryParam("format") String format) { + XMLCount xmlcount = new XMLCount(); + String decodedQuery; + try { + decodedQuery = URLDecoder.decode(query, "UTF-8"); + xmlcount.count = (long) documentService.count(decodedQuery, maxResult); + } catch (UnsupportedEncodingException | QueryException e) { + xmlcount.count = 0l; + logger.severe(e.getMessage()); + } + + if ("json".equals(format)) { + return Response + // Set the status and Put your entity here. + .ok(xmlcount) + // Add the Content-Type header to tell Jersey which format it should marshall + // the entity into. + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON).build(); + } else if ("xml".equals(format)) { + return Response + // Set the status and Put your entity here. + .ok(xmlcount) + // Add the Content-Type header to tell Jersey which format it should marshall + // the entity into. + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML).build(); + } else { + // default header param + return Response + // Set the status and Put your entity here. + .ok(xmlcount).build(); + } } - } - - /** - * Delegater putEntity @PUT - * - * @see putWorkitemDefault - * @param xmlworkitem - document to be saved - * @param items - optional item list to be returned in the result - * @return - */ - @PUT - // @Path("/") generates jersey warning - @Produces(MediaType.APPLICATION_XML) - @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON,}) - public Response putDocument(XMLDocument xmlworkitem, @QueryParam("items") String items) { - logger.finest("putDocument @PUT / delegate to POST...."); - return postDocument(xmlworkitem, items); - } - - /** - * This method deletes an entity - * - */ - @DELETE - @Path("/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") - public Response deleteEntity(@PathParam("uniqueid") String uniqueid) { - if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { - return Response.status(Response.Status.UNAUTHORIZED).build(); + + /** + * Returns the total pages for a lucene Search Query and a given page size. + * + * @param query + * @param pageSize + * @param pageIndex + * @param items + * @return + */ + @GET + @Path("/countpages/{query}") + public Response countTotalPagesByQuery(@PathParam("query") String query, + @DefaultValue("-1") @QueryParam("pageSize") int pageSize, @QueryParam("format") String format) { + XMLCount xmlcount = new XMLCount(); + String decodedQuery; + try { + decodedQuery = URLDecoder.decode(query, "UTF-8"); + xmlcount.count = (long) documentService.countPages(decodedQuery, pageSize); + } catch (UnsupportedEncodingException | QueryException e) { + xmlcount.count = 0l; + logger.severe(e.getMessage()); + + } + + if ("json".equals(format)) { + return Response + // Set the status and Put your entity here. + .ok(xmlcount) + // Add the Content-Type header to tell Jersey which format it should marshall + // the entity into. + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON).build(); + } else if ("xml".equals(format)) { + return Response + // Set the status and Put your entity here. + .ok(xmlcount) + // Add the Content-Type header to tell Jersey which format it should marshall + // the entity into. + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML).build(); + } else { + // default header param + return Response + // Set the status and Put your entity here. + .ok(xmlcount).build(); + } } - ItemCollection entity = documentService.load(uniqueid); - if (entity != null) { - documentService.remove(entity); + + /** + * The method saves a document provided in xml format. The caller need to be + * assigned to the access role 'org.imixs.ACCESSLEVEL.MANAGERACCESS' + * + * Note: the method merges the content of the given document into an existing + * one because the DocumentService method save() did not merge an entity. But + * the rest service typically consumes only a subset of attributes. So this is + * the reason why we merge the entity here. In different to the behavior of the + * DocumentService the WorkflowService method process() did this merge + * automatically. + * + * @param xmlworkitem - document to be saved + * @param items - optional item list to be returned in the result + * @return + */ + @POST + // @Path("/") generates jersey warning + @Produces(MediaType.APPLICATION_XML) + @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON, }) + public Response postDocument(XMLDocument xmlworkitem, @QueryParam("items") String items) { + if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { + return Response.status(Response.Status.UNAUTHORIZED).build(); + } + ItemCollection workitem; + workitem = XMLDocumentAdapter.putDocument(xmlworkitem); + + if (workitem == null) { + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } + + try { + + // try to load current instance of this entity + ItemCollection currentInstance = documentService.load(workitem.getItemValueString(WorkflowKernel.UNIQUEID)); + if (currentInstance != null) { + // merge entity into current instance + // an instance of this Entity still exists! so we update the + // new values here.... + currentInstance.replaceAllItems(workitem.getAllItems()); + workitem = currentInstance; + } + + workitem.removeItem("$error_code"); + workitem.removeItem("$error_message"); + // now lets try to process the workitem... + workitem = documentService.save(workitem); + + } catch (AccessDeniedException e) { + logger.severe(e.getMessage()); + workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); + } catch (RuntimeException e) { + logger.severe(e.getMessage()); + workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); + } + + // return workitem + try { + if (workitem.hasItem("$error_code")) { + logger.severe(workitem.getItemValueString("$error_code") + ": " + + workitem.getItemValueString("$error_message")); + return Response.ok(XMLDataCollectionAdapter.getDataCollection(workitem), MediaType.APPLICATION_XML) + .status(Response.Status.NOT_ACCEPTABLE).build(); + } else { + return Response.ok( + XMLDataCollectionAdapter.getDataCollection(workitem, DocumentRestService.getItemList(items)), + MediaType.APPLICATION_XML).build(); + } + + } catch (Exception e) { + e.printStackTrace(); + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } } - return Response.status(Response.Status.OK).build(); - } - - /** - * This method creates a backup of the result set form a JQPL query. The entity list will be - * stored into the file system. The backup can be restored by calling the restore method - * - * - * @param query - * @param start - * @param count - * @param filepath - path in server filesystem - * @return - */ - @PUT - @Path("/backup/{query}") - public Response backup(@PathParam("query") String query, - @QueryParam("filepath") String filepath) { - - if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { - return Response.status(Response.Status.UNAUTHORIZED).build(); + /** + * Delegater putEntity @PUT + * + * @see putWorkitemDefault + * @param xmlworkitem - document to be saved + * @param items - optional item list to be returned in the result + * @return + */ + @PUT + // @Path("/") generates jersey warning + @Produces(MediaType.APPLICATION_XML) + @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON, }) + public Response putDocument(XMLDocument xmlworkitem, @QueryParam("items") String items) { + logger.finest("putDocument @PUT / delegate to POST...."); + return postDocument(xmlworkitem, items); } - try { - // decode query... - String decodedQuery = URLDecoder.decode(query, "UTF-8"); - documentService.backup(decodedQuery, filepath); - } catch (IOException e) { - e.printStackTrace(); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); - } catch (QueryException e) { - e.printStackTrace(); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + + /** + * This method deletes an entity + * + */ + @DELETE + @Path("/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") + public Response deleteEntity(@PathParam("uniqueid") String uniqueid) { + if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { + return Response.status(Response.Status.UNAUTHORIZED).build(); + } + ItemCollection entity = documentService.load(uniqueid); + if (entity != null) { + documentService.remove(entity); + } + + return Response.status(Response.Status.OK).build(); } - return Response.status(Response.Status.OK).build(); + /** + * This method creates a backup of the result set form a JQPL query. The entity + * list will be stored into the file system. The backup can be restored by + * calling the restore method + * + * + * @param query + * @param start + * @param count + * @param filepath - path in server filesystem + * @return + */ + @PUT + @Path("/backup/{query}") + public Response backup(@PathParam("query") String query, @QueryParam("filepath") String filepath) { + + if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { + return Response.status(Response.Status.UNAUTHORIZED).build(); + } + try { + // decode query... + String decodedQuery = URLDecoder.decode(query, "UTF-8"); + documentService.backup(decodedQuery, filepath); + } catch (IOException e) { + e.printStackTrace(); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } catch (QueryException e) { + e.printStackTrace(); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } + + return Response.status(Response.Status.OK).build(); - } + } - /** - * This method restores a backup from the fileSystem - * - * @param filepath - path in server fileSystem - * @return - */ - @GET - @Path("/restore") - public Response restore(@QueryParam("filepath") String filepath) { + /** + * This method restores a backup from the fileSystem + * + * @param filepath - path in server fileSystem + * @return + */ + @GET + @Path("/restore") + public Response restore(@QueryParam("filepath") String filepath) { + + if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { + return Response.status(Response.Status.UNAUTHORIZED).build(); + } + try { + documentService.restore(filepath); + } catch (IOException e) { + e.printStackTrace(); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } + + return Response.status(Response.Status.OK).build(); - if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { - return Response.status(Response.Status.UNAUTHORIZED).build(); - } - try { - documentService.restore(filepath); - } catch (IOException e) { - e.printStackTrace(); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } - return Response.status(Response.Status.OK).build(); - - } - - /** - * Returns the IndexFieldListNoAnalyse from the lucensUpdateService - * - * @return - * @throws Exception - */ - @GET - @Path("/configuration") - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) - public Response getConfiguration(@QueryParam("format") String format) throws Exception { - if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { - return null; - } - ItemCollection config = schemaService.getConfiguration(); - - return convertResult(config, null, format); - } - - /** - * This method returns a List object from a given comma separated string. The method returns null - * if no elements are found. The provided parameter looks typical like this: - * txtWorkflowStatus,numProcessID,txtName - * - * - * @param items - * @return - */ - protected static List getItemList(String items) { - if (items == null || "".equals(items)) - return null; - Vector v = new Vector(); - StringTokenizer st = new StringTokenizer(items, ","); - while (st.hasMoreTokens()) - v.add(st.nextToken()); - return v; - } - - - /** - * This method converts a single ItemCollection into a Jax-rs response object. - *

- * The method expects optional items and format string (json|xml) - *

- * In case the result set is null, than the method returns an empty collection. - * - * @param result list of ItemCollection - * @param items - optional item list - * @param format - optional format string (json|xml) - * @return jax-rs Response object. - */ - public Response convertResult(ItemCollection workitem, String items, String format) { - if (workitem == null) { - workitem = new ItemCollection(); + /** + * Returns the IndexFieldListNoAnalyse from the lucensUpdateService + * + * @return + * @throws Exception + */ + @GET + @Path("/configuration") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public Response getConfiguration(@QueryParam("format") String format) throws Exception { + if (servletRequest.isUserInRole("org.imixs.ACCESSLEVEL.MANAGERACCESS") == false) { + return null; + } + ItemCollection config = schemaService.getConfiguration(); + + return convertResult(config, null, format); } - if ("json".equals(format)) { - return Response - // Set the status and Put your entity here. - .ok(XMLDataCollectionAdapter.getDataCollection(workitem, - DocumentRestService.getItemList(items))) - // Add the Content-Type header to tell Jersey which format it should marshall - // the entity into. - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON).build(); - } else if ("xml".equals(format)) { - return Response - // Set the status and Put your entity here. - .ok(XMLDataCollectionAdapter.getDataCollection(workitem, - DocumentRestService.getItemList(items))) - // Add the Content-Type header to tell Jersey which format it should marshall - // the entity into. - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML).build(); - } else { - // default header param - return Response - // Set the status and Put your entity here. - .ok(XMLDataCollectionAdapter.getDataCollection(workitem, - DocumentRestService.getItemList(items))) - .build(); + + /** + * This method returns a List object from a given comma separated string. The + * method returns null if no elements are found. The provided parameter looks + * typical like this: + * txtWorkflowStatus,numProcessID,txtName + * + * + * @param items + * @return + */ + protected static List getItemList(String items) { + if (items == null || "".equals(items)) + return null; + Vector v = new Vector(); + StringTokenizer st = new StringTokenizer(items, ","); + while (st.hasMoreTokens()) + v.add(st.nextToken()); + return v; } - } - - /** - * This method converts a ItemCollection List into a Jax-rs response object. - *

- * The method expects optional items and format string (json|xml) - *

- * In case the result set is null, than the method returns an empty collection. - * - * @param result list of ItemCollection - * @param items - optional item list - * @param format - optional format string (json|xml) - * @return jax-rs Response object. - */ - public Response convertResultList(List result, String items, String format) { - if (result == null) { - result = new ArrayList(); + + /** + * This method converts a single ItemCollection into a Jax-rs response object. + *

+ * The method expects optional items and format string (json|xml) + *

+ * In case the result set is null, than the method returns an empty collection. + * + * @param result list of ItemCollection + * @param items - optional item list + * @param format - optional format string (json|xml) + * @return jax-rs Response object. + */ + public Response convertResult(ItemCollection workitem, String items, String format) { + if (workitem == null) { + workitem = new ItemCollection(); + } + if ("json".equals(format)) { + return Response + // Set the status and Put your entity here. + .ok(XMLDataCollectionAdapter.getDataCollection(workitem, DocumentRestService.getItemList(items))) + // Add the Content-Type header to tell Jersey which format it should marshall + // the entity into. + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON).build(); + } else if ("xml".equals(format)) { + return Response + // Set the status and Put your entity here. + .ok(XMLDataCollectionAdapter.getDataCollection(workitem, DocumentRestService.getItemList(items))) + // Add the Content-Type header to tell Jersey which format it should marshall + // the entity into. + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML).build(); + } else { + // default header param + return Response + // Set the status and Put your entity here. + .ok(XMLDataCollectionAdapter.getDataCollection(workitem, DocumentRestService.getItemList(items))) + .build(); + } } - if ("json".equals(format)) { - return Response - // Set the status and Put your entity here. - .ok(XMLDataCollectionAdapter.getDataCollection(result, - DocumentRestService.getItemList(items))) - // Add the Content-Type header to tell Jersey which format it should marshall - // the entity into. - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON).build(); - } else if ("xml".equals(format)) { - return Response - // Set the status and Put your entity here. - .ok(XMLDataCollectionAdapter.getDataCollection(result, - DocumentRestService.getItemList(items))) - // Add the Content-Type header to tell Jersey which format it should marshall - // the entity into. - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML).build(); - } else { - // default header param - return Response - // Set the status and Put your entity here. - .ok(XMLDataCollectionAdapter.getDataCollection(result, - DocumentRestService.getItemList(items))) - .build(); + + /** + * This method converts a ItemCollection List into a Jax-rs response object. + *

+ * The method expects optional items and format string (json|xml) + *

+ * In case the result set is null, than the method returns an empty collection. + * + * @param result list of ItemCollection + * @param items - optional item list + * @param format - optional format string (json|xml) + * @return jax-rs Response object. + */ + public Response convertResultList(List result, String items, String format) { + if (result == null) { + result = new ArrayList(); + } + if ("json".equals(format)) { + return Response + // Set the status and Put your entity here. + .ok(XMLDataCollectionAdapter.getDataCollection(result, DocumentRestService.getItemList(items))) + // Add the Content-Type header to tell Jersey which format it should marshall + // the entity into. + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON).build(); + } else if ("xml".equals(format)) { + return Response + // Set the status and Put your entity here. + .ok(XMLDataCollectionAdapter.getDataCollection(result, DocumentRestService.getItemList(items))) + // Add the Content-Type header to tell Jersey which format it should marshall + // the entity into. + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML).build(); + } else { + // default header param + return Response + // Set the status and Put your entity here. + .ok(XMLDataCollectionAdapter.getDataCollection(result, DocumentRestService.getItemList(items))) + .build(); + } } - } } diff --git a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/DocumentTableWriter.java b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/DocumentTableWriter.java index 648104b1d..c3c04b241 100644 --- a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/DocumentTableWriter.java +++ b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/DocumentTableWriter.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *

- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.jaxrs; @@ -47,8 +46,8 @@ import org.imixs.workflow.xml.XMLDocumentAdapter; /** - * This MessageBodyWriter generates an HTML representation from a EntityTable. The output is a table - * format where each entity has the same columns. + * This MessageBodyWriter generates an HTML representation from a EntityTable. + * The output is a table format where each entity has the same columns. * * @author rsoika * @@ -56,81 +55,78 @@ @Provider public class DocumentTableWriter implements MessageBodyWriter { + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return DocumentTable.class.isAssignableFrom(type); + } - public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, - MediaType mediaType) { - return DocumentTable.class.isAssignableFrom(type); - } - - /** - * This method prints the collection data into a HTML table - * - * - */ - @SuppressWarnings({"rawtypes"}) - public void writeTo(DocumentTable documentTable, Class type, Type genericType, - Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, - OutputStream entityStream) throws IOException, WebApplicationException { - - boolean trClass = true; - - BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(entityStream)); + /** + * This method prints the collection data into a HTML table + * + * + */ + @SuppressWarnings({ "rawtypes" }) + public void writeTo(DocumentTable documentTable, Class type, Type genericType, Annotation[] annotations, + MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) + throws IOException, WebApplicationException { - bw.write(""); - XMLItemCollectionWriter.printHead(bw, mediaType.toString(), documentTable.getEncoding()); + boolean trClass = true; - bw.write(""); + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(entityStream)); - /* Print table header */ - bw.write(""); - if (trClass) - bw.write(""); - else - bw.write(""); - trClass = !trClass; + bw.write(""); + XMLItemCollectionWriter.printHead(bw, mediaType.toString(), documentTable.getEncoding()); - for (String label : documentTable.getLabels()) { - bw.write(""); - } - bw.write(""); + bw.write(""); - // print table body - try { - - for (XMLDocument xmlworkItem : documentTable.getDocument()) { - /* Print row */ + /* Print table header */ + bw.write("
" + label + "
"); if (trClass) - bw.write(""); + bw.write(""); else - bw.write(""); + bw.write(""); trClass = !trClass; - ItemCollection itemCol = XMLDocumentAdapter.putDocument(xmlworkItem); - for (String itemName : documentTable.getItems()) { - // test if item name contains format or converter definition - List vValues = itemCol.getItemValue(itemName); - bw.write(""); + for (String label : documentTable.getLabels()) { + bw.write(""); } bw.write(""); - } - - bw.write("
" + XMLItemCollectionWriter.convertValuesToString(vValues) + "" + label + "
"); - } catch ( - Exception e) { - bw.write("ERROR
"); - // e.printStackTrace(bw.); - } + // print table body + try { + + for (XMLDocument xmlworkItem : documentTable.getDocument()) { + /* Print row */ + if (trClass) + bw.write(""); + else + bw.write(""); + trClass = !trClass; + + ItemCollection itemCol = XMLDocumentAdapter.putDocument(xmlworkItem); + for (String itemName : documentTable.getItems()) { + // test if item name contains format or converter definition + List vValues = itemCol.getItemValue(itemName); + bw.write("" + XMLItemCollectionWriter.convertValuesToString(vValues) + ""); + } + bw.write(""); + } + + bw.write(""); + } catch ( + + Exception e) { + bw.write("ERROR
"); + // e.printStackTrace(bw.); + } - bw.write(""); - bw.write(""); + bw.write(""); + bw.write(""); - bw.flush(); - } + bw.flush(); + } - public long getSize(DocumentTable arg0, Class arg1, Type arg2, Annotation[] arg3, - MediaType arg4) { - return -1; - } + public long getSize(DocumentTable arg0, Class arg1, Type arg2, Annotation[] arg3, MediaType arg4) { + return -1; + } } diff --git a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/EventLogRestService.java b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/EventLogRestService.java index ad51a70bc..5cb9d010c 100644 --- a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/EventLogRestService.java +++ b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/EventLogRestService.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.jaxrs; @@ -51,70 +50,69 @@ import org.imixs.workflow.xml.XMLDataCollectionAdapter; /** - * The EventLogRestService supports methods to access the event log entries by different kind of - * request URIs + * The EventLogRestService supports methods to access the event log entries by + * different kind of request URIs * * @author rsoika * */ @Path("/eventlog") -@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML, - MediaType.TEXT_XML}) +@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML, MediaType.TEXT_XML }) @Stateless public class EventLogRestService { - @Inject - private EventLogService eventLogService; + @Inject + private EventLogService eventLogService; - @Context - private HttpServletRequest servletRequest; + @Context + private HttpServletRequest servletRequest; - private static Logger logger = Logger.getLogger(EventLogRestService.class.getName()); + private static Logger logger = Logger.getLogger(EventLogRestService.class.getName()); - /** - * Returns a set of eventLog entries for a given topic. Multiple topics can be separated by a - * swung dash (~). - * - * @param topic - topic to search event log entries. - * @param maxCount - max count of returned eventLogEntries (default 99) - * @return - xmlDataCollection containing all matching eventLog entries - */ - @GET - @Path("/{topic}") - public XMLDataCollection getEventLogEntriesByTopic(@PathParam("topic") String topic, - @DefaultValue("99") @QueryParam("maxCount") int maxCount) { + /** + * Returns a set of eventLog entries for a given topic. Multiple topics can be + * separated by a swung dash (~). + * + * @param topic - topic to search event log entries. + * @param maxCount - max count of returned eventLogEntries (default 99) + * @return - xmlDataCollection containing all matching eventLog entries + */ + @GET + @Path("/{topic}") + public XMLDataCollection getEventLogEntriesByTopic(@PathParam("topic") String topic, + @DefaultValue("99") @QueryParam("maxCount") int maxCount) { - logger.finest("......get eventLogEntry by topic: " + topic); - // we split the topic by swung dash if multiple topics are provided - String[] topicList = topic.split("~"); - List eventLogEntries = eventLogService.findEventsByTopic(maxCount, topicList); + logger.finest("......get eventLogEntry by topic: " + topic); + // we split the topic by swung dash if multiple topics are provided + String[] topicList = topic.split("~"); + List eventLogEntries = eventLogService.findEventsByTopic(maxCount, topicList); - List result = new ArrayList(); - for (EventLog eventLog : eventLogEntries) { - // Build a ItemCollection for each EventLog + List result = new ArrayList(); + for (EventLog eventLog : eventLogEntries) { + // Build a ItemCollection for each EventLog - ItemCollection itemColEvent = new ItemCollection(); - itemColEvent.setItemValue("id", eventLog.getId()); - itemColEvent.setItemValue("ref", eventLog.getRef()); - itemColEvent.setItemValue("created", eventLog.getCreated()); - itemColEvent.setItemValue("topic", eventLog.getTopic()); - itemColEvent.setItemValue("data", eventLog.getData()); + ItemCollection itemColEvent = new ItemCollection(); + itemColEvent.setItemValue("id", eventLog.getId()); + itemColEvent.setItemValue("ref", eventLog.getRef()); + itemColEvent.setItemValue("created", eventLog.getCreated()); + itemColEvent.setItemValue("topic", eventLog.getTopic()); + itemColEvent.setItemValue("data", eventLog.getData()); - result.add(itemColEvent); + result.add(itemColEvent); + } + return XMLDataCollectionAdapter.getDataCollection(result); } - return XMLDataCollectionAdapter.getDataCollection(result); - } - /** - * Deletes a eventLog entry by its $uniqueID - * - * @param name of report or uniqueid - */ - @DELETE - @Path("/{id}") - public void deleteEventLogEntry(@PathParam("id") String id) { - // remove eventLogEntry.... - eventLogService.removeEvent(id); - } + /** + * Deletes a eventLog entry by its $uniqueID + * + * @param name of report or uniqueid + */ + @DELETE + @Path("/{id}") + public void deleteEventLogEntry(@PathParam("id") String id) { + // remove eventLogEntry.... + eventLogService.removeEvent(id); + } } diff --git a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/ModelRestService.java b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/ModelRestService.java index d513ca270..a3664300f 100644 --- a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/ModelRestService.java +++ b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/ModelRestService.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.jaxrs; @@ -69,458 +68,457 @@ import org.imixs.workflow.xml.XMLDocumentAdapter; /** - * The WorkflowService Handler supports methods to process different kind of request URIs + * The WorkflowService Handler supports methods to process different kind of + * request URIs * * @author rsoika * */ @Path("/model") -@Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML_XML, MediaType.APPLICATION_XML, - MediaType.APPLICATION_JSON, MediaType.TEXT_XML}) +@Produces({ MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, + MediaType.TEXT_XML }) @Stateless public class ModelRestService { - private static Logger logger = Logger.getLogger(ModelRestService.class.getName()); - - static List modelEntityTypes = - Arrays.asList("WorkflowEnvironmentEntity", "processentity", "activityentity"); + private static Logger logger = Logger.getLogger(ModelRestService.class.getName()); - @Inject - private DocumentService documentService; + static List modelEntityTypes = Arrays.asList("WorkflowEnvironmentEntity", "processentity", + "activityentity"); - @Inject - private WorkflowRestService workflowRestService; + @Inject + private DocumentService documentService; - @Inject - private ModelService modelService; + @Inject + private WorkflowRestService workflowRestService; - @javax.ws.rs.core.Context - private HttpServletRequest servletRequest; + @Inject + private ModelService modelService; - @GET - @Produces({MediaType.TEXT_HTML}) - public StreamingOutput getModelOverview() { - return new StreamingOutput() { - public void write(OutputStream out) throws IOException, WebApplicationException { + @javax.ws.rs.core.Context + private HttpServletRequest servletRequest; - out.write("".getBytes()); - out.write("".getBytes()); - out.write("".getBytes()); + out.write("table tr.b {background-color: #eee;}".getBytes()); - out.write("

Imixs-Workflow Model Service

".getBytes()); - out.write("

".getBytes()); - printVersionTable(out); - out.write("

".getBytes()); - // footer - out.write( - "

See the Imixs-Workflow REST API for more information.

" - .getBytes()); + out.write("".getBytes()); + out.write("".getBytes()); - // end - out.write("".getBytes()); - } - }; + out.write("

Imixs-Workflow Model Service

".getBytes()); + out.write("

".getBytes()); + printVersionTable(out); + out.write("

".getBytes()); + // footer + out.write( + "

See the Imixs-Workflow REST API for more information.

" + .getBytes()); - } + // end + out.write("".getBytes()); + } + }; - /** - * This helper method prints the current model information in html format - */ - private void printVersionTable(OutputStream out) { - try { - StringBuffer buffer = new StringBuffer(); - - List modelVersionList = modelService.getVersions(); + } - // compute rootContext: - String rootContext = servletRequest.getContextPath() + servletRequest.getServletPath(); + /** + * This helper method prints the current model information in html format + */ + private void printVersionTable(OutputStream out) { + try { + StringBuffer buffer = new StringBuffer(); + + List modelVersionList = modelService.getVersions(); + + // compute rootContext: + String rootContext = servletRequest.getContextPath() + servletRequest.getServletPath(); + + buffer.append(""); + buffer.append(""); + for (String modelVersion : modelVersionList) { + + Model model = modelService.getModel(modelVersion); + ItemCollection modelEntity = modelService.loadModelEntity(modelVersion); + + // now check groups... + List groupList = model.getGroups(); + + buffer.append(""); + + if (modelEntity != null) { + + buffer.append(""); + + // print upload date... + if (modelEntity != null) { + Date dat = modelEntity.getItemValueDate("$Modified"); + SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + buffer.append(""); + } + } else { + buffer.append(""); + buffer.append(""); + } + + // Groups + buffer.append(""); + buffer.append(""); + + } + + buffer.append("
VersionUploadedWorkflow Groups
" + modelVersion + + "" + formater.format(dat) + "" + modelVersion + " - "); + for (String group : groupList) { + // build a link for each group to get the Tasks + + buffer.append("" + + group + "
"); + } + buffer.append("
"); + out.write(buffer.toString().getBytes()); + } catch (ModelException | IOException e) { + // no opp! + try { + out.write("No model definition found.".getBytes()); + } catch (IOException e1) { + + e1.printStackTrace(); + } + } + } - buffer.append(""); - buffer.append(""); - for (String modelVersion : modelVersionList) { + @GET + @Produces({ MediaType.APPLICATION_XML, MediaType.TEXT_XML }) + public String getModelXML() { + List col = null; + StringBuffer sb = new StringBuffer(); + sb.append(""); + try { + col = modelService.getVersions(); + + for (String aversion : col) { + sb.append("" + aversion + ""); + } + } catch (Exception e) { + e.printStackTrace(); + } + sb.append(""); + return sb.toString(); + } - Model model = modelService.getModel(modelVersion); - ItemCollection modelEntity = modelService.loadModelEntity(modelVersion); + @GET + @Path("/{version}/tasks/") + public XMLDataCollection findAllTasks(@PathParam("version") String version, @QueryParam("items") String items) { + Collection col = null; + try { - // now check groups... - List groupList = model.getGroups(); + col = modelService.getModel(version).findAllTasks(); + return XMLDataCollectionAdapter.getDataCollection(col, getItemList(items)); - buffer.append(""); + } catch (Exception e) { + e.printStackTrace(); + } + return new XMLDataCollection(); + } + @GET + @Path("/{version}/bpmn") + public Response getModelFile(@PathParam("version") String version, @Context UriInfo uriInfo) { + ItemCollection modelEntity = modelService.loadModelEntity(version); if (modelEntity != null) { - - buffer.append(""); - - // print upload date... - if (modelEntity != null) { - Date dat = modelEntity.getItemValueDate("$Modified"); - SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - buffer.append(""); - } + return workflowRestService.getWorkItemFile(modelEntity.getUniqueID(), modelEntity.getFileNames().get(0), + uriInfo); } else { - buffer.append(""); - buffer.append(""); + return Response.status(Response.Status.NOT_FOUND).build(); } + } - // Groups - buffer.append(""); - buffer.append(""); - - } - - buffer.append("
VersionUploadedWorkflow Groups
" - + modelVersion + "" + formater.format(dat) + "" + modelVersion + " - "); - for (String group : groupList) { - // build a link for each group to get the Tasks - - buffer.append("" + group + "
"); + /** + * Returns the model definition containing general model information (e.g. + * $ModelVersion). + * + */ + @GET + @Path("/{version}/definition") + public XMLDataCollection getDefiniton(@PathParam("version") String version, @QueryParam("items") String items) { + ItemCollection definition = null; + try { + definition = modelService.getModel(version).getDefinition(); + return XMLDataCollectionAdapter.getDataCollection(definition, getItemList(items)); + + } catch (Exception e) { + e.printStackTrace(); } - buffer.append("
"); - out.write(buffer.toString().getBytes()); - } catch (ModelException | IOException e) { - // no opp! - try { - out.write("No model definition found.".getBytes()); - } catch (IOException e1) { - - e1.printStackTrace(); - } - } - } - - @GET - @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) - public String getModelXML() { - List col = null; - StringBuffer sb = new StringBuffer(); - sb.append(""); - try { - col = modelService.getVersions(); - - for (String aversion : col) { - sb.append("" + aversion + ""); - } - } catch (Exception e) { - e.printStackTrace(); - } - sb.append(""); - return sb.toString(); - } - - @GET - @Path("/{version}/tasks/") - public XMLDataCollection findAllTasks(@PathParam("version") String version, - @QueryParam("items") String items) { - Collection col = null; - try { - - col = modelService.getModel(version).findAllTasks(); - return XMLDataCollectionAdapter.getDataCollection(col, getItemList(items)); - - } catch (Exception e) { - e.printStackTrace(); + return new XMLDataCollection(); } - return new XMLDataCollection(); - } - - @GET - @Path("/{version}/bpmn") - public Response getModelFile(@PathParam("version") String version, @Context UriInfo uriInfo) { - ItemCollection modelEntity = modelService.loadModelEntity(version); - if (modelEntity != null) { - return workflowRestService.getWorkItemFile(modelEntity.getUniqueID(), - modelEntity.getFileNames().get(0), uriInfo); - } else { - return Response.status(Response.Status.NOT_FOUND).build(); + + @GET + @Path("/{version}/tasks/{taskid}") + public XMLDataCollection getTask(@PathParam("version") String version, @PathParam("taskid") int processid, + @QueryParam("items") String items) { + ItemCollection process = null; + try { + process = modelService.getModel(version).getTask(processid); + return XMLDataCollectionAdapter.getDataCollection(process, getItemList(items)); + + } catch (Exception e) { + e.printStackTrace(); + } + return new XMLDataCollection(); } - } - - /** - * Returns the model definition containing general model information (e.g. $ModelVersion). - * - */ - @GET - @Path("/{version}/definition") - public XMLDataCollection getDefiniton(@PathParam("version") String version, - @QueryParam("items") String items) { - ItemCollection definition = null; - try { - definition = modelService.getModel(version).getDefinition(); - return XMLDataCollectionAdapter.getDataCollection(definition, getItemList(items)); - - } catch (Exception e) { - e.printStackTrace(); + + @GET + @Path("/{version}/tasks/{taskid}/events") + public XMLDataCollection findAllEventsByTask(@PathParam("version") String version, + @PathParam("taskid") int processid, @QueryParam("items") String items) { + Collection col = null; + try { + col = modelService.getModel(version).findAllEventsByTask(processid); + return XMLDataCollectionAdapter.getDataCollection(col, getItemList(items)); + } catch (Exception e) { + e.printStackTrace(); + } + return new XMLDataCollection(); } - return new XMLDataCollection(); - } - - @GET - @Path("/{version}/tasks/{taskid}") - public XMLDataCollection getTask(@PathParam("version") String version, - @PathParam("taskid") int processid, @QueryParam("items") String items) { - ItemCollection process = null; - try { - process = modelService.getModel(version).getTask(processid); - return XMLDataCollectionAdapter.getDataCollection(process, getItemList(items)); - - } catch (Exception e) { - e.printStackTrace(); + + /** + * Retuns a list of all Start Entities from each workflowgroup + * + * @param version + * @return + */ + @GET + @Path("/{version}/groups") + public List getGroups(@PathParam("version") String version, @QueryParam("items") String items) { + List col = null; + try { + + col = modelService.getModel(version).getGroups(); + return col; + + } catch (Exception e) { + e.printStackTrace(); + } + return null; } - return new XMLDataCollection(); - } - - @GET - @Path("/{version}/tasks/{taskid}/events") - public XMLDataCollection findAllEventsByTask(@PathParam("version") String version, - @PathParam("taskid") int processid, @QueryParam("items") String items) { - Collection col = null; - try { - col = modelService.getModel(version).findAllEventsByTask(processid); - return XMLDataCollectionAdapter.getDataCollection(col, getItemList(items)); - } catch (Exception e) { - e.printStackTrace(); + + /** + * Returns a list of all Tasks of a specific workflow group. + * + * @param version + * @return + */ + @GET + @Path("/{version}/groups/{group}") + public XMLDataCollection findTasksByGroup(@PathParam("version") String version, @PathParam("group") String group, + @QueryParam("items") String items) { + Collection col = null; + try { + col = modelService.getModel(version).findTasksByGroup(group); + return XMLDataCollectionAdapter.getDataCollection(col, getItemList(items)); + + } catch (Exception e) { + e.printStackTrace(); + } + return new XMLDataCollection(); } - return new XMLDataCollection(); - } - - /** - * Retuns a list of all Start Entities from each workflowgroup - * - * @param version - * @return - */ - @GET - @Path("/{version}/groups") - public List getGroups(@PathParam("version") String version, - @QueryParam("items") String items) { - List col = null; - try { - - col = modelService.getModel(version).getGroups(); - return col; - - } catch (Exception e) { - e.printStackTrace(); + + @DELETE + @Path("/{version}") + public void deleteModel(@PathParam("version") String version) { + try { + modelService.deleteModel(version); + } catch (Exception e) { + e.printStackTrace(); + } + } - return null; - } - - /** - * Returns a list of all Tasks of a specific workflow group. - * - * @param version - * @return - */ - @GET - @Path("/{version}/groups/{group}") - public XMLDataCollection findTasksByGroup(@PathParam("version") String version, - @PathParam("group") String group, @QueryParam("items") String items) { - Collection col = null; - try { - col = modelService.getModel(version).findTasksByGroup(group); - return XMLDataCollectionAdapter.getDataCollection(col, getItemList(items)); - - } catch (Exception e) { - e.printStackTrace(); + + /** + * This method consumes a Imixs BPMN model file and updates the corresponding + * model information. + * + * @param model + * @return + */ + @PUT + @Path("/bpmn") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN }) + public Response putBPMNModel(BPMNModel bpmnmodel) { + try { + logger.fine("BPMN Model posted... "); + modelService.saveModel(bpmnmodel); + } catch (ModelException e) { + logger.warning("Unable to update model: " + e.getMessage()); + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } + logger.fine("putBPMNModel finished! "); + return Response.status(Response.Status.OK).build(); } - return new XMLDataCollection(); - } - - @DELETE - @Path("/{version}") - public void deleteModel(@PathParam("version") String version) { - try { - modelService.deleteModel(version); - } catch (Exception e) { - e.printStackTrace(); + + /** + * This method consumes a Imixs BPMN model file and updates the corresponding + * model information. + *

+ * The filename param is used to store the file in the corresponding bpmn + * document. + * + * @param model + * @return + */ + @PUT + @Path("/bpmn/{filename}") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN }) + public Response putBPMNModel(@PathParam("filename") String filename, BPMNModel bpmnmodel) { + try { + logger.fine("BPMN Model posted... "); + modelService.saveModel(bpmnmodel, filename); + } catch (ModelException e) { + logger.warning("Unable to update model: " + e.getMessage()); + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } + logger.fine("putBPMNModel finished! "); + return Response.status(Response.Status.OK).build(); } - } - - /** - * This method consumes a Imixs BPMN model file and updates the corresponding model information. - * - * @param model - * @return - */ - @PUT - @Path("/bpmn") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN}) - public Response putBPMNModel(BPMNModel bpmnmodel) { - try { - logger.fine("BPMN Model posted... "); - modelService.saveModel(bpmnmodel); - } catch (ModelException e) { - logger.warning("Unable to update model: " + e.getMessage()); - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + @POST + @Path("/bpmn") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN }) + public Response postBPMNModel(BPMNModel bpmnmodel) { + return putBPMNModel(bpmnmodel); } - logger.fine("putBPMNModel finished! "); - return Response.status(Response.Status.OK).build(); - } - - /** - * This method consumes a Imixs BPMN model file and updates the corresponding model information. - *

- * The filename param is used to store the file in the corresponding bpmn document. - * - * @param model - * @return - */ - @PUT - @Path("/bpmn/{filename}") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN}) - public Response putBPMNModel(@PathParam("filename") String filename, BPMNModel bpmnmodel) { - try { - logger.fine("BPMN Model posted... "); - modelService.saveModel(bpmnmodel, filename); - } catch (ModelException e) { - logger.warning("Unable to update model: " + e.getMessage()); - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + + @POST + @Path("/bpmn/{filename}") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN }) + public Response postBPMNModel(@PathParam("filename") String filename, BPMNModel bpmnmodel) { + return putBPMNModel(filename, bpmnmodel); } - logger.fine("putBPMNModel finished! "); - return Response.status(Response.Status.OK).build(); - } - - @POST - @Path("/bpmn") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN}) - public Response postBPMNModel(BPMNModel bpmnmodel) { - return putBPMNModel(bpmnmodel); - } - - @POST - @Path("/bpmn/{filename}") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN}) - public Response postBPMNModel(@PathParam("filename") String filename, BPMNModel bpmnmodel) { - return putBPMNModel(filename, bpmnmodel); - } - - /** - * This method updates a Model provided in a EntityCollection object for a provided model version. - * The Method expects a subresource with a ModelVersion. Next the method updates each Entity - * object with the property $ModelVersion. An old version will be automatically removed before - * update. - * - * @param version - $modelversion - * @param ecol - model data - */ - @PUT - @Path("/{version}") - @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) - public void putModelByVersion(@PathParam("version") final String _modelVersion, - XMLDataCollection ecol) { - - String sModelVersion = _modelVersion; - XMLDocument entity; - ItemCollection itemCollection; - try { - if (ecol.getDocument().length > 0) { - /* - * first we need to delete the old model if available. - */ - if (sModelVersion == null) - sModelVersion = ""; - - // delete old model if a modelversion is available - if (!"".equals(sModelVersion)) - modelService.removeModel(sModelVersion); - - // save new entities into database and update modelversion..... - for (int i = 0; i < ecol.getDocument().length; i++) { - entity = ecol.getDocument()[i]; - itemCollection = XMLDocumentAdapter.putDocument(entity); - // update model version - itemCollection.replaceItemValue("$modelVersion", sModelVersion); - // save entity - documentService.save(itemCollection); + + /** + * This method updates a Model provided in a EntityCollection object for a + * provided model version. The Method expects a subresource with a ModelVersion. + * Next the method updates each Entity object with the property $ModelVersion. + * An old version will be automatically removed before update. + * + * @param version - $modelversion + * @param ecol - model data + */ + @PUT + @Path("/{version}") + @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML }) + public void putModelByVersion(@PathParam("version") final String _modelVersion, XMLDataCollection ecol) { + + String sModelVersion = _modelVersion; + XMLDocument entity; + ItemCollection itemCollection; + try { + if (ecol.getDocument().length > 0) { + /* + * first we need to delete the old model if available. + */ + if (sModelVersion == null) + sModelVersion = ""; + + // delete old model if a modelversion is available + if (!"".equals(sModelVersion)) + modelService.removeModel(sModelVersion); + + // save new entities into database and update modelversion..... + for (int i = 0; i < ecol.getDocument().length; i++) { + entity = ecol.getDocument()[i]; + itemCollection = XMLDocumentAdapter.putDocument(entity); + // update model version + itemCollection.replaceItemValue("$modelVersion", sModelVersion); + // save entity + documentService.save(itemCollection); + } + } + + } catch (Exception e) { + e.printStackTrace(); } - } - } catch (Exception e) { - e.printStackTrace(); } - } - - @POST - @Path("/{version}") - @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) - public void postModelByVersion(@PathParam("version") String sModelVersion, - XMLDataCollection ecol) { - putModelByVersion(sModelVersion, ecol); - } - - /** - * This method updates a Model provided in a EntityCollection object. - * - * The method takes the first entity to get the provided $modelVersion. An old version will be - * automatically removed before update. - * - * @param ecol - */ - @PUT - @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) - public void putModel(XMLDataCollection ecol) { - String sModelVersion = null; - XMLDocument entity; - ItemCollection itemCollection; - try { - if (ecol.getDocument().length > 0) { - /* - * first we need get model version from first entity - */ - entity = ecol.getDocument()[0]; - itemCollection = XMLDocumentAdapter.putDocument(entity); - sModelVersion = itemCollection.getItemValueString("$ModelVersion"); - + @POST + @Path("/{version}") + @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML }) + public void postModelByVersion(@PathParam("version") String sModelVersion, XMLDataCollection ecol) { putModelByVersion(sModelVersion, ecol); + } - } + /** + * This method updates a Model provided in a EntityCollection object. + * + * The method takes the first entity to get the provided $modelVersion. An old + * version will be automatically removed before update. + * + * @param ecol + */ + @PUT + @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML }) + public void putModel(XMLDataCollection ecol) { + String sModelVersion = null; + XMLDocument entity; + ItemCollection itemCollection; + try { + if (ecol.getDocument().length > 0) { + /* + * first we need get model version from first entity + */ + entity = ecol.getDocument()[0]; + itemCollection = XMLDocumentAdapter.putDocument(entity); + sModelVersion = itemCollection.getItemValueString("$ModelVersion"); + + putModelByVersion(sModelVersion, ecol); + + } + + } catch (Exception e) { + e.printStackTrace(); + } - } catch (Exception e) { - e.printStackTrace(); } - } - - @POST - @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) - public void postModel(XMLDataCollection ecol) { - putModel(ecol); - } - - /** - * This method returns a List object from a given comma separated string. The method returns null - * if no elements are found. The provided parameter looks typical like this: - * txtWorkflowStatus,numProcessID,txtName - * - * - * @param items - * @return - */ - private List getItemList(String items) { - if (items == null || "".equals(items)) - return null; - Vector v = new Vector(); - StringTokenizer st = new StringTokenizer(items, ","); - while (st.hasMoreTokens()) - v.add(st.nextToken()); - return v; - } + @POST + @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML }) + public void postModel(XMLDataCollection ecol) { + putModel(ecol); + } + + /** + * This method returns a List object from a given comma separated string. The + * method returns null if no elements are found. The provided parameter looks + * typical like this: + * txtWorkflowStatus,numProcessID,txtName + * + * + * @param items + * @return + */ + private List getItemList(String items) { + if (items == null || "".equals(items)) + return null; + Vector v = new Vector(); + StringTokenizer st = new StringTokenizer(items, ","); + while (st.hasMoreTokens()) + v.add(st.nextToken()); + return v; + } } diff --git a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/ReportRestService.java b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/ReportRestService.java index 001b5a120..17725832d 100644 --- a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/ReportRestService.java +++ b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/ReportRestService.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *

- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.jaxrs; @@ -87,543 +86,542 @@ import org.imixs.workflow.xml.XSLHandler; /** - * The WorkflowService Handler supports methods to process different kind of request URIs + * The WorkflowService Handler supports methods to process different kind of + * request URIs * * @author rsoika * */ @Path("/report") -@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML, - MediaType.TEXT_XML}) +@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML, MediaType.TEXT_XML }) @Stateless public class ReportRestService { - @Inject - private DocumentService entityService; + @Inject + private DocumentService entityService; - @Inject - private ReportService reportService; + @Inject + private ReportService reportService; - @Context - private HttpServletRequest servletRequest; + @Context + private HttpServletRequest servletRequest; - private static Logger logger = Logger.getLogger(ReportRestService.class.getName()); + private static Logger logger = Logger.getLogger(ReportRestService.class.getName()); - @GET - @Produces("text/html") - public StreamingOutput getHelpHTML() { - return new StreamingOutput() { - public void write(OutputStream out) throws IOException, WebApplicationException { + @GET + @Produces("text/html") + public StreamingOutput getHelpHTML() { + return new StreamingOutput() { + public void write(OutputStream out) throws IOException, WebApplicationException { - out.write("".getBytes()); - out.write("".getBytes()); - out.write("".getBytes()); + out.write("".getBytes()); + out.write("".getBytes()); - // body - out.write("

Imixs-Workflow REST Service

".getBytes()); - out.write( - "

See the Imixs-Workflow REST API for more information about this Service.

" - .getBytes()); + // body + out.write("

Imixs-Workflow REST Service

".getBytes()); + out.write( + "

See the Imixs-Workflow REST API for more information about this Service.

" + .getBytes()); - // end - out.write("".getBytes()); - } - }; + // end + out.write("".getBytes()); + } + }; - } + } - @GET - @Path("/definitions") - public XMLDataCollection getReportsDefinitions() { - try { + @GET + @Path("/definitions") + public XMLDataCollection getReportsDefinitions() { + try { - Collection col = null; - col = reportService.findAllReports(); - return XMLDataCollectionAdapter.getDataCollection(col); - } catch (Exception e) { - e.printStackTrace(); - } - return new XMLDataCollection(); - } - - /** - * Returns a single report by name or by uniqueid - * - * @param name reportname or uniqueid of report - * @return - */ - @GET - @Path("/definitions/{name}") - public XMLDataCollection getReportDefinition(@PathParam("name") String name) { - try { - ItemCollection itemCol = reportService.findReport(name); - return XMLDataCollectionAdapter.getDataCollection(itemCol); - } catch (Exception e) { - e.printStackTrace(); + Collection col = null; + col = reportService.findAllReports(); + return XMLDataCollectionAdapter.getDataCollection(col); + } catch (Exception e) { + e.printStackTrace(); + } + return new XMLDataCollection(); } - return null; - } - - /** - * Executes a single report defined by name or uniqueid - * - * The output depends on the requested media format - * - * Since 2.1.2: the ReportService also supports FOP Transformation. If the ContentType is - * 'application/pdf' the method will call fopTransofrmation instat of xslTransformation. The FOP - * API need to be provided by the main application. - * - * @param name reportname of the report to be executed - * @return a collection of entiteis - * - */ - @GET - @Path("/{name}.imixs-report") - public Response getExcecuteReport(@PathParam("name") String reportName, - @DefaultValue("1000") @QueryParam("pageSize") int pageSize, - @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @QueryParam("sortBy") String sortBy, @QueryParam("sortReverse") boolean sortReverse, - @DefaultValue("") @QueryParam("encoding") String encoding, @Context UriInfo uriInfo) { - Collection col = null; - - String sXSL; - String sContentType; - - try { - - ItemCollection report = reportService.findReport(reportName); - if (report == null) { - logger.severe("Report '" + reportName + "' not defined!"); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); - } - - sXSL = report.getItemValueString("XSL").trim(); - sContentType = report.getItemValueString("contenttype"); - if ("".equals(sContentType)) - sContentType = "text/html"; - - // if no encoding is provided by the query string than the encoding - // from the report will be taken - if ("".equals(encoding)) - encoding = report.getItemValueString("encoding"); - // no encoding defined so take a default encoding - // (UTF-8) - if ("".equals(encoding)) - encoding = "UTF-8"; - - // execute report - Map params = getQueryParams(uriInfo); - col = reportService.getDataSource(report, pageSize, pageIndex, sortBy, sortReverse, params); - - // if no XSL is provided return standard html format...? - if ("".equals(sXSL)) { - Response.ResponseBuilder builder = - Response.ok(XMLDataCollectionAdapter.getDataCollection(col), "text/html"); - return builder.build(); - } - - // Transform XML per XSL and generate output - XMLDataCollection xmlCol = XMLDataCollectionAdapter.getDataCollection(col); - - StringWriter writer = new StringWriter(); - - JAXBContext context = JAXBContext.newInstance(XMLDataCollection.class); - - Marshaller m = context.createMarshaller(); - m.setProperty("jaxb.encoding", encoding); - m.marshal(xmlCol, writer); - - // create a ByteArray Output Stream - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - try { - // test if FOP Tranformation - if ("application/pdf".equals(sContentType.toLowerCase())) - fopTranformation(writer.toString(), sXSL, encoding, outputStream); - else - XSLHandler.transform(writer.toString(), sXSL, encoding, outputStream); - } finally { - outputStream.close(); - } - - /* - * outputStream.toByteArray() did not work here because the encoding will not be considered. - * For that reason we use the toString(encoding) method here. - * - * 8.9.2012: - * - * after some tests we see that only toByteArray will work on things like fop processing. So - * for that reason we switched back to the toByteArray method again. But we still need to - * solve the encoding issue - */ - - Response.ResponseBuilder builder = Response.ok(outputStream.toByteArray(), sContentType); - // Response.ResponseBuilder builder = Response.ok( - // outputStream.toString(encoding), sContentType); - return builder.build(); - } catch (Exception e) { - e.printStackTrace(); + /** + * Returns a single report by name or by uniqueid + * + * @param name reportname or uniqueid of report + * @return + */ + @GET + @Path("/definitions/{name}") + public XMLDataCollection getReportDefinition(@PathParam("name") String name) { + try { + ItemCollection itemCol = reportService.findReport(name); + return XMLDataCollectionAdapter.getDataCollection(itemCol); + } catch (Exception e) { + e.printStackTrace(); + } + return null; } - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); - - } - - /** - * helper method for .pdf file extention - * - * @param name reportname of the report to be executed - * @return a collection of entiteis - * - */ - @GET - @Path("/{name}.pdf") - public Response getPdfReport(@PathParam("name") String reportName, - @DefaultValue("1000") @QueryParam("pageSize") int pageSize, - @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @QueryParam("sortBy") String sortBy, @QueryParam("sortReverse") boolean sortReverse, - @DefaultValue("") @QueryParam("encoding") String encoding, @Context UriInfo uriInfo) { - return this.getExcecuteReport(reportName, pageSize, pageIndex, sortBy, sortReverse, encoding, - uriInfo); - } - - /** - * Returns an HTML Stream with a HTML Datatable corresponding to the report query. - * - * @param name - * @param start - * @param count - * @return - */ - @SuppressWarnings("unchecked") - @GET - @Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML_XML}) - @Path("/{name}.html") - public DocumentTable getHTMLResult(@PathParam("name") String reportName, - @DefaultValue("1000") @QueryParam("pageSize") int pageSize, - @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @QueryParam("sortBy") String sortBy, @QueryParam("sortReverse") boolean sortReverse, - @DefaultValue("") @QueryParam("encoding") String encoding, @Context UriInfo uriInfo, - @Context HttpServletResponse servlerResponse) { - Collection col = null; - - try { - ItemCollection report = reportService.findReport(reportName); - List> attributes = (List>) report.getItemValue("attributes"); - List items = new ArrayList(); - List labels = new ArrayList(); - for (List attribute : attributes) { - items.add(attribute.get(0)); - String label = attribute.get(0); - if ((attribute.size() >= 2) && !(attribute.get(1).isEmpty())) { - label = attribute.get(1); - } - labels.add(label); - } - - // execute report - Map params = getQueryParams(uriInfo); - col = reportService.getDataSource(report, pageSize, pageIndex, sortBy, sortReverse, params); - - XMLDataCollection documentCollection = XMLDataCollectionAdapter.getDataCollection(col); - DocumentTable documentTable = - new DocumentTable(documentCollection.getDocument(), items, labels, encoding); - - if (encoding == null || "".equals(encoding)) { - encoding = report.getItemValueString("encoding"); - if ("".equals(encoding)) { - // no encoding defined so take a default encoding (UTF-8) - encoding = "UTF-8"; + /** + * Executes a single report defined by name or uniqueid + * + * The output depends on the requested media format + * + * Since 2.1.2: the ReportService also supports FOP Transformation. If the + * ContentType is 'application/pdf' the method will call fopTransofrmation + * instat of xslTransformation. The FOP API need to be provided by the main + * application. + * + * @param name reportname of the report to be executed + * @return a collection of entiteis + * + */ + @GET + @Path("/{name}.imixs-report") + public Response getExcecuteReport(@PathParam("name") String reportName, + @DefaultValue("1000") @QueryParam("pageSize") int pageSize, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, @QueryParam("sortBy") String sortBy, + @QueryParam("sortReverse") boolean sortReverse, @DefaultValue("") @QueryParam("encoding") String encoding, + @Context UriInfo uriInfo) { + Collection col = null; + + String sXSL; + String sContentType; + + try { + + ItemCollection report = reportService.findReport(reportName); + if (report == null) { + logger.severe("Report '" + reportName + "' not defined!"); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } + + sXSL = report.getItemValueString("XSL").trim(); + sContentType = report.getItemValueString("contenttype"); + if ("".equals(sContentType)) + sContentType = "text/html"; + + // if no encoding is provided by the query string than the encoding + // from the report will be taken + if ("".equals(encoding)) + encoding = report.getItemValueString("encoding"); + // no encoding defined so take a default encoding + // (UTF-8) + if ("".equals(encoding)) + encoding = "UTF-8"; + + // execute report + Map params = getQueryParams(uriInfo); + col = reportService.getDataSource(report, pageSize, pageIndex, sortBy, sortReverse, params); + + // if no XSL is provided return standard html format...? + if ("".equals(sXSL)) { + Response.ResponseBuilder builder = Response.ok(XMLDataCollectionAdapter.getDataCollection(col), + "text/html"); + return builder.build(); + } + + // Transform XML per XSL and generate output + XMLDataCollection xmlCol = XMLDataCollectionAdapter.getDataCollection(col); + + StringWriter writer = new StringWriter(); + + JAXBContext context = JAXBContext.newInstance(XMLDataCollection.class); + + Marshaller m = context.createMarshaller(); + m.setProperty("jaxb.encoding", encoding); + m.marshal(xmlCol, writer); + + // create a ByteArray Output Stream + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try { + // test if FOP Tranformation + if ("application/pdf".equals(sContentType.toLowerCase())) + fopTranformation(writer.toString(), sXSL, encoding, outputStream); + else + XSLHandler.transform(writer.toString(), sXSL, encoding, outputStream); + } finally { + outputStream.close(); + } + + /* + * outputStream.toByteArray() did not work here because the encoding will not be + * considered. For that reason we use the toString(encoding) method here. + * + * 8.9.2012: + * + * after some tests we see that only toByteArray will work on things like fop + * processing. So for that reason we switched back to the toByteArray method + * again. But we still need to solve the encoding issue + */ + + Response.ResponseBuilder builder = Response.ok(outputStream.toByteArray(), sContentType); + // Response.ResponseBuilder builder = Response.ok( + // outputStream.toString(encoding), sContentType); + return builder.build(); + } catch (Exception e) { + e.printStackTrace(); + } - } - logger.fine("set encoding :" + encoding); - servlerResponse.setContentType(MediaType.TEXT_HTML + "; charset=" + encoding); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); - return documentTable; - } catch (Exception e) { - e.printStackTrace(); } - return null; - } - - /** - * Returns a Datatable corresponding to the report definition and report content type. - *

- * The path annotation allows any file extension. - * - * @param name - * @param start - * @param count - * @return - */ - @GET - @Path("/custom/{name}.{s:.*}") - public Response getCustomResult(@PathParam("name") String reportName, - @DefaultValue("1000") @QueryParam("pageSize") int pageSize, - @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @QueryParam("sortBy") String sortBy, @QueryParam("sortReverse") boolean sortReverse, - @DefaultValue("") @QueryParam("encoding") String encoding, @Context UriInfo uriInfo, - @Context HttpServletResponse servlerResponse) { - - ItemCollection report = reportService.findReport(reportName); - if (report == null) { - logger.severe("Report '" + reportName + "' not defined!"); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + + /** + * helper method for .pdf file extention + * + * @param name reportname of the report to be executed + * @return a collection of entiteis + * + */ + @GET + @Path("/{name}.pdf") + public Response getPdfReport(@PathParam("name") String reportName, + @DefaultValue("1000") @QueryParam("pageSize") int pageSize, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, @QueryParam("sortBy") String sortBy, + @QueryParam("sortReverse") boolean sortReverse, @DefaultValue("") @QueryParam("encoding") String encoding, + @Context UriInfo uriInfo) { + return this.getExcecuteReport(reportName, pageSize, pageIndex, sortBy, sortReverse, encoding, uriInfo); } - if (encoding == null || "".equals(encoding)) { - encoding = report.getItemValueString("encoding"); - if ("".equals(encoding)) { - // no encoding defined so take a default encoding (UTF-8) - encoding = "UTF-8"; - } + + /** + * Returns an HTML Stream with a HTML Datatable corresponding to the report + * query. + * + * @param name + * @param start + * @param count + * @return + */ + @SuppressWarnings("unchecked") + @GET + @Produces({ MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML_XML }) + @Path("/{name}.html") + public DocumentTable getHTMLResult(@PathParam("name") String reportName, + @DefaultValue("1000") @QueryParam("pageSize") int pageSize, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, @QueryParam("sortBy") String sortBy, + @QueryParam("sortReverse") boolean sortReverse, @DefaultValue("") @QueryParam("encoding") String encoding, + @Context UriInfo uriInfo, @Context HttpServletResponse servlerResponse) { + Collection col = null; + + try { + ItemCollection report = reportService.findReport(reportName); + List> attributes = (List>) report.getItemValue("attributes"); + List items = new ArrayList(); + List labels = new ArrayList(); + for (List attribute : attributes) { + items.add(attribute.get(0)); + String label = attribute.get(0); + if ((attribute.size() >= 2) && !(attribute.get(1).isEmpty())) { + label = attribute.get(1); + } + labels.add(label); + } + + // execute report + Map params = getQueryParams(uriInfo); + col = reportService.getDataSource(report, pageSize, pageIndex, sortBy, sortReverse, params); + + XMLDataCollection documentCollection = XMLDataCollectionAdapter.getDataCollection(col); + DocumentTable documentTable = new DocumentTable(documentCollection.getDocument(), items, labels, encoding); + + if (encoding == null || "".equals(encoding)) { + encoding = report.getItemValueString("encoding"); + if ("".equals(encoding)) { + // no encoding defined so take a default encoding (UTF-8) + encoding = "UTF-8"; + } + } + + logger.fine("set encoding :" + encoding); + servlerResponse.setContentType(MediaType.TEXT_HTML + "; charset=" + encoding); + + return documentTable; + } catch (Exception e) { + e.printStackTrace(); + } + return null; } - DocumentTable documentTable = getHTMLResult(reportName, pageSize, pageIndex, sortBy, - sortReverse, encoding, uriInfo, servlerResponse); + /** + * Returns a Datatable corresponding to the report definition and report content + * type. + *

+ * The path annotation allows any file extension. + * + * @param name + * @param start + * @param count + * @return + */ + @GET + @Path("/custom/{name}.{s:.*}") + public Response getCustomResult(@PathParam("name") String reportName, + @DefaultValue("1000") @QueryParam("pageSize") int pageSize, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, @QueryParam("sortBy") String sortBy, + @QueryParam("sortReverse") boolean sortReverse, @DefaultValue("") @QueryParam("encoding") String encoding, + @Context UriInfo uriInfo, @Context HttpServletResponse servlerResponse) { + + ItemCollection report = reportService.findReport(reportName); + if (report == null) { + logger.severe("Report '" + reportName + "' not defined!"); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } + if (encoding == null || "".equals(encoding)) { + encoding = report.getItemValueString("encoding"); + if ("".equals(encoding)) { + // no encoding defined so take a default encoding (UTF-8) + encoding = "UTF-8"; + } + } - String sContentType = report.getItemValueString("contenttype"); - if (sContentType.isEmpty()) { - sContentType = MediaType.APPLICATION_XML; - } + DocumentTable documentTable = getHTMLResult(reportName, pageSize, pageIndex, sortBy, sortReverse, encoding, + uriInfo, servlerResponse); - // set content type and character encoding - logger.fine("set encoding :" + encoding); - servlerResponse.setContentType(sContentType + "; charset=" + encoding); - - return Response.ok(documentTable, sContentType).build(); - - } - - /** - * Returns a xml stream from a report - * - * If a attribute list is defined in the report only the corresponding properties will be returend - * in the xml stream. - * - * If the query param 'items' is provided the attribute list in the report will be ignored. - * - * @param name reportname of the report to be executed - * @param start - * @param count - * @return - * @throws Exception - */ - @GET - @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) - @Path("/{name}.xml") - public XMLDataCollection getXMLResult(@PathParam("name") String reportName, - @DefaultValue("100") @QueryParam("pageSize") int pageSize, - @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @QueryParam("sortBy") String sortBy, @QueryParam("sortReverse") boolean sortReverse, - @DefaultValue("") @QueryParam("encoding") String encoding, - - @Context UriInfo uriInfo, @Context HttpServletResponse servlerResponse) throws Exception { - Collection col = null; - - try { - // execute report - ItemCollection report = reportService.findReport(reportName); - Map params = getQueryParams(uriInfo); - col = reportService.getDataSource(report, pageSize, pageIndex, sortBy, sortReverse, params); - - // set content type and character encoding - if (encoding == null || "".equals(encoding)) { - encoding = report.getItemValueString("encoding"); - if ("".equals(encoding)) { - // no encoding defined so take a default encoding (UTF-8) - encoding = "UTF-8"; + String sContentType = report.getItemValueString("contenttype"); + if (sContentType.isEmpty()) { + sContentType = MediaType.APPLICATION_XML; } - } - logger.fine("set encoding :" + encoding); - servlerResponse.setContentType(MediaType.APPLICATION_XML + "; charset=" + encoding); + // set content type and character encoding + logger.fine("set encoding :" + encoding); + servlerResponse.setContentType(sContentType + "; charset=" + encoding); - return XMLDataCollectionAdapter.getDataCollection(col); + return Response.ok(documentTable, sContentType).build(); - } catch (Exception e) { - e.printStackTrace(); } - return null; - } - - /** - * Returns a JSON stream from a report - * - * If a attribute list is defined in the report only the corresponding properties will be returend - * in the xml stream. - * - * - * @param name reportname of the report to be executed - * @param start - * @param count - * @return - * @throws Exception - */ - @GET - @Produces(MediaType.APPLICATION_JSON) - @Path("/{name}.json") - public XMLDataCollection getJSONResult(@PathParam("name") String name, - - @DefaultValue("-1") @QueryParam("pageSize") int pageSize, - @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @QueryParam("sortBy") String sortBy, @QueryParam("sortReverse") boolean sortReverse, - - @DefaultValue("") @QueryParam("encoding") String encoding, @Context UriInfo uriInfo, - @Context HttpServletResponse servlerResponse) throws Exception { - - XMLDataCollection result = getXMLResult(name, pageSize, pageIndex, sortBy, sortReverse, - encoding, uriInfo, servlerResponse); - - servlerResponse.setContentType(MediaType.APPLICATION_JSON + "; charset=" + encoding); - - return result; - - } - - /** - * Deletes a report by name or by its $uniqueID or name. - * - * @param name of report or uniqueid - */ - @DELETE - @Path("/reports/{name}") - public void deleteReport(@PathParam("name") String name) { - try { - ItemCollection itemCol = reportService.findReport(name); - entityService.remove(itemCol); - } catch (Exception e) { - e.printStackTrace(); + + /** + * Returns a xml stream from a report + * + * If a attribute list is defined in the report only the corresponding + * properties will be returend in the xml stream. + * + * If the query param 'items' is provided the attribute list in the report will + * be ignored. + * + * @param name reportname of the report to be executed + * @param start + * @param count + * @return + * @throws Exception + */ + @GET + @Produces({ MediaType.APPLICATION_XML, MediaType.TEXT_XML }) + @Path("/{name}.xml") + public XMLDataCollection getXMLResult(@PathParam("name") String reportName, + @DefaultValue("100") @QueryParam("pageSize") int pageSize, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, @QueryParam("sortBy") String sortBy, + @QueryParam("sortReverse") boolean sortReverse, @DefaultValue("") @QueryParam("encoding") String encoding, + + @Context UriInfo uriInfo, @Context HttpServletResponse servlerResponse) throws Exception { + Collection col = null; + + try { + // execute report + ItemCollection report = reportService.findReport(reportName); + Map params = getQueryParams(uriInfo); + col = reportService.getDataSource(report, pageSize, pageIndex, sortBy, sortReverse, params); + + // set content type and character encoding + if (encoding == null || "".equals(encoding)) { + encoding = report.getItemValueString("encoding"); + if ("".equals(encoding)) { + // no encoding defined so take a default encoding (UTF-8) + encoding = "UTF-8"; + } + } + + logger.fine("set encoding :" + encoding); + servlerResponse.setContentType(MediaType.APPLICATION_XML + "; charset=" + encoding); + + return XMLDataCollectionAdapter.getDataCollection(col); + + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * Returns a JSON stream from a report + * + * If a attribute list is defined in the report only the corresponding + * properties will be returend in the xml stream. + * + * + * @param name reportname of the report to be executed + * @param start + * @param count + * @return + * @throws Exception + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/{name}.json") + public XMLDataCollection getJSONResult(@PathParam("name") String name, + + @DefaultValue("-1") @QueryParam("pageSize") int pageSize, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, @QueryParam("sortBy") String sortBy, + @QueryParam("sortReverse") boolean sortReverse, + + @DefaultValue("") @QueryParam("encoding") String encoding, @Context UriInfo uriInfo, + @Context HttpServletResponse servlerResponse) throws Exception { + + XMLDataCollection result = getXMLResult(name, pageSize, pageIndex, sortBy, sortReverse, encoding, uriInfo, + servlerResponse); + + servlerResponse.setContentType(MediaType.APPLICATION_JSON + "; charset=" + encoding); + + return result; + + } + + /** + * Deletes a report by name or by its $uniqueID or name. + * + * @param name of report or uniqueid + */ + @DELETE + @Path("/reports/{name}") + public void deleteReport(@PathParam("name") String name) { + try { + ItemCollection itemCol = reportService.findReport(name); + entityService.remove(itemCol); + } catch (Exception e) { + e.printStackTrace(); + } + } - } - - /** - * This method updates or creates a Report object provided in a XMLItemCollection object - * - * - * @param reportCol - report data - */ - @PUT - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN, - MediaType.TEXT_XML}) - public void putReport(XMLDocument reportCol) { - ItemCollection itemCollection; - try { - itemCollection = XMLDocumentAdapter.putDocument(reportCol); - reportService.updateReport(itemCollection); - } catch (Exception e) { - e.printStackTrace(); + /** + * This method updates or creates a Report object provided in a + * XMLItemCollection object + * + * + * @param reportCol - report data + */ + @PUT + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN, + MediaType.TEXT_XML }) + public void putReport(XMLDocument reportCol) { + ItemCollection itemCollection; + try { + itemCollection = XMLDocumentAdapter.putDocument(reportCol); + reportService.updateReport(itemCollection); + } catch (Exception e) { + e.printStackTrace(); + } } - } - - @POST - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN, - MediaType.TEXT_XML}) - public void postReport(XMLDocument reportCol) { - putReport(reportCol); - } - - /** - * This method dos a apache FOP transformation using the FopFactory - * - * @param xmlSource - * @param xslSource - * @param aEncoding - * @param outputWriter - */ - public void fopTranformation(String xmlSource, String xslSource, String aEncoding, - OutputStream output) throws Exception { - // configure fopFactory as desired - FopFactory fopFactory = FopFactory.newInstance(); - - FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); - foUserAgent.setBaseURL(fopFactory.getBaseURL()); - - // configure foUserAgent as desired - // OutputStream out =null; - try { - // Construct fop with desired output format - Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, output); - - // Setup XSLT - TransformerFactory factory = TransformerFactory.newInstance(); - ByteArrayInputStream baisXSL = new ByteArrayInputStream(xslSource.getBytes()); - InputStreamReader isreaderXSL = new InputStreamReader(baisXSL, aEncoding); - Source xslSrc = new StreamSource(isreaderXSL); - - Transformer transformer = factory.newTransformer(xslSrc); - - // Setup input for XSLT transformation - ByteArrayInputStream baisXML = new ByteArrayInputStream(xmlSource.getBytes()); - InputStreamReader isreaderXML; - - isreaderXML = new InputStreamReader(baisXML, aEncoding); - - Source xmlSrc = new StreamSource(isreaderXML); - - // Resulting SAX events (the generated FO) must be piped through to - // FOP - Result res = new SAXResult(fop.getDefaultHandler()); - - // Start XSLT transformation and FOP processing - transformer.transform(xmlSrc, res); - - // return res.toString(); - } finally { - - // out.close(); - // output.flush(); - // output.close(); + + @POST + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_PLAIN, + MediaType.TEXT_XML }) + public void postReport(XMLDocument reportCol) { + putReport(reportCol); } - } - - /** - * This method parses the query Params of a Request URL and adds params to a given JPQL Query. In - * addition the method replace dynamic date values in the JPQLStatement - * - * - * @param uriInfo - * @return - */ - - /** - * Extracts the query parameters and returns a hashmap with key value pairs - * - * @param aQuery - * @param uriInfo - * @return - */ - private Map getQueryParams(UriInfo uriInfo) { - // test each given QueryParam if it is contained in the EQL Query... - MultivaluedMap mvm = uriInfo.getQueryParameters(); - Map result = new HashMap(); - Set keys = mvm.keySet(); - Iterator iter = keys.iterator(); - while (iter.hasNext()) { - // read key - String sKeyName = iter.next().toString(); - result.put(sKeyName, mvm.getFirst(sKeyName)); + /** + * This method dos a apache FOP transformation using the FopFactory + * + * @param xmlSource + * @param xslSource + * @param aEncoding + * @param outputWriter + */ + public void fopTranformation(String xmlSource, String xslSource, String aEncoding, OutputStream output) + throws Exception { + // configure fopFactory as desired + FopFactory fopFactory = FopFactory.newInstance(); + + FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); + foUserAgent.setBaseURL(fopFactory.getBaseURL()); + + // configure foUserAgent as desired + // OutputStream out =null; + try { + // Construct fop with desired output format + Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, output); + + // Setup XSLT + TransformerFactory factory = TransformerFactory.newInstance(); + ByteArrayInputStream baisXSL = new ByteArrayInputStream(xslSource.getBytes()); + InputStreamReader isreaderXSL = new InputStreamReader(baisXSL, aEncoding); + Source xslSrc = new StreamSource(isreaderXSL); + + Transformer transformer = factory.newTransformer(xslSrc); + + // Setup input for XSLT transformation + ByteArrayInputStream baisXML = new ByteArrayInputStream(xmlSource.getBytes()); + InputStreamReader isreaderXML; + + isreaderXML = new InputStreamReader(baisXML, aEncoding); + + Source xmlSrc = new StreamSource(isreaderXML); + + // Resulting SAX events (the generated FO) must be piped through to + // FOP + Result res = new SAXResult(fop.getDefaultHandler()); + + // Start XSLT transformation and FOP processing + transformer.transform(xmlSrc, res); + + // return res.toString(); + } finally { + + // out.close(); + // output.flush(); + // output.close(); + } + } - return result; - } + /** + * This method parses the query Params of a Request URL and adds params to a + * given JPQL Query. In addition the method replace dynamic date values in the + * JPQLStatement + * + * + * @param uriInfo + * @return + */ + + /** + * Extracts the query parameters and returns a hashmap with key value pairs + * + * @param aQuery + * @param uriInfo + * @return + */ + private Map getQueryParams(UriInfo uriInfo) { + // test each given QueryParam if it is contained in the EQL Query... + MultivaluedMap mvm = uriInfo.getQueryParameters(); + Map result = new HashMap(); + Set keys = mvm.keySet(); + Iterator iter = keys.iterator(); + while (iter.hasNext()) { + // read key + String sKeyName = iter.next().toString(); + result.put(sKeyName, mvm.getFirst(sKeyName)); + } + + return result; + } } diff --git a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/RootRestService.java b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/RootRestService.java index 0062ed2b8..25829d82d 100644 --- a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/RootRestService.java +++ b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/RootRestService.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *

- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.jaxrs; @@ -46,29 +45,27 @@ * */ @Path("/") -@Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, - MediaType.TEXT_XML}) +@Produces({ MediaType.TEXT_HTML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) @Stateless public class RootRestService { + @GET + @Produces(MediaType.APPLICATION_XHTML_XML) + // @Path("/") generates jersey warning + public StreamingOutput getRoot() { - @GET - @Produces(MediaType.APPLICATION_XHTML_XML) - // @Path("/") generates jersey warning - public StreamingOutput getRoot() { - - return new StreamingOutput() { - public void write(OutputStream out) throws IOException, WebApplicationException { + return new StreamingOutput() { + public void write(OutputStream out) throws IOException, WebApplicationException { - out.write("".getBytes()); - } - }; + out.write("".getBytes()); + } + }; - } + } } diff --git a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/WorkflowRestService.java b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/WorkflowRestService.java index 44acd5556..b5aa2ebb7 100644 --- a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/WorkflowRestService.java +++ b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/WorkflowRestService.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *
- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.jaxrs; @@ -75,789 +74,783 @@ import org.imixs.workflow.xml.XMLDocumentAdapter; /** - * The WorkflowService Handler supports methods to process different kind of request URIs + * The WorkflowService Handler supports methods to process different kind of + * request URIs * * @author rsoika * */ @Path("/workflow") -@Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, - MediaType.TEXT_XML}) +@Produces({ MediaType.TEXT_HTML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) @Stateless public class WorkflowRestService { - @Inject - private WorkflowService workflowService; - - @Inject - private DocumentRestService documentRestService; - - @javax.ws.rs.core.Context - private HttpServletRequest servletRequest; - - private static Logger logger = Logger.getLogger(WorkflowRestService.class.getName()); - - @GET - @Produces("text/html") - public StreamingOutput getHelpHTML() { - - return new StreamingOutput() { - public void write(OutputStream out) throws IOException, WebApplicationException { - - out.write("".getBytes()); - out.write("".getBytes()); - out.write("".getBytes()); - - // body - out.write("

Imixs-Workflow REST Service

".getBytes()); - out.write( - "

See the Imixs-Workflow REST API for more information about this Service.

" - .getBytes()); - - // end - out.write("".getBytes()); - } - }; - - } - - /** - * returns a single workitem defined by $uniqueid - * - * @param uniqueid - * @return - */ - @GET - @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") - public Response getWorkItem(@PathParam("uniqueid") String uniqueid, - @QueryParam("items") String items, @QueryParam("format") String format) { - - ItemCollection workitem; - try { - workitem = workflowService.getWorkItem(uniqueid); - if (workitem == null) { - // workitem not found - return Response.status(Response.Status.NOT_FOUND).build(); - } + @Inject + private WorkflowService workflowService; + + @Inject + private DocumentRestService documentRestService; + + @javax.ws.rs.core.Context + private HttpServletRequest servletRequest; + + private static Logger logger = Logger.getLogger(WorkflowRestService.class.getName()); + + @GET + @Produces("text/html") + public StreamingOutput getHelpHTML() { + + return new StreamingOutput() { + public void write(OutputStream out) throws IOException, WebApplicationException { + + out.write("".getBytes()); + out.write("".getBytes()); + out.write("".getBytes()); + + // body + out.write("

Imixs-Workflow REST Service

".getBytes()); + out.write( + "

See the Imixs-Workflow REST API for more information about this Service.

" + .getBytes()); + + // end + out.write("".getBytes()); + } + }; - } catch (Exception e) { - e.printStackTrace(); - workitem = null; } - return documentRestService.convertResult(workitem, items, format); - } - - /** - * Returns a file attachment located in the property $file of the specified workitem - *

- * The file name will be encoded. With a URLDecode the filename is decoded in different formats - * and searched in the file list. This is not a nice solution. - * - * @param uniqueid - * @return - */ - @GET - @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}/file/{file}") - public Response getWorkItemFile(@PathParam("uniqueid") String uniqueid, - @PathParam("file") @Encoded String file, @Context UriInfo uriInfo) { - - ItemCollection workItem; - try { - workItem = workflowService.getWorkItem(uniqueid); - - if (workItem != null) { - - String fileNameUTF8 = URLDecoder.decode(file, "UTF-8"); - String fileNameISO = URLDecoder.decode(file, "ISO-8859-1"); - - // fetch FileData object - FileData fileData = null; - // try to guess encodings..... - fileData = workItem.getFileData(fileNameUTF8); - if (fileData == null) - fileData = workItem.getFileData(fileNameISO); - if (fileData == null) - fileData = workItem.getFileData(file); - - if (fileData != null) { - // Set content type in order of the contentType stored - // in the $file attribute - Response.ResponseBuilder builder = - Response.ok(fileData.getContent(), fileData.getContentType()); - return builder.build(); - } else { - logger.warning("WorklfowRestService unable to open file: '" + file + "' in workitem '" - + uniqueid + "' - error: Filename not found!"); - // workitem not found - return Response.status(Response.Status.NOT_FOUND).build(); + /** + * returns a single workitem defined by $uniqueid + * + * @param uniqueid + * @return + */ + @GET + @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") + public Response getWorkItem(@PathParam("uniqueid") String uniqueid, @QueryParam("items") String items, + @QueryParam("format") String format) { + + ItemCollection workitem; + try { + workitem = workflowService.getWorkItem(uniqueid); + if (workitem == null) { + // workitem not found + return Response.status(Response.Status.NOT_FOUND).build(); + } + + } catch (Exception e) { + e.printStackTrace(); + workitem = null; } - } else { - logger.warning("WorklfowRestService unable to open file: '" + file + "' in workitem '" - + uniqueid + "' - error: Workitem not found!"); - // workitem not found + return documentRestService.convertResult(workitem, items, format); + } + + /** + * Returns a file attachment located in the property $file of the specified + * workitem + *

+ * The file name will be encoded. With a URLDecode the filename is decoded in + * different formats and searched in the file list. This is not a nice solution. + * + * @param uniqueid + * @return + */ + @GET + @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}/file/{file}") + public Response getWorkItemFile(@PathParam("uniqueid") String uniqueid, @PathParam("file") @Encoded String file, + @Context UriInfo uriInfo) { + + ItemCollection workItem; + try { + workItem = workflowService.getWorkItem(uniqueid); + + if (workItem != null) { + + String fileNameUTF8 = URLDecoder.decode(file, "UTF-8"); + String fileNameISO = URLDecoder.decode(file, "ISO-8859-1"); + + // fetch FileData object + FileData fileData = null; + // try to guess encodings..... + fileData = workItem.getFileData(fileNameUTF8); + if (fileData == null) + fileData = workItem.getFileData(fileNameISO); + if (fileData == null) + fileData = workItem.getFileData(file); + + if (fileData != null) { + // Set content type in order of the contentType stored + // in the $file attribute + Response.ResponseBuilder builder = Response.ok(fileData.getContent(), fileData.getContentType()); + return builder.build(); + } else { + logger.warning("WorklfowRestService unable to open file: '" + file + "' in workitem '" + uniqueid + + "' - error: Filename not found!"); + // workitem not found + return Response.status(Response.Status.NOT_FOUND).build(); + } + + } else { + logger.warning("WorklfowRestService unable to open file: '" + file + "' in workitem '" + uniqueid + + "' - error: Workitem not found!"); + // workitem not found + return Response.status(Response.Status.NOT_FOUND).build(); + } + + } catch (Exception e) { + logger.severe("WorklfowRestService unable to open file: '" + file + "' in workitem '" + uniqueid + + "' - error: " + e.getMessage()); + e.printStackTrace(); + } + + logger.severe("WorklfowRestService unable to open file: '" + file + "' in workitem '" + uniqueid + "'"); return Response.status(Response.Status.NOT_FOUND).build(); - } - } catch (Exception e) { - logger.severe("WorklfowRestService unable to open file: '" + file + "' in workitem '" - + uniqueid + "' - error: " + e.getMessage()); - e.printStackTrace(); } - logger.severe( - "WorklfowRestService unable to open file: '" + file + "' in workitem '" + uniqueid + "'"); - return Response.status(Response.Status.NOT_FOUND).build(); - - } - - /** - * Returns a collection of events of a workitem, visible to the current user - * - * @param uniqueid of workitem - * @return list of event entities - */ - @GET - @Path("/workitem/events/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") - public Response getEvents(@PathParam("uniqueid") String uniqueid, - @QueryParam("format") String format) { - List result = null; - try { - result = workflowService.getEvents(this.workflowService.getDocumentService().load(uniqueid)); - } catch (Exception e) { - e.printStackTrace(); + /** + * Returns a collection of events of a workitem, visible to the current user + * + * @param uniqueid of workitem + * @return list of event entities + */ + @GET + @Path("/workitem/events/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") + public Response getEvents(@PathParam("uniqueid") String uniqueid, @QueryParam("format") String format) { + List result = null; + try { + result = workflowService.getEvents(this.workflowService.getDocumentService().load(uniqueid)); + } catch (Exception e) { + e.printStackTrace(); + } + + return documentRestService.convertResultList(result, null, format); + } + + /** + * Returns a collection of workitems representing the worklist by the current + * user + * + * @param start + * @param count + * @param type + * @param sortorder + */ + @GET + @Path("/worklist") + public Response getWorkList(@QueryParam("type") String type, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, + @DefaultValue("10") @QueryParam("pageSize") int pageSize, + @DefaultValue("") @QueryParam("sortBy") String sortBy, + @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, @QueryParam("items") String items, + @QueryParam("format") String format) { + + return getTaskListByOwner(null, type, pageSize, pageIndex, sortBy, sortReverse, items, format); + } + + @GET + @Path("/tasklist/owner/{owner}") + public Response getTaskListByOwner(@PathParam("owner") String owner, @QueryParam("type") String type, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, + @DefaultValue("10") @QueryParam("pageSize") int pageSize, + @DefaultValue("") @QueryParam("sortBy") String sortBy, + @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, @QueryParam("items") String items, + @QueryParam("format") String format) { + List result = null; + try { + if ("null".equalsIgnoreCase(owner)) + owner = null; + + // decode URL param + if (owner != null) + owner = URLDecoder.decode(owner, "UTF-8"); + + result = workflowService.getWorkListByOwner(owner, type, pageSize, pageIndex, sortBy, sortReverse); + } catch (Exception e) { + e.printStackTrace(); + } + + return documentRestService.convertResultList(result, items, format); } - return documentRestService.convertResultList(result, null, format); - } - - /** - * Returns a collection of workitems representing the worklist by the current user - * - * @param start - * @param count - * @param type - * @param sortorder - */ - @GET - @Path("/worklist") - public Response getWorkList(@QueryParam("type") String type, - @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @DefaultValue("10") @QueryParam("pageSize") int pageSize, - @DefaultValue("") @QueryParam("sortBy") String sortBy, - @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, - @QueryParam("items") String items, @QueryParam("format") String format) { - - return getTaskListByOwner(null, type, pageSize, pageIndex, sortBy, sortReverse, items, format); - } - - @GET - @Path("/tasklist/owner/{owner}") - public Response getTaskListByOwner(@PathParam("owner") String owner, - @QueryParam("type") String type, @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @DefaultValue("10") @QueryParam("pageSize") int pageSize, - @DefaultValue("") @QueryParam("sortBy") String sortBy, - @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, - @QueryParam("items") String items, @QueryParam("format") String format) { - List result = null; - try { - if ("null".equalsIgnoreCase(owner)) - owner = null; - - // decode URL param - if (owner != null) - owner = URLDecoder.decode(owner, "UTF-8"); - - result = - workflowService.getWorkListByOwner(owner, type, pageSize, pageIndex, sortBy, sortReverse); - } catch (Exception e) { - e.printStackTrace(); + /** + * Returns a collection of workitems representing the worklist by the current + * user + * + * @param start + * @param count + * @param type + * @param sortorder + */ + @GET + @Path("/tasklist/author/{user}") + public Response getTaskListByAuthor(@PathParam("user") String user, @QueryParam("type") String type, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, + @DefaultValue("10") @QueryParam("pageSize") int pageSize, + @DefaultValue("") @QueryParam("sortBy") String sortBy, + @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, @QueryParam("items") String items, + @QueryParam("format") String format) { + List result = null; + try { + if ("null".equalsIgnoreCase(user)) + user = null; + + // decode URL param + if (user != null) + user = URLDecoder.decode(user, "UTF-8"); + + result = workflowService.getWorkListByAuthor(user, type, pageSize, pageIndex, sortBy, sortReverse); + + } catch (Exception e) { + e.printStackTrace(); + } + return documentRestService.convertResultList(result, items, format); + } + + @GET + @Path("/tasklist/creator/{creator}") + public Response getTaskListByCreator(@PathParam("creator") String creator, @QueryParam("type") String type, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, + @DefaultValue("10") @QueryParam("pageSize") int pageSize, + @DefaultValue("") @QueryParam("sortBy") String sortBy, + @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, @QueryParam("items") String items, + @QueryParam("format") String format) { + List result = null; + try { + if ("null".equalsIgnoreCase(creator)) + creator = null; + + // decode URL param + if (creator != null) + creator = URLDecoder.decode(creator, "UTF-8"); + + result = workflowService.getWorkListByCreator(creator, type, pageSize, pageIndex, sortBy, sortReverse); + + } catch (Exception e) { + e.printStackTrace(); + } + + return documentRestService.convertResultList(result, items, format); } - return documentRestService.convertResultList(result, items, format); - } - - /** - * Returns a collection of workitems representing the worklist by the current user - * - * @param start - * @param count - * @param type - * @param sortorder - */ - @GET - @Path("/tasklist/author/{user}") - public Response getTaskListByAuthor(@PathParam("user") String user, - @QueryParam("type") String type, @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @DefaultValue("10") @QueryParam("pageSize") int pageSize, - @DefaultValue("") @QueryParam("sortBy") String sortBy, - @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, - @QueryParam("items") String items, @QueryParam("format") String format) { - List result = null; - try { - if ("null".equalsIgnoreCase(user)) - user = null; - - // decode URL param - if (user != null) - user = URLDecoder.decode(user, "UTF-8"); - - result = - workflowService.getWorkListByAuthor(user, type, pageSize, pageIndex, sortBy, sortReverse); - - } catch (Exception e) { - e.printStackTrace(); + @GET + @Path("/tasklist/processid/{processid}") + public Response getTaskListByProcessID(@PathParam("processid") int processid, @QueryParam("type") String type, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, + @DefaultValue("10") @QueryParam("pageSize") int pageSize, + @DefaultValue("") @QueryParam("sortBy") String sortBy, + @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, @QueryParam("items") String items, + @QueryParam("format") String format) { + List result = null; + try { + result = workflowService.getWorkListByProcessID(processid, type, pageSize, pageIndex, sortBy, sortReverse); + } catch (Exception e) { + e.printStackTrace(); + } + return documentRestService.convertResultList(result, items, format); } - return documentRestService.convertResultList(result, items, format); - } - - @GET - @Path("/tasklist/creator/{creator}") - public Response getTaskListByCreator(@PathParam("creator") String creator, - @QueryParam("type") String type, @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @DefaultValue("10") @QueryParam("pageSize") int pageSize, - @DefaultValue("") @QueryParam("sortBy") String sortBy, - @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, - @QueryParam("items") String items, @QueryParam("format") String format) { - List result = null; - try { - if ("null".equalsIgnoreCase(creator)) - creator = null; - - // decode URL param - if (creator != null) - creator = URLDecoder.decode(creator, "UTF-8"); - - result = workflowService.getWorkListByCreator(creator, type, pageSize, pageIndex, sortBy, - sortReverse); - - } catch (Exception e) { - e.printStackTrace(); + + @GET + @Path("/tasklist/group/{processgroup}") + public Response getTaskListByGroup(@PathParam("processgroup") String processgroup, @QueryParam("type") String type, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, + @DefaultValue("10") @QueryParam("pageSize") int pageSize, + @DefaultValue("") @QueryParam("sortBy") String sortBy, + @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, @QueryParam("items") String items, + @QueryParam("format") String format) { + List result = null; + try { + // decode URL param + if (processgroup != null) + processgroup = URLDecoder.decode(processgroup, "UTF-8"); + result = workflowService.getWorkListByGroup(processgroup, type, pageSize, pageIndex, sortBy, sortReverse); + } catch (Exception e) { + e.printStackTrace(); + } + + return documentRestService.convertResultList(result, items, format); } - return documentRestService.convertResultList(result, items, format); - } - - @GET - @Path("/tasklist/processid/{processid}") - public Response getTaskListByProcessID(@PathParam("processid") int processid, - @QueryParam("type") String type, @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @DefaultValue("10") @QueryParam("pageSize") int pageSize, - @DefaultValue("") @QueryParam("sortBy") String sortBy, - @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, - @QueryParam("items") String items, @QueryParam("format") String format) { - List result = null; - try { - result = workflowService.getWorkListByProcessID(processid, type, pageSize, pageIndex, sortBy, - sortReverse); - } catch (Exception e) { - e.printStackTrace(); + @GET + @Path("/tasklist/ref/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") + public Response getTaskListByRef(@PathParam("uniqueid") String uniqueid, @QueryParam("type") String type, + @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, + @DefaultValue("10") @QueryParam("pageSize") int pageSize, + @DefaultValue("") @QueryParam("sortBy") String sortBy, + @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, @QueryParam("items") String items, + @QueryParam("format") String format) { + List result = null; + try { + result = workflowService.getWorkListByRef(uniqueid, type, pageSize, pageIndex, sortBy, sortReverse); + } catch (Exception e) { + e.printStackTrace(); + } + + return documentRestService.convertResultList(result, items, format); } - return documentRestService.convertResultList(result, items, format); - } - - @GET - @Path("/tasklist/group/{processgroup}") - public Response getTaskListByGroup(@PathParam("processgroup") String processgroup, - @QueryParam("type") String type, @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @DefaultValue("10") @QueryParam("pageSize") int pageSize, - @DefaultValue("") @QueryParam("sortBy") String sortBy, - @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, - @QueryParam("items") String items, @QueryParam("format") String format) { - List result = null; - try { - // decode URL param - if (processgroup != null) - processgroup = URLDecoder.decode(processgroup, "UTF-8"); - result = workflowService.getWorkListByGroup(processgroup, type, pageSize, pageIndex, sortBy, - sortReverse); - } catch (Exception e) { - e.printStackTrace(); + + /** + * This method expects a form post and processes the WorkItem by the + * WorkflowService EJB. After the workItem was processed the method redirect the + * request to the provided action URI. The action URI can also be computed by + * the Imixs Workflow ResutlPlugin + * + * @param requestBodyStream - form content + * @param action - return URI + * @return + */ + @POST + @Path("/workitem") + @Consumes({ MediaType.APPLICATION_FORM_URLENCODED }) + public Response postFormWorkitem(InputStream requestBodyStream, @QueryParam("items") String items) { + logger.fine("postFormWorkitem @POST /workitem method:postWorkitem...."); + // parse the workItem. + ItemCollection workitem = parseWorkitem(requestBodyStream); + return processWorkitem(workitem, null, items); } - return documentRestService.convertResultList(result, items, format); - } - - @GET - @Path("/tasklist/ref/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") - public Response getTaskListByRef(@PathParam("uniqueid") String uniqueid, - @QueryParam("type") String type, @DefaultValue("0") @QueryParam("pageIndex") int pageIndex, - @DefaultValue("10") @QueryParam("pageSize") int pageSize, - @DefaultValue("") @QueryParam("sortBy") String sortBy, - @DefaultValue("false") @QueryParam("sortReverse") Boolean sortReverse, - @QueryParam("items") String items, @QueryParam("format") String format) { - List result = null; - try { - result = workflowService.getWorkListByRef(uniqueid, type, pageSize, pageIndex, sortBy, - sortReverse); - } catch (Exception e) { - e.printStackTrace(); + /** + * This method expects a form post and processes the WorkItem by the + * WorkflowService EJB. After the workItem was processed the method redirect the + * request to the provided action URI. The action URI can also be computed by + * the Imixs Workflow ResutlPlugin + * + * @param requestBodyStream - form content + * @param items - optional item list to be returned in the result + * @return + */ + @POST + @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") + @Consumes({ MediaType.APPLICATION_FORM_URLENCODED }) + public Response postFormWorkitemByUnqiueID(@PathParam("uniqueid") String uid, InputStream requestBodyStream, + @QueryParam("items") String items) { + logger.finest("......postFormWorkitem @POST /workitem method:postWorkitem...."); + // parse the workItem. + ItemCollection workitem = parseWorkitem(requestBodyStream); + return processWorkitem(workitem, uid, items); } - return documentRestService.convertResultList(result, items, format); - } - - /** - * This method expects a form post and processes the WorkItem by the WorkflowService EJB. After - * the workItem was processed the method redirect the request to the provided action URI. The - * action URI can also be computed by the Imixs Workflow ResutlPlugin - * - * @param requestBodyStream - form content - * @param action - return URI - * @return - */ - @POST - @Path("/workitem") - @Consumes({MediaType.APPLICATION_FORM_URLENCODED}) - public Response postFormWorkitem(InputStream requestBodyStream, - @QueryParam("items") String items) { - logger.fine("postFormWorkitem @POST /workitem method:postWorkitem...."); - // parse the workItem. - ItemCollection workitem = parseWorkitem(requestBodyStream); - return processWorkitem(workitem, null, items); - } - - /** - * This method expects a form post and processes the WorkItem by the WorkflowService EJB. After - * the workItem was processed the method redirect the request to the provided action URI. The - * action URI can also be computed by the Imixs Workflow ResutlPlugin - * - * @param requestBodyStream - form content - * @param items - optional item list to be returned in the result - * @return - */ - @POST - @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") - @Consumes({MediaType.APPLICATION_FORM_URLENCODED}) - public Response postFormWorkitemByUnqiueID(@PathParam("uniqueid") String uid, - InputStream requestBodyStream, @QueryParam("items") String items) { - logger.finest("......postFormWorkitem @POST /workitem method:postWorkitem...."); - // parse the workItem. - ItemCollection workitem = parseWorkitem(requestBodyStream); - return processWorkitem(workitem, uid, items); - } - - /** - * This method expects a form post. - * - * @see putWorkitemDefault - * @param requestBodyStream - * @param items - optional item list to be returned in the result - * @return - */ - @PUT - @Path("/workitem") - @Consumes({MediaType.APPLICATION_FORM_URLENCODED}) - public Response putFormWorkitem(InputStream requestBodyStream, - @QueryParam("items") String items) { - logger.fine("putFormWorkitem @POST /workitem delegate to POST...."); - return postFormWorkitem(requestBodyStream, items); - } - - /** - * This method post a ItemCollection object to be processed by the WorkflowManager. The method - * test for the properties $taskidid and $eventid - * - * NOTE!! - this method did not update an existing instance of a workItem. The behavior is - * different to the method putWorkitem(). It need to be discussed if the behavior is wrong or not. - * - * @param workitem - new workItem data - * @param items - optional item list to be returned in the result - */ - @POST - @Path("/workitem") - @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON}) - public Response postWorkitem(XMLDocument xmlworkitem, @QueryParam("items") String items) { - logger.fine("postWorkitem @POST /workitem method:postWorkitem...."); - ItemCollection workitem = XMLDocumentAdapter.putDocument(xmlworkitem); - return processWorkitem(workitem, null, items); - } - - /** - * Delegater - * - * @param workitem - * @param items - optional item list to be returned in the result - * @return - */ - @PUT - @Path("/workitem") - @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON}) - public Response putWorkitem(XMLDocument workitem, @QueryParam("items") String items) { - logger.fine("putWorkitem @PUT /workitem delegate to POST...."); - return postWorkitem(workitem, items); - } - - @POST - @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") - @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON}) - public Response postWorkitemByUniqueID(@PathParam("uniqueid") String uniqueid, - XMLDocument xmlworkitem, @QueryParam("items") String items) { - logger.fine( - "postWorkitemByUniqueID @POST /workitem/" + uniqueid + " method:postWorkitemXML...."); - ItemCollection workitem; - workitem = XMLDocumentAdapter.putDocument(xmlworkitem); - return processWorkitem(workitem, uniqueid, items); - } - - /** - * Delegater for PUT postXMLWorkitemByUniqueID - * - * @param workitem - * @param items - optional item list to be returned in the result - * @return - */ - @PUT - @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") - @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON}) - public Response putWorkitemByUniqueID(@PathParam("uniqueid") String uniqueid, - XMLDocument xmlworkitem, @QueryParam("items") String items) { - logger.fine("putWorkitem @PUT /workitem/{uniqueid} delegate to POST...."); - return postWorkitemByUniqueID(uniqueid, xmlworkitem, items); - } - - /** - * This method post a collection of ItemCollection objects to be processed by the WorkflowManager. - * - * @param worklist - workitem list data - * @param items - optional item list to be returned in the result - */ - @POST - @Path("/workitems") - @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON}) - public Response postWorkitems(XMLDataCollection worklist) { - - logger.fine("postWorkitems @POST /workitems method:postWorkitems...."); - - XMLDocument entity; - ItemCollection itemCollection; - try { - // save new entities into database and update modelversion..... - for (int i = 0; i < worklist.getDocument().length; i++) { - entity = worklist.getDocument()[i]; - itemCollection = XMLDocumentAdapter.putDocument(entity); - // process entity - workflowService.processWorkItem(itemCollection); - } - return Response.status(Response.Status.OK).build(); - } catch (Exception e) { - e.printStackTrace(); + /** + * This method expects a form post. + * + * @see putWorkitemDefault + * @param requestBodyStream + * @param items - optional item list to be returned in the result + * @return + */ + @PUT + @Path("/workitem") + @Consumes({ MediaType.APPLICATION_FORM_URLENCODED }) + public Response putFormWorkitem(InputStream requestBodyStream, @QueryParam("items") String items) { + logger.fine("putFormWorkitem @POST /workitem delegate to POST...."); + return postFormWorkitem(requestBodyStream, items); } - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); - } - - @PUT - @Path("/workitems") - @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON}) - public Response putWorkitems(XMLDataCollection worklist) { - logger.fine("pupWorkitems @PUT /workitems delegate to @POST...."); - return postWorkitems(worklist); - } - - /** - * This method expects JSON in BADGARFISH notation to processed by the WorkflowService EJB. - *

- * The Method returns a workitem with the new data. If a processException Occurs the method - * returns an object with the error code - *

- * The JSON is parsed manually by teh imixs json parser. The expreced notation is: - *

- * ... value":{"@type":"xs:int","$":"10"} - * - * - * @param requestBodyStream - * @param items - optional item list to be returned in the result - * @return JSON object - * @throws Exception - */ - @POST - @Path("/workitem/typed") - @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) - @Consumes(MediaType.APPLICATION_JSON) - public Response postTypedWorkitemJSON(InputStream requestBodyStream, - @QueryParam("error") String error, @QueryParam("items") String items) { - - logger.fine("postTypedWorkitemJSON @POST workitem...."); - ItemCollection workitem = null; - try { - List result = ImixsJSONParser.parse(requestBodyStream); - if (result != null && result.size() > 0) { - workitem = result.get(0); - } - // workitem = JSONParser.parseWorkitem(requestBodyStream, encoding); - } catch (ParseException e) { - logger.severe("postJSONWorkitem wrong json format!"); - e.printStackTrace(); - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); - } catch (UnsupportedEncodingException e) { - logger.severe("postJSONWorkitem wrong json format!"); - e.printStackTrace(); - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + + /** + * This method post a ItemCollection object to be processed by the + * WorkflowManager. The method test for the properties $taskidid and $eventid + * + * NOTE!! - this method did not update an existing instance of a workItem. The + * behavior is different to the method putWorkitem(). It need to be discussed if + * the behavior is wrong or not. + * + * @param workitem - new workItem data + * @param items - optional item list to be returned in the result + */ + @POST + @Path("/workitem") + @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON }) + public Response postWorkitem(XMLDocument xmlworkitem, @QueryParam("items") String items) { + logger.fine("postWorkitem @POST /workitem method:postWorkitem...."); + ItemCollection workitem = XMLDocumentAdapter.putDocument(xmlworkitem); + return processWorkitem(workitem, null, items); } - if (workitem == null) { - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + + /** + * Delegater + * + * @param workitem + * @param items - optional item list to be returned in the result + * @return + */ + @PUT + @Path("/workitem") + @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON }) + public Response putWorkitem(XMLDocument workitem, @QueryParam("items") String items) { + logger.fine("putWorkitem @PUT /workitem delegate to POST...."); + return postWorkitem(workitem, items); } - return processWorkitem(workitem, null, items); - } - - /** - * Delegater for PUT postJSONTypedWorkitem - * - * @param workitem - * @param items - optional item list to be returned in the result - * @return - */ - @PUT - @Path("/workitem/typed") - @Consumes(MediaType.APPLICATION_JSON) - public Response putTypedWorkitemJSON(InputStream requestBodyStream, - @QueryParam("error") String error, @QueryParam("items") String items) { - - logger.fine("putTypedWorkitemJSON @PUT /workitem/{uniqueid} delegate to POST...."); - return postTypedWorkitemJSON(requestBodyStream, error, items); - } - - @POST - @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}/typed") - @Consumes({MediaType.APPLICATION_JSON}) - public Response postTypedWorkitemJSONByUniqueID(@PathParam("uniqueid") String uniqueid, - InputStream requestBodyStream, @QueryParam("error") String error, - @QueryParam("items") String items) { - logger.fine("postJSONWorkitemByUniqueID @POST /workitem/" + uniqueid + "...."); - - ItemCollection workitem = null; - try { - List result = ImixsJSONParser.parse(requestBodyStream); - if (result != null && result.size() > 0) { - workitem = result.get(0); - } - // workitem = JSONParser.parseWorkitem(requestBodyStream, encoding); - } catch (ParseException e) { - logger.severe("postJSONWorkitemByUniqueID wrong json format!"); - e.printStackTrace(); - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); - } catch (UnsupportedEncodingException e) { - logger.severe("postJSONWorkitemByUniqueID wrong json format!"); - e.printStackTrace(); - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + @POST + @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") + @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON }) + public Response postWorkitemByUniqueID(@PathParam("uniqueid") String uniqueid, XMLDocument xmlworkitem, + @QueryParam("items") String items) { + logger.fine("postWorkitemByUniqueID @POST /workitem/" + uniqueid + " method:postWorkitemXML...."); + ItemCollection workitem; + workitem = XMLDocumentAdapter.putDocument(xmlworkitem); + return processWorkitem(workitem, uniqueid, items); } - return processWorkitem(workitem, uniqueid, items); - } - - /** - * Delegater for PUT postJSONWorkitemByUniqueID - * - * @param workitem - * @param items - optional item list to be returned in the result - * @return - */ - @PUT - @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}/typed") - @Consumes({MediaType.APPLICATION_JSON}) - public Response putTypedWorkitemJSONByUniqueID(@PathParam("uniqueid") String uniqueid, - InputStream requestBodyStream, @QueryParam("error") String error, - @QueryParam("items") String items) { - - logger.fine("postJSONWorkitemByUniqueID @PUT /workitem/{uniqueid} delegate to POST...."); - return postTypedWorkitemJSONByUniqueID(uniqueid, requestBodyStream, error, items); - } - - /** - * This method expects a form post. The method parses the input stream to extract the provides - * field/value pairs. NOTE: The method did not(!) assume that the put/post request contains a - * complete workItem. For this reason the method loads the existing instance of the corresponding - * workItem (identified by the $uniqueid) and adds the values provided by the put/post request - * into the existing instance. - * - * The following kind of lines which can be included in the InputStream will be skipped - * - * - * ------------------------------1a26f3661ff7 - Content-Disposition: form-data; name="query" - Connection: keep-alive - Content-Type: multipart/form-data; boundary=---------------------------195571638125373 - Content-Length: 5680 - - -----------------------------195571638125373 - * - * - * @param requestBodyStream - * @return a workitem - */ - @SuppressWarnings({"unchecked", "rawtypes"}) - public ItemCollection parseWorkitem(InputStream requestBodyStream) { - Vector vMultiValueFieldNames = new Vector(); - BufferedReader in = new BufferedReader(new InputStreamReader(requestBodyStream)); - String inputLine; - ItemCollection workitem = new ItemCollection(); - - logger.fine("[WorkflowRestService] parseWorkitem...."); - - try { - while ((inputLine = in.readLine()) != null) { - // System.out.println(inputLine); - - // split params separated by & - StringTokenizer st = new StringTokenizer(inputLine, "&", false); - while (st.hasMoreTokens()) { - String fieldValue = st.nextToken(); - logger.finest("[WorkflowRestService] parse line:" + fieldValue + ""); - try { - fieldValue = URLDecoder.decode(fieldValue, "UTF-8"); - - if (!fieldValue.contains("=")) { - logger.finest("[WorkflowRestService] line will be skipped"); - continue; - } - // get fieldname - String fieldName = fieldValue.substring(0, fieldValue.indexOf('=')); + /** + * Delegater for PUT postXMLWorkitemByUniqueID + * + * @param workitem + * @param items - optional item list to be returned in the result + * @return + */ + @PUT + @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") + @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON }) + public Response putWorkitemByUniqueID(@PathParam("uniqueid") String uniqueid, XMLDocument xmlworkitem, + @QueryParam("items") String items) { + logger.fine("putWorkitem @PUT /workitem/{uniqueid} delegate to POST...."); + return postWorkitemByUniqueID(uniqueid, xmlworkitem, items); + } - // if fieldName contains blank or : or --- we skipp the - // line - if (fieldName.contains(":") || fieldName.contains(" ") || fieldName.contains(";")) { - logger.finest("[WorkflowRestService] line will be skipped"); - continue; + /** + * This method post a collection of ItemCollection objects to be processed by + * the WorkflowManager. + * + * @param worklist - workitem list data + * @param items - optional item list to be returned in the result + */ + @POST + @Path("/workitems") + @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON }) + public Response postWorkitems(XMLDataCollection worklist) { + + logger.fine("postWorkitems @POST /workitems method:postWorkitems...."); + + XMLDocument entity; + ItemCollection itemCollection; + try { + // save new entities into database and update modelversion..... + for (int i = 0; i < worklist.getDocument().length; i++) { + entity = worklist.getDocument()[i]; + itemCollection = XMLDocumentAdapter.putDocument(entity); + // process entity + workflowService.processWorkItem(itemCollection); } + return Response.status(Response.Status.OK).build(); + } catch (Exception e) { + e.printStackTrace(); + } + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } - // test for value... - if (fieldValue.indexOf('=') == fieldValue.length()) { - // no value - workitem.replaceItemValue(fieldName, ""); - logger.fine("[WorkflowRestService] no value for '" + fieldName + "'"); - } else { - fieldValue = fieldValue.substring(fieldValue.indexOf('=') + 1); - // test for a multiValue field - did we know - // this - // field....? - fieldName = fieldName.toLowerCase(); - if (vMultiValueFieldNames.indexOf(fieldName) > -1) { - - List v = workitem.getItemValue(fieldName); - v.add(fieldValue); - logger.fine("[WorkflowRestService] multivalue for '" + fieldName + "' = '" - + fieldValue + "'"); - workitem.replaceItemValue(fieldName, v); - } else { - // first single value.... - logger.fine( - "[WorkflowRestService] value for '" + fieldName + "' = '" + fieldValue + "'"); - workitem.replaceItemValue(fieldName, fieldValue); - vMultiValueFieldNames.add(fieldName); - } - } + @PUT + @Path("/workitems") + @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON }) + public Response putWorkitems(XMLDataCollection worklist) { + logger.fine("pupWorkitems @PUT /workitems delegate to @POST...."); + return postWorkitems(worklist); + } - } catch (NumberFormatException e) { + /** + * This method expects JSON in BADGARFISH notation to processed by the + * WorkflowService EJB. + *

+ * The Method returns a workitem with the new data. If a processException Occurs + * the method returns an object with the error code + *

+ * The JSON is parsed manually by teh imixs json parser. The expreced notation + * is: + *

+ * ... value":{"@type":"xs:int","$":"10"} + * + * + * @param requestBodyStream + * @param items - optional item list to be returned in the result + * @return JSON object + * @throws Exception + */ + @POST + @Path("/workitem/typed") + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML }) + @Consumes(MediaType.APPLICATION_JSON) + public Response postTypedWorkitemJSON(InputStream requestBodyStream, @QueryParam("error") String error, + @QueryParam("items") String items) { + + logger.fine("postTypedWorkitemJSON @POST workitem...."); + ItemCollection workitem = null; + try { + List result = ImixsJSONParser.parse(requestBodyStream); + if (result != null && result.size() > 0) { + workitem = result.get(0); + } + // workitem = JSONParser.parseWorkitem(requestBodyStream, encoding); + } catch (ParseException e) { + logger.severe("postJSONWorkitem wrong json format!"); e.printStackTrace(); - } catch (Exception e) { + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } catch (UnsupportedEncodingException e) { + logger.severe("postJSONWorkitem wrong json format!"); e.printStackTrace(); - } + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } + if (workitem == null) { + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); } - } - } catch (IOException e1) { - logger.severe("[WorkflowRestService] Unable to parse workitem data!"); - e1.printStackTrace(); - return null; - } finally { - try { - in.close(); - } catch (IOException e) { - e.printStackTrace(); - } - + return processWorkitem(workitem, null, items); } - return workitem; - } - - /** - * This helper method processes a workitem. The response code of the response object is set to 200 - * if case the processing was successful. In case of an Exception a error message is generated and - * the status NOT_ACCEPTABLE is returned. - *

- * The param 'uid' is optional and will be validated against the workitem data - *

- * This method is called by the POST/PUT methods. - * - * @param workitem - * @param uid - optional $uniqueid, will be validated. - * @param items - optional list of items to be returned - * @return - */ - private Response processWorkitem(ItemCollection workitem, String uid, String items) { - - // test for null values - if (workitem == null) { - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + /** + * Delegater for PUT postJSONTypedWorkitem + * + * @param workitem + * @param items - optional item list to be returned in the result + * @return + */ + @PUT + @Path("/workitem/typed") + @Consumes(MediaType.APPLICATION_JSON) + public Response putTypedWorkitemJSON(InputStream requestBodyStream, @QueryParam("error") String error, + @QueryParam("items") String items) { + + logger.fine("putTypedWorkitemJSON @PUT /workitem/{uniqueid} delegate to POST...."); + return postTypedWorkitemJSON(requestBodyStream, error, items); } - // validate optional uniqueId - if (uid != null && !uid.isEmpty() && !workitem.getUniqueID().isEmpty() - && !uid.equals(workitem.getUniqueID())) { - logger.severe("@POST/@PUT workitem/" + uid - + " : $UNIQUEID did not match, remove $uniqueid to create a new instnace!"); - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + @POST + @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}/typed") + @Consumes({ MediaType.APPLICATION_JSON }) + public Response postTypedWorkitemJSONByUniqueID(@PathParam("uniqueid") String uniqueid, + InputStream requestBodyStream, @QueryParam("error") String error, @QueryParam("items") String items) { + logger.fine("postJSONWorkitemByUniqueID @POST /workitem/" + uniqueid + "...."); + + ItemCollection workitem = null; + try { + List result = ImixsJSONParser.parse(requestBodyStream); + if (result != null && result.size() > 0) { + workitem = result.get(0); + } + // workitem = JSONParser.parseWorkitem(requestBodyStream, encoding); + } catch (ParseException e) { + logger.severe("postJSONWorkitemByUniqueID wrong json format!"); + e.printStackTrace(); + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } catch (UnsupportedEncodingException e) { + logger.severe("postJSONWorkitemByUniqueID wrong json format!"); + e.printStackTrace(); + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } + return processWorkitem(workitem, uniqueid, items); } - if (uid != null && !uid.isEmpty()) { - // set provided uniqueid - workitem.replaceItemValue(WorkflowKernel.UNIQUEID, uid); + /** + * Delegater for PUT postJSONWorkitemByUniqueID + * + * @param workitem + * @param items - optional item list to be returned in the result + * @return + */ + @PUT + @Path("/workitem/{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}/typed") + @Consumes({ MediaType.APPLICATION_JSON }) + public Response putTypedWorkitemJSONByUniqueID(@PathParam("uniqueid") String uniqueid, + InputStream requestBodyStream, @QueryParam("error") String error, @QueryParam("items") String items) { + + logger.fine("postJSONWorkitemByUniqueID @PUT /workitem/{uniqueid} delegate to POST...."); + return postTypedWorkitemJSONByUniqueID(uniqueid, requestBodyStream, error, items); } - try { - // remove old error code and message - workitem.removeItem("$error_code"); - workitem.removeItem("$error_message"); - // now lets try to process the workitem... - workitem = workflowService.processWorkItem(workitem); - - } catch (AccessDeniedException e) { - workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); - } catch (PluginException e) { - workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); - } catch (RuntimeException e) { - workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); - } catch (ModelException e) { - workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); - } + /** + * This method expects a form post. The method parses the input stream to + * extract the provides field/value pairs. NOTE: The method did not(!) assume + * that the put/post request contains a complete workItem. For this reason the + * method loads the existing instance of the corresponding workItem (identified + * by the $uniqueid) and adds the values provided by the put/post request into + * the existing instance. + * + * The following kind of lines which can be included in the InputStream will be + * skipped + * + * + * ------------------------------1a26f3661ff7 + Content-Disposition: form-data; name="query" + Connection: keep-alive + Content-Type: multipart/form-data; boundary=---------------------------195571638125373 + Content-Length: 5680 + + -----------------------------195571638125373 + * + * + * @param requestBodyStream + * @return a workitem + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public ItemCollection parseWorkitem(InputStream requestBodyStream) { + Vector vMultiValueFieldNames = new Vector(); + BufferedReader in = new BufferedReader(new InputStreamReader(requestBodyStream)); + String inputLine; + ItemCollection workitem = new ItemCollection(); + + logger.fine("[WorkflowRestService] parseWorkitem...."); + + try { + while ((inputLine = in.readLine()) != null) { + // System.out.println(inputLine); + + // split params separated by & + StringTokenizer st = new StringTokenizer(inputLine, "&", false); + while (st.hasMoreTokens()) { + String fieldValue = st.nextToken(); + logger.finest("[WorkflowRestService] parse line:" + fieldValue + ""); + try { + fieldValue = URLDecoder.decode(fieldValue, "UTF-8"); + + if (!fieldValue.contains("=")) { + logger.finest("[WorkflowRestService] line will be skipped"); + continue; + } + + // get fieldname + String fieldName = fieldValue.substring(0, fieldValue.indexOf('=')); + + // if fieldName contains blank or : or --- we skipp the + // line + if (fieldName.contains(":") || fieldName.contains(" ") || fieldName.contains(";")) { + logger.finest("[WorkflowRestService] line will be skipped"); + continue; + } + + // test for value... + if (fieldValue.indexOf('=') == fieldValue.length()) { + // no value + workitem.replaceItemValue(fieldName, ""); + logger.fine("[WorkflowRestService] no value for '" + fieldName + "'"); + } else { + fieldValue = fieldValue.substring(fieldValue.indexOf('=') + 1); + // test for a multiValue field - did we know + // this + // field....? + fieldName = fieldName.toLowerCase(); + if (vMultiValueFieldNames.indexOf(fieldName) > -1) { + + List v = workitem.getItemValue(fieldName); + v.add(fieldValue); + logger.fine("[WorkflowRestService] multivalue for '" + fieldName + "' = '" + fieldValue + + "'"); + workitem.replaceItemValue(fieldName, v); + } else { + // first single value.... + logger.fine( + "[WorkflowRestService] value for '" + fieldName + "' = '" + fieldValue + "'"); + workitem.replaceItemValue(fieldName, fieldValue); + vMultiValueFieldNames.add(fieldName); + } + } + + } catch (NumberFormatException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + } - // return workitem - try { - if (workitem.hasItem("$error_code")) { - logger.severe(workitem.getItemValueString("$error_code") + ": " - + workitem.getItemValueString("$error_message")); - return Response.ok(XMLDataCollectionAdapter.getDataCollection(workitem)) - .status(Response.Status.NOT_ACCEPTABLE).build(); - } else { - return Response.ok(XMLDataCollectionAdapter.getDataCollection(workitem, - DocumentRestService.getItemList(items))).build(); - } - } catch (Exception e) { - e.printStackTrace(); - return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } + } catch (IOException e1) { + logger.severe("[WorkflowRestService] Unable to parse workitem data!"); + e1.printStackTrace(); + return null; + } finally { + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + return workitem; } - } + /** + * This helper method processes a workitem. The response code of the response + * object is set to 200 if case the processing was successful. In case of an + * Exception a error message is generated and the status NOT_ACCEPTABLE is + * returned. + *

+ * The param 'uid' is optional and will be validated against the workitem data + *

+ * This method is called by the POST/PUT methods. + * + * @param workitem + * @param uid - optional $uniqueid, will be validated. + * @param items - optional list of items to be returned + * @return + */ + private Response processWorkitem(ItemCollection workitem, String uid, String items) { + + // test for null values + if (workitem == null) { + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } + + // validate optional uniqueId + if (uid != null && !uid.isEmpty() && !workitem.getUniqueID().isEmpty() && !uid.equals(workitem.getUniqueID())) { + logger.severe("@POST/@PUT workitem/" + uid + + " : $UNIQUEID did not match, remove $uniqueid to create a new instnace!"); + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } + + if (uid != null && !uid.isEmpty()) { + // set provided uniqueid + workitem.replaceItemValue(WorkflowKernel.UNIQUEID, uid); + } + try { + // remove old error code and message + workitem.removeItem("$error_code"); + workitem.removeItem("$error_message"); + // now lets try to process the workitem... + workitem = workflowService.processWorkItem(workitem); + + } catch (AccessDeniedException e) { + workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); + } catch (PluginException e) { + workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); + } catch (RuntimeException e) { + workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); + } catch (ModelException e) { + workitem = ImixsExceptionHandler.addErrorMessage(e, workitem); + } + // return workitem + try { + if (workitem.hasItem("$error_code")) { + logger.severe(workitem.getItemValueString("$error_code") + ": " + + workitem.getItemValueString("$error_message")); + return Response.ok(XMLDataCollectionAdapter.getDataCollection(workitem)) + .status(Response.Status.NOT_ACCEPTABLE).build(); + } else { + return Response.ok( + XMLDataCollectionAdapter.getDataCollection(workitem, DocumentRestService.getItemList(items))) + .build(); + } + } catch (Exception e) { + e.printStackTrace(); + return Response.status(Response.Status.NOT_ACCEPTABLE).build(); + } + + } } diff --git a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/XMLItemCollectionWriter.java b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/XMLItemCollectionWriter.java index e40b88c23..a7be61783 100644 --- a/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/XMLItemCollectionWriter.java +++ b/imixs-workflow-jax-rs/src/main/java/org/imixs/workflow/jaxrs/XMLItemCollectionWriter.java @@ -1,6 +1,6 @@ -/******************************************************************************* - *

- *  Imixs Workflow 
+/*  
+ *  Imixs-Workflow 
+ *  
  *  Copyright (C) 2001-2020 Imixs Software Solutions GmbH,  
  *  http://www.imixs.com
  *  
@@ -22,10 +22,9 @@
  *      https://github.com/imixs/imixs-workflow
  *  
  *  Contributors:  
- *      Imixs Software Solutions GmbH - initial API and implementation
+ *      Imixs Software Solutions GmbH - Project Management
  *      Ralph Soika - Software Developer
- * 
- *******************************************************************************/ + */ package org.imixs.workflow.jaxrs; @@ -63,163 +62,157 @@ @Produces(MediaType.TEXT_HTML) public class XMLItemCollectionWriter implements MessageBodyWriter { - public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, - MediaType mediaType) { - return XMLDocument.class.isAssignableFrom(type); - } + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return XMLDocument.class.isAssignableFrom(type); + } + + public void writeTo(XMLDocument xmlItemCollection, Class type, Type genericType, Annotation[] annotations, + MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) + throws IOException, WebApplicationException { + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(entityStream)); + + bw.write(""); + printHead(bw, mediaType.toString(), null); + bw.write(""); + try { + bw.write("

Entity

"); - public void writeTo(XMLDocument xmlItemCollection, Class type, Type genericType, - Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, - OutputStream entityStream) throws IOException, WebApplicationException { - BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(entityStream)); + printXMLItemCollectionHTML(bw, xmlItemCollection); - bw.write(""); - printHead(bw, mediaType.toString(), null); - bw.write(""); - try { - bw.write("

Entity

"); + } catch (Exception e) { + bw.write("ERROR
"); + // e.printStackTrace(bw.); + } - printXMLItemCollectionHTML(bw, xmlItemCollection); + bw.write(""); + bw.write(""); - } catch (Exception e) { - bw.write("ERROR
"); - // e.printStackTrace(bw.); + bw.flush(); } - bw.write(""); - bw.write(""); - - bw.flush(); - } - - public long getSize(XMLDocument arg0, Class arg1, Type arg2, Annotation[] arg3, - MediaType arg4) { - return -1; - } - - /** - * This Method prints a single XMLItemCollection in html format. The items are sorted by name - * - * @param out - * @param workItem - * @throws IOException - */ - @SuppressWarnings("rawtypes") - public static void printXMLItemCollectionHTML(BufferedWriter bw, XMLDocument xmlworkItem) - throws IOException { - boolean trClass = false; - - ItemCollection workItem = XMLDocumentAdapter.putDocument(xmlworkItem); - bw.write(""); - - bw.write(""); - bw.write(""); - bw.write(""); - bw.write(""); - - // sort values by using a treemap..... - Map map = new TreeMap(workItem.getAllItems()); - Set set2 = map.entrySet(); - Iterator iter = set2.iterator(); - while (iter.hasNext()) { - // WorkItemAttribute da = new WorkItemAttribute(); - Map.Entry mapEntry = (Map.Entry) iter.next(); - String sName = mapEntry.getKey().toString(); - List value = (List) mapEntry.getValue(); - - if (trClass) - bw.write(""); - else - bw.write(""); - trClass = !trClass; + public long getSize(XMLDocument arg0, Class arg1, Type arg2, Annotation[] arg3, MediaType arg4) { + return -1; + } + + /** + * This Method prints a single XMLItemCollection in html format. The items are + * sorted by name + * + * @param out + * @param workItem + * @throws IOException + */ + @SuppressWarnings("rawtypes") + public static void printXMLItemCollectionHTML(BufferedWriter bw, XMLDocument xmlworkItem) throws IOException { + boolean trClass = false; + + ItemCollection workItem = XMLDocumentAdapter.putDocument(xmlworkItem); + bw.write("
UniqueID: " + workItem.getItemValueString("$uniqueid") - + "
NameValue
"); - bw.write(""); + bw.write(""); + bw.write(""); + bw.write(""); + bw.write(""); + + // sort values by using a treemap..... + Map map = new TreeMap(workItem.getAllItems()); + Set set2 = map.entrySet(); + Iterator iter = set2.iterator(); + while (iter.hasNext()) { + // WorkItemAttribute da = new WorkItemAttribute(); + Map.Entry mapEntry = (Map.Entry) iter.next(); + String sName = mapEntry.getKey().toString(); + List value = (List) mapEntry.getValue(); + + if (trClass) + bw.write(""); + else + bw.write(""); + trClass = !trClass; + + bw.write(""); + } + bw.write("
" + sName + "" + convertValuesToString(value) + "
UniqueID: " + workItem.getItemValueString("$uniqueid") + "
NameValue
" + sName + "" + convertValuesToString(value) + "
"); + bw.write("

"); } - bw.write(""); - bw.write("

"); - } - - /** - * This method converts the Values of a vector into a string representation. - * - * Multivalues will be separated with '~' characters. Date Objects will be converted into a short - * String representation taking the server locale - * - * - * @param values - * @return - */ - @SuppressWarnings("rawtypes") - public static String convertValuesToString(List values) { - String convertedValue = ""; - - if (values == null) - return convertedValue; - - boolean bFirstValue = true; - // Iterate over vector list - Iterator iter = values.iterator(); - while (iter.hasNext()) { - Object o = iter.next(); - Date dateValue = null; - // now test the objct type to date - if (o instanceof Date) { - dateValue = (Date) o; - } - if (o instanceof Calendar) { - Calendar cal = (Calendar) o; - dateValue = cal.getTime(); - } - - // if it is not the first value then add the delimiter ~ - String singleValue = ""; - if (!bFirstValue) - convertedValue += "~"; - - // if value is a date object format date into a string - // otherwise take the value as it is - if (dateValue != null) { - singleValue = - DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(dateValue); - } else { - // take value as it is - if (o != null) - singleValue = singleValue + o.toString(); - } - - convertedValue += singleValue; - bFirstValue = false; + + /** + * This method converts the Values of a vector into a string representation. + * + * Multivalues will be separated with '~' characters. Date Objects will be + * converted into a short String representation taking the server locale + * + * + * @param values + * @return + */ + @SuppressWarnings("rawtypes") + public static String convertValuesToString(List values) { + String convertedValue = ""; + + if (values == null) + return convertedValue; + + boolean bFirstValue = true; + // Iterate over vector list + Iterator iter = values.iterator(); + while (iter.hasNext()) { + Object o = iter.next(); + Date dateValue = null; + // now test the objct type to date + if (o instanceof Date) { + dateValue = (Date) o; + } + if (o instanceof Calendar) { + Calendar cal = (Calendar) o; + dateValue = cal.getTime(); + } + + // if it is not the first value then add the delimiter ~ + String singleValue = ""; + if (!bFirstValue) + convertedValue += "~"; + + // if value is a date object format date into a string + // otherwise take the value as it is + if (dateValue != null) { + singleValue = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(dateValue); + } else { + // take value as it is + if (o != null) + singleValue = singleValue + o.toString(); + } + + convertedValue += singleValue; + bFirstValue = false; + } + + // return values as string + return convertedValue; } - // return values as string - return convertedValue; - } - - /** - * This method prints the generic HTML Header for HTML output, including a default CSS definition - * for table layout. The meta tag Content-Type is generated in case a contentType and encoding is - * provided. - * - * @param bw - * @throws IOException - */ - public static void printHead(BufferedWriter bw, String contentType, String encoding) - throws IOException { - bw.write(""); - - if (contentType != null && encoding != null) { - bw.write(""); + /** + * This method prints the generic HTML Header for HTML output, including a + * default CSS definition for table layout. The meta tag Content-Type is + * generated in case a contentType and encoding is provided. + * + * @param bw + * @throws IOException + */ + public static void printHead(BufferedWriter bw, String contentType, String encoding) throws IOException { + bw.write(""); + + if (contentType != null && encoding != null) { + bw.write(""); + } + bw.write(""); + bw.write(""); } - bw.write(""); - bw.write(""); - } }