edu.kit.dama.ui.admin.workflow.DataWorkflowTaskConfigurationTab.java Source code

Java tutorial

Introduction

Here is the source code for edu.kit.dama.ui.admin.workflow.DataWorkflowTaskConfigurationTab.java

Source

/* 
 * Copyright 2015 Karlsruhe Institute of Technology.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.kit.dama.ui.admin.workflow;

import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.server.AbstractErrorMessage;
import com.vaadin.server.ErrorMessage;
import com.vaadin.server.UserError;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.Tree;
import edu.kit.dama.authorization.entities.IRoleRestriction;
import edu.kit.dama.authorization.entities.Role;
import edu.kit.dama.authorization.entities.UserId;
import edu.kit.dama.authorization.entities.impl.AuthorizationContext;
import edu.kit.dama.authorization.exceptions.EntityNotFoundException;
import edu.kit.dama.authorization.exceptions.UnauthorizedAccessAttemptException;
import edu.kit.dama.authorization.services.administration.UserServiceLocal;
import edu.kit.dama.commons.exceptions.ConfigurationException;
import edu.kit.dama.mdm.core.IMetaDataManager;
import edu.kit.dama.mdm.core.MetaDataManagement;
import edu.kit.dama.mdm.dataworkflow.DataWorkflowTaskConfiguration;
import edu.kit.dama.mdm.dataworkflow.properties.ExecutionEnvironmentProperty;
import edu.kit.dama.ui.admin.AbstractConfigurationTab;
import edu.kit.dama.ui.admin.exception.DBCommitException;
import edu.kit.dama.ui.admin.exception.MsgBuilder;
import edu.kit.dama.ui.admin.exception.NoteBuilder;
import edu.kit.dama.ui.admin.exception.UIComponentUpdateException;
import edu.kit.dama.ui.admin.utils.CSSTokenContainer;
import edu.kit.dama.ui.admin.utils.UIComponentTools;
import edu.kit.dama.ui.admin.utils.UIHelper;
import edu.kit.dama.ui.commons.util.UIUtils7;
import edu.kit.dama.ui.components.ConfirmationWindow7;
import static edu.kit.dama.ui.components.ConfirmationWindow7.RESULT.YES;
import edu.kit.dama.util.Constants;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author jejkal
 */
public class DataWorkflowTaskConfigurationTab extends AbstractConfigurationTab<DataWorkflowTaskConfiguration> {

    private static final Logger LOGGER = LoggerFactory.getLogger(DataWorkflowTaskConfigurationTab.class);
    private String DEBUG_ID_PREFIX = DataWorkflowTaskConfigurationTab.class.getName() + "_";

    private GridLayout mainLayout;
    private DataWorkflowBasePropertiesLayout basicPropertiesLayout;
    private boolean createNewWorkflowMode = false;
    private DataWorkflowTaskConfiguration selection;
    private Tree elementTree;

    public DataWorkflowTaskConfigurationTab() {
        super();
        DEBUG_ID_PREFIX += hashCode() + "_";
    }

    public final Tree getElementTree() {
        if (elementTree == null) {
            String id = "elementList";
            LOGGER.debug("Building " + DEBUG_ID_PREFIX + id + " ...");

            elementTree = new Tree("AVAILABLE ELEMENTS");
            elementTree.setId(DEBUG_ID_PREFIX + id);
            HierarchicalContainer container = new HierarchicalContainer();
            container.addContainerProperty("caption", String.class, null);
            elementTree.setContainerDataSource(container);
            elementTree.setItemCaptionPropertyId("caption");
            elementTree.setHeight("100%");
            elementTree.setWidth("300px");
            elementTree.setNullSelectionAllowed(false);
            elementTree.setImmediate(true);
            elementTree.addStyleName(CSSTokenContainer.BOLD_CAPTION);

            elementTree.addValueChangeListener(new Property.ValueChangeListener() {

                @Override
                public void valueChange(Property.ValueChangeEvent event) {
                    Object value = event.getProperty().getValue();
                    String selection;
                    if (value instanceof Long) {
                        selection = Long.toString((Long) value);
                    } else {
                        selection = (String) value;
                    }

                    ListSelection listSelection = validateListSelection(selection);

                    switch (listSelection) {
                    case NO:
                        fireNoListEntrySelected();
                        break;
                    case NEW:
                        fireNewInstanceSelected();
                        break;
                    case VALID:
                        fireValidListEntrySelected();
                        break;
                    case INVALID:
                        fireInvalidListEntrySelected();
                        break;
                    default:
                        UIComponentTools.showError("ERROR", "Unknown error occurred while updating "
                                + "element selection. " + NoteBuilder.CONTACT, -1);
                        LOGGER.error("Failed to update " + this.getClass().getSimpleName()
                                + ". Cause: Undefined enum constant detected, namely '" + listSelection.name()
                                + "'.");
                        break;
                    }
                }

            });
        }
        return elementTree;
    }

    @Override
    public GridLayout buildMainLayout() {
        String id = "mainLayout";
        LOGGER.debug("Building " + DEBUG_ID_PREFIX + id + " ...");

        UIUtils7.GridLayoutBuilder mainLayoutBuilder = new UIUtils7.GridLayoutBuilder(2, 2);

        // Add components to mainLayout
        mainLayoutBuilder.fillColumn(getElementTree(), 0, 0, 1);
        mainLayoutBuilder.fillRow(getPropertiesPanel(), 1, 0, 1);
        mainLayoutBuilder.addComponent(getCommitChangesButton(), Alignment.BOTTOM_RIGHT, 1, 1, 1, 1);
        mainLayout = mainLayoutBuilder.getLayout();
        mainLayout.setId(DEBUG_ID_PREFIX + id);
        mainLayout.setSizeFull();
        mainLayout.setImmediate(true);
        mainLayout.setSpacing(true);
        mainLayout.setMargin(true);

        mainLayout.setColumnExpandRatio(1, 1f);
        mainLayout.setRowExpandRatio(0, 1f);

        return mainLayout;

    }

    @Override
    public String getSelectedItemId() {
        return (String) getElementTree().getValue();
    }

    @Override
    public void fillElementList() {
        List<DataWorkflowTaskConfiguration> configurations = new LinkedList<>();

        IMetaDataManager mdm = MetaDataManagement.getMetaDataManagement().getMetaDataManager();
        mdm.setAuthorizationContext(AuthorizationContext.factorySystemContext());
        try {
            configurations = mdm.find(DataWorkflowTaskConfiguration.class);
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to obtain data workflow configurations", ex);
        } finally {
            mdm.close();
        }

        Map<String, List<DataWorkflowTaskConfiguration>> elementMap = new HashMap<>();

        for (DataWorkflowTaskConfiguration config : configurations) {
            String name = config.getName();
            List<DataWorkflowTaskConfiguration> configList = elementMap.get(name);
            if (configList == null) {
                configList = new ArrayList<>();
                elementMap.put(name, configList);
            }
            configList.add(config);
        }

        HierarchicalContainer container = (HierarchicalContainer) getElementTree().getContainerDataSource();
        container.removeAllItems();

        //add NEW element
        container.addItem(NEW_UNIQUE_ID);
        container.setChildrenAllowed(NEW_UNIQUE_ID, false);
        container.getContainerProperty(NEW_UNIQUE_ID, "caption").setValue(NEW_ELEMENT_LABEL);
        //add remaining elements
        elementMap.entrySet().forEach((entry) -> {
            List<DataWorkflowTaskConfiguration> elements = entry.getValue();
            Collections.sort(elements, (DataWorkflowTaskConfiguration o1,
                    DataWorkflowTaskConfiguration o2) -> Integer.compare(o1.getVersion(), o2.getVersion()));
            //parentId is ELEMENT_NAME + ID_OF_FIRST_VERSION
            String parentId = entry.getKey() + "@" + elements.get(0).getId();
            Item parent = container.addItem(parentId);
            parent.getItemProperty("caption").setValue(
                    entry.getKey() + " ( " + elements.size() + " version" + ((elements.size() > 1) ? "s)" : ")"));
            container.setChildrenAllowed(parentId, true);
            for (DataWorkflowTaskConfiguration config : elements) {
                Item child = container.addItem(config.getId());
                container.setChildrenAllowed(config.getId(), false);
                child.getItemProperty("caption").setValue(getWorkflowConfigurationCaption(config));
                container.setParent(config.getId(), parentId);
            }
        });
    }

    /**
     * Get the primary key for the provided node elementId. The elementId can be
     * one of the following: 'null' for no selection, 'MINUS_ONE_ELEMENT' for
     * 'NEW' selection, '1' for selection of a task version node, 'Task@1' for
     * selection of a task parent node containing all versions.
     */
    private long getPrimaryKeyByElementId(String elementId) {
        long value = 0;
        if (null == elementId) {
            //no selection
            value = -1;
        } else {
            switch (elementId) {
            case NEW_UNIQUE_ID:
                //we have the "NEW' node
                value = 0;
                break;
            default:
                try {
                    value = Long.parseLong(elementId);
                    //if this works, the node is a task version node
                } catch (NumberFormatException ex) {
                    //string selection
                    int minusIdx = elementId.indexOf("@");
                    if (minusIdx > -1) {
                        value = Long.parseLong(elementId.substring(minusIdx + 1, elementId.length()));
                        //if this works, the node is a task parent node
                    }
                }
                break;
            }
        }
        return value;
    }

    @Override
    public boolean elementWithIdExists(String pId) {
        boolean result = false;
        IMetaDataManager mdm = MetaDataManagement.getMetaDataManagement().getMetaDataManager();
        mdm.setAuthorizationContext(AuthorizationContext.factorySystemContext());
        try {
            result = mdm.find(DataWorkflowTaskConfiguration.class, getPrimaryKeyByElementId(pId)) != null;
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to obtain data workflow configuration for id " + pId, ex);
        } finally {
            mdm.close();
        }
        return result;
    }

    @Override
    public DataWorkflowTaskConfiguration loadElementById(String pId) {
        DataWorkflowTaskConfiguration result = null;
        IMetaDataManager mdm = MetaDataManagement.getMetaDataManagement().getMetaDataManager();
        mdm.setAuthorizationContext(AuthorizationContext.factorySystemContext());
        try {
            result = mdm.find(DataWorkflowTaskConfiguration.class, getPrimaryKeyByElementId(pId));
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to obtain data workflow configuration for id " + pId, ex);
        } finally {
            mdm.close();
        }
        return result;
    }

    @Override
    public void selectElement(DataWorkflowTaskConfiguration pSelection)
            throws ConfigurationException, UIComponentUpdateException {
        //called if a valid element is selected.
        if (pSelection != null) {
            //Store all information of the selected workflow that may not change without changing also the version number.
            //'selection' is later used to check whether the version number must be updated or not.
            selection = new DataWorkflowTaskConfiguration();
            selection.setId(pSelection.getId());
            selection.setName(pSelection.getName());
            selection.setApplicationPackageUrl(pSelection.getApplicationPackageUrl());
            selection.setApplicationArguments(pSelection.getApplicationArguments());
        } else {
            //called if new element is selected
            DataWorkflowTaskConfiguration dummySelection = new DataWorkflowTaskConfiguration();
            dummySelection.setName("NewDataWorkflowTask");
            dummySelection.setVersion(1);
            dummySelection.setContactUserId("admin");
            dummySelection.setApplicationPackageUrl("file:///");
            dummySelection.setGroupId(Constants.USERS_GROUP_ID);
            //            dummySelection.setDisabled(Boolean.TRUE);
            //            dummySelection.setDefaultTask(Boolean.FALSE);
            getBasicPropertiesLayout().updateSelection(dummySelection);
            //no selection, new element creation
            selection = null;
        }
    }

    @Override
    public void resetComponents() {
        //nothing to do here
    }

    @Override
    public void enableComponents(boolean pValue) {
        //nothing to do here

    }

    @Override
    public void setEnabledComponents(ListSelection listSelection) {
        //overwriting of this method is needed as this tab uses the properties panel for both: creating and changing elements.
        switch (listSelection) {
        case NO:
        case INVALID:
            getPropertiesPanel().setEnabled(false);
            getCommitChangesButton().setEnabled(false);
            enableComponents(false);
            createNewWorkflowMode = false;
            break;
        case NEW:
            getPropertiesPanel().setEnabled(true);
            getCommitChangesButton().setEnabled(true);
            enableComponents(true);
            createNewWorkflowMode = true;
            try {
                selectElement(null);
            } catch (ConfigurationException | UIComponentUpdateException ex) {
                //ignore
            }
            break;
        case VALID:
            getPropertiesPanel().setEnabled(true);
            getCommitChangesButton().setEnabled(true);
            enableComponents(true);
            createNewWorkflowMode = false;
            break;
        default:
            UIComponentTools.showError("ERROR",
                    "Unknown error occurred while updating " + "element. " + NoteBuilder.CONTACT, -1);
            LOGGER.error("Failed to update " + getPropertiesPanel().getId()
                    + ". Cause: Undefined enum constant detected, namely '" + listSelection.name() + "'.");
            createNewWorkflowMode = false;
        }
    }

    @Override
    public void commitChanges() {
        final String applicationName = getBasicPropertiesLayout().getNameField().getValue();
        final int currentVersion = getWorkflowVersion(applicationName);
        LOGGER.debug("Committing changed to workflow configuration with name '{}' and version '{}'",
                applicationName, currentVersion);
        if (createNewWorkflowMode) {
            //'selection' should be null, check for existing workflow with same name

            if (currentVersion <= 0) {//if not exist, check packageUrl and contactId, persist entity and reload
                LOGGER.debug("Creating new workflow.");
                createNewWorkflowConfiguration(applicationName);
            } else {//if exists, ask for update...cancel if no update, update version otherwise 
                UIComponentTools.showWarning("There is already a workflow configuration named '" + applicationName
                        + "' registered. " + "Please select another name to proceed.");
                return;
            }
        } else {
            //'selection' should contain the name of the currently selected workflow, compare the name field with it.
            if (applicationName.equals(selection.getName())) {
                //if names are equal, check whether update-relevant fields have changed (applicationUrl and arguments)
                updateWorkflowConfiguration(applicationName, currentVersion + 1);
            } else {
                //if names are not equal, behave like creating a new workflow, check packageUrl and contactId, persist entity and reload.
                createNewWorkflowConfiguration(applicationName);
            }
        }
    }

    /**
     * Create a new workflow configuration using the values from the UI.
     *
     * @param pName The configuration name.
     */
    private void createNewWorkflowConfiguration(String pName) {
        IMetaDataManager mdm = MetaDataManagement.getMetaDataManagement().getMetaDataManager();
        mdm.setAuthorizationContext(AuthorizationContext.factorySystemContext());
        boolean result = false;

        if (getWorkflowVersion(pName) > 0) {
            UIComponentTools.showWarning("There is already a workflow configuration named '" + pName
                    + "' registered. " + "Please select another name to proceed.");
            return;
        }
        if (pName.contains("@")) {
            getBasicPropertiesLayout().getNameField().setComponentError(
                    new UserError("Data workflow configuration names may not contain the @ character.",
                            AbstractErrorMessage.ContentMode.TEXT, ErrorMessage.ErrorLevel.WARNING));
            return;
        } else {
            getBasicPropertiesLayout().getNameField().setComponentError(null);
        }

        try {
            LOGGER.debug("Creating new workflow configuration from UI.");
            selection = new DataWorkflowTaskConfiguration();
            selection.setName(pName);
            selection.setGroupId((String) getBasicPropertiesLayout().getGroupBox().getValue());
            String contactUserId = (String) getBasicPropertiesLayout().getContactBox().getValue();
            if (!checkContactUserId(contactUserId)) {
                return;
            }

            String applicationUrl = getBasicPropertiesLayout().getApplicationPackageUrlField().getValue();

            try {
                LOGGER.debug("Successfully validated application package URL {}", new URL(applicationUrl));
            } catch (MalformedURLException ex) {
                UIComponentTools.showWarning("The provided application package URL is invalid.");
                return;
            }

            selection.setApplicationPackageUrl(
                    getBasicPropertiesLayout().getApplicationPackageUrlField().getValue());

            selection.setApplicationArguments(getBasicPropertiesLayout().getApplicationArgumentsField().getValue());
            selection.setVersion(1);
            selection.setContactUserId((String) getBasicPropertiesLayout().getContactBox().getValue());
            LOGGER.debug("Setting other attributes.");
            selection.setKeywords(getBasicPropertiesLayout().getKeywordsField().getValue());
            selection.setDescription(getBasicPropertiesLayout().getDescriptionArea().getValue());
            //            selection.setDisabled(getBasicPropertiesLayout().getDisabledBox().getValue());
            //            selection.setDefaultTask(getBasicPropertiesLayout().getDefaultBox().getValue());
            LOGGER.debug("Updating environment requirements.");
            selection.removeRequiredEnvironmentProperties();
            Set<Object> environmentProperties = (Set<Object>) getBasicPropertiesLayout()
                    .getEnvironmentPropertiesSelect().getValue();
            for (Object propId : environmentProperties) {
                ExecutionEnvironmentProperty property = mdm.find(ExecutionEnvironmentProperty.class, propId);
                if (property == null) {
                    LOGGER.warn("Failed to add environment property with id {}. Entry not found in database.",
                            propId);
                    return;
                } else {
                    selection.addRequiredEnvironmentProperty(property);
                }
            }
            LOGGER.debug("Saving new workflow configuration.");
            selection = mdm.save(selection);
            LOGGER.debug("Workflow configuration '{}' successully saved.", pName);
            result = true;
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Not authorized to obtain data workflow configuration for id " + selection.getId(), ex);
        } finally {
            mdm.close();
        }
        if (result) {
            addNewElementInstance(selection);
        }

    }

    /**
     * Update the workflow configuration with the provided name to the provided
     * version. A new version will be created if either the
     * applicationPackageUrl or the applicationArguments have changed. To check
     * this, the member variable 'selection' should contain those field that can
     * be compared to the current values in the UI. Otherwise, the existing
     * workflow configuration will just be updated.
     *
     * @param
     */
    private void updateWorkflowConfiguration(String pName, int pNewVersion) {
        IMetaDataManager mdm = MetaDataManagement.getMetaDataManagement().getMetaDataManager();
        mdm.setAuthorizationContext(AuthorizationContext.factorySystemContext());
        boolean result = false;
        try {
            if (selection.getId() == null) {
                throw new DBCommitException("Id of the current selection must not be null.");
            }

            //just reload the result.
            selection = mdm.find(DataWorkflowTaskConfiguration.class, selection.getId());

            String contactUserId = (String) getBasicPropertiesLayout().getContactBox().getValue();
            if (!checkContactUserId(contactUserId)) {
                return;
            }

            selection.setContactUserId((String) getBasicPropertiesLayout().getContactBox().getValue());
            selection.setGroupId((String) getBasicPropertiesLayout().getGroupBox().getValue());
            LOGGER.debug("Setting other attributes.");
            selection.setKeywords(getBasicPropertiesLayout().getKeywordsField().getValue());
            selection.setDescription(getBasicPropertiesLayout().getDescriptionArea().getValue());
            //            selection.setDisabled(getBasicPropertiesLayout().getDisabledBox().getValue());
            //            selection.setDefaultTask(getBasicPropertiesLayout().getDefaultBox().getValue());

            LOGGER.debug("Updating environment requirements.");
            selection.removeRequiredEnvironmentProperties();
            Set<Object> environmentProperties = (Set<Object>) getBasicPropertiesLayout()
                    .getEnvironmentPropertiesSelect().getValue();
            for (Object propId : environmentProperties) {
                ExecutionEnvironmentProperty property = mdm.find(ExecutionEnvironmentProperty.class, propId);
                if (property == null) {
                    LOGGER.warn("Failed to add environment property with id {}. Entry not found in database.",
                            propId);
                } else {
                    selection.addRequiredEnvironmentProperty(property);
                }
            }
            LOGGER.debug("Checking whether to perform an update or an upgrade.");

            String appPkg1 = selection.getApplicationPackageUrl();
            String appPkg2 = getBasicPropertiesLayout().getApplicationPackageUrlField().getValue();

            if (appPkg1 == null || appPkg2 == null) {
                throw new DBCommitException("Package Url must not be null.");
            }

            String arg1 = selection.getApplicationArguments() == null ? "" : selection.getApplicationArguments();
            String arg2 = getBasicPropertiesLayout().getApplicationArgumentsField().getValue() == null ? ""
                    : getBasicPropertiesLayout().getApplicationArgumentsField().getValue();

            if (appPkg1.equals(appPkg2) && arg1.equals(arg2)) {
                //simple update
                LOGGER.debug(
                        "No upgrade-relevant fields have been modified. Updating existing workflow configuration.");
                selection = mdm.save(selection);
                LOGGER.debug("Workflow configuration '{}' successully updated, version number unchanged.", pName);
            } else {
                //url or arguments have changed...do version update
                LOGGER.debug(
                        "At least one upgrade-relevant field hast been modified. Upgrading existing workflow configuration to new version '{}'.",
                        pNewVersion);
                selection.setId(null);
                selection.setApplicationPackageUrl(
                        getBasicPropertiesLayout().getApplicationPackageUrlField().getValue());
                selection.setApplicationArguments(
                        getBasicPropertiesLayout().getApplicationArgumentsField().getValue());
                selection.setVersion(pNewVersion);
                selection = mdm.save(selection);
                LOGGER.debug("Workflow configuration '{}' successully upgraded to version '{}'", pName,
                        pNewVersion);
            }
            result = true;
        } catch (DBCommitException ex) {
            UIComponentTools.showError("Failed to update data workflow configuration! Cause: " + ex.getMessage());
            String object = "the changed workflow configuration '" + pName + "'";
            LOGGER.error(MsgBuilder.commitFailed(object) + "Cause: " + ex.getMessage(), ex);
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to obtain data workflow configuration for id " + selection.getId(), ex);
        } finally {
            mdm.close();
        }

        if (result) {
            updateElementInstance(selection);
        }
    }

    /**
     * Check the provided userId. If the user id exists and the max. role is
     * {@link edu.kit.dama.authorization.entities.Role#MEMBER}, TRUE is
     * returned. Otherwise, FALSE is returned and the cause of the failed check
     * is set as component error to the userId input field of the according
     * properties UI.
     *
     * @param pUserId The userId to check.
     *
     * @return TRUE if the user exists and has a proper max. role, FALSE
     * otherwise.
     */
    private boolean checkContactUserId(String pUserId) {
        boolean result = true;
        LOGGER.debug("Checking contact user id {}.", pUserId);
        if (pUserId != null) {
            try {
                IRoleRestriction<Role> role = UserServiceLocal.getSingleton()
                        .getRoleRestriction(new UserId(pUserId), AuthorizationContext.factorySystemContext());
                if (!role.atLeast(Role.MEMBER)) {
                    LOGGER.warn("Invalid contact userId '{}'. MaxRole is lower than MEMBER.", pUserId);
                    getBasicPropertiesLayout().getContactBox()
                            .setComponentError(new UserError("User has insufficient permissions (role < MEMBER).",
                                    AbstractErrorMessage.ContentMode.TEXT, ErrorMessage.ErrorLevel.WARNING));
                    result = false;
                }
            } catch (UnauthorizedAccessAttemptException ex) {
                LOGGER.error("Failed to check contact userId. SystemContext is not authorized.", ex);
                getBasicPropertiesLayout().getContactBox()
                        .setComponentError(new UserError("Failed to check for user id '" + pUserId + "'",
                                AbstractErrorMessage.ContentMode.TEXT, ErrorMessage.ErrorLevel.WARNING));
                result = false;
            } catch (EntityNotFoundException ex) {
                LOGGER.warn("Invalid contact userId '{}'. UserId not found.", pUserId);
                getBasicPropertiesLayout().getContactBox()
                        .setComponentError(new UserError("No valid user id '" + pUserId + "'",
                                AbstractErrorMessage.ContentMode.TEXT, ErrorMessage.ErrorLevel.WARNING));
                result = false;
            }
        }
        if (result) {
            getBasicPropertiesLayout().getContactBox().setComponentError(null);
        }
        return result;
    }

    /**
     * Get the current version of the workflow configuration with the provided
     * name. There are three possible results: -1 means that the query for the
     * configuration with the provided name failed. 0 means, that there is no
     * configuration with the provided name and a value larger 0 is the current
     * version of the configuration with the provided name.
     *
     * @param pConfigurationName The name of the configuration.
     *
     * @return The version number as described above.
     */
    private int getWorkflowVersion(String pConfigurationName) {
        IMetaDataManager mdm = MetaDataManagement.getMetaDataManagement().getMetaDataManager();
        mdm.setAuthorizationContext(AuthorizationContext.factorySystemContext());
        List<DataWorkflowTaskConfiguration> result = new LinkedList<>();
        try {
            result = mdm.findResultList("SELECT w FROM DataWorkflowTaskConfiguration w WHERE w.name=?1",
                    new Object[] { pConfigurationName }, DataWorkflowTaskConfiguration.class);
        } catch (UnauthorizedAccessAttemptException ex) {
            //error ... cannot continue
            return -1;
        } finally {
            mdm.close();
        }

        if (result.isEmpty()) {
            return 0;
        }
        Collections.sort(result, (DataWorkflowTaskConfiguration o1, DataWorkflowTaskConfiguration o2) -> Integer
                .compare(o1.getVersion(), o2.getVersion()));

        return result.get(result.size() - 1).getVersion();
    }

    @Override
    public void addNewElementInstance(DataWorkflowTaskConfiguration pElementToAdd) {
        fillElementList();
        Object parent = elementTree.getParent(pElementToAdd.getId());
        elementTree.expandItemsRecursively(parent);
        elementTree.select(pElementToAdd.getId());
    }

    @Override
    public void updateElementInstance(DataWorkflowTaskConfiguration pElementToUpdate) {
        fillElementList();
        Object parent = elementTree.getParent(pElementToUpdate.getId());
        elementTree.expandItemsRecursively(parent);
        elementTree.select(pElementToUpdate.getId());
    }

    /**
     * Get the (list) item caption for the provided workflow configuration.
     *
     * @param accessPoint The workflow configuration.
     *
     * @return The item caption in the format 'ConfigurationName
     * ConfigurationVersion (ConfigurationId)'
     */
    private String getWorkflowConfigurationCaption(DataWorkflowTaskConfiguration workflowConfiguration) {
        return workflowConfiguration.getName() + " v." + workflowConfiguration.getVersion() + " ("
                + workflowConfiguration.getId() + ")";
    }

    @Override
    public DataWorkflowBasePropertiesLayout getBasicPropertiesLayout() {
        if (basicPropertiesLayout == null) {
            basicPropertiesLayout = new DataWorkflowBasePropertiesLayout();
        }
        return basicPropertiesLayout;
    }

}