org.eclipse.hawkbit.ui.management.actionhistory.ActionHistoryTable.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.hawkbit.ui.management.actionhistory.ActionHistoryTable.java

Source

/**
 * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.eclipse.hawkbit.ui.management.actionhistory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringJoiner;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.eclipse.hawkbit.repository.ActionStatusFields;
import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.ActionWithStatusCount;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.ui.common.ConfirmationDialog;
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.management.event.ManagementUIEvent;
import org.eclipse.hawkbit.ui.management.event.PinUnpinEvent;
import org.eclipse.hawkbit.ui.management.event.TargetTableEvent;
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;

import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.server.FontAwesome;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TreeTable;
import com.vaadin.ui.UI;
import com.vaadin.ui.themes.ValoTheme;

/**
 * Table for {@link Target#getActions()} history.
 *
 */
@SpringComponent
@ViewScope
public class ActionHistoryTable extends TreeTable {

    private static final long serialVersionUID = -1631514704696786653L;
    private static final Logger LOG = LoggerFactory.getLogger(ActionHistoryTable.class);
    private static final String BUTTON_CANCEL = "button.cancel";
    private static final String BUTTON_OK = "button.ok";

    @Autowired
    private I18N i18n;

    @Autowired
    private transient DeploymentManagement deploymentManagement;

    @Autowired
    private transient EventBus.SessionEventBus eventBus;

    @Autowired
    private UINotification notification;

    @Autowired
    private ManagementUIState managementUIState;

    private Container hierarchicalContainer;
    private boolean alreadyHasMessages;

    private Target target;

    private static final String STATUS_ICON_GREEN = "statusIconGreen";

    /**
     * Initialize the Action History Table.
     */
    @PostConstruct
    public void init() {
        initializeTableSettings();
        buildComponent();
        restorePreviousState();
        setVisibleColumns(getVisbleColumns().toArray());
        eventBus.subscribe(this);
        setPageLength(SPUIDefinitions.PAGE_SIZE);
    }

    @PreDestroy
    void destroy() {
        eventBus.unsubscribe(this);
    }

    @EventBusListenerMethod(scope = EventScope.SESSION)
    void onEvent(final ManagementUIEvent mgmtUIEvent) {
        if (mgmtUIEvent == ManagementUIEvent.MAX_ACTION_HISTORY) {
            UI.getCurrent().access(() -> createTableContentForMax());
        }
        if (mgmtUIEvent == ManagementUIEvent.MIN_ACTION_HISTORY) {
            UI.getCurrent().access(() -> normalActionHistoryTable());
        }
    }

    /*
     * this method is called when the target history component is initialized
     * without any data
     */
    private void buildComponent() {
        // create an empty container
        createContainer();
        setContainerDataSource(hierarchicalContainer);
        addGeneratedColumns();
        setColumnExpandRatioForMinimisedTable();
    }

    private void setColumnExpandRatioForMinimisedTable() {
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID, 0.1F);
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DIST, 0.3F);
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_STATUS, 0.15F);
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DATETIME, 0.3F);
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_FORCED, 0.15F);
        setColumnExpandRatio(SPUIDefinitions.ACTIONS_COLUMN, 0.2F);
    }

    private void initializeTableSettings() {

        setId(UIComponentIdProvider.ACTION_HISTORY_TABLE_ID);
        setSelectable(false);
        setMultiSelect(false);
        setSortEnabled(true);
        setColumnReorderingAllowed(true);
        setHeight(100.0F, Unit.PERCENTAGE);
        setWidth(100.0F, Unit.PERCENTAGE);
        setImmediate(true);
        setStyleName("sp-table");
        addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
        addStyleName(ValoTheme.TABLE_SMALL);
        setColumnAlignment(SPUIDefinitions.ACTION_HIS_TBL_FORCED, Align.CENTER);
        setColumnAlignment(SPUIDefinitions.ACTION_HIS_TBL_STATUS, Align.CENTER);
        setColumnAlignment(SPUIDefinitions.ACTIONS_COLUMN, Align.CENTER);
        // listeners for child
        addExpandListener(event -> {
            expandParentActionRow(event.getItemId());
            managementUIState.getExpandParentActionRowId().add(event.getItemId());
        });
        addCollapseListener(event -> {
            collapseParentActionRow(event.getItemId());
            managementUIState.getExpandParentActionRowId().remove(event.getItemId());
        });
    }

    /**
     * Create a empty HierarchicalContainer.
     */
    public void createContainer() {
        /* Create HierarchicalContainer container */
        hierarchicalContainer = new HierarchicalContainer();
        hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN, String.class,
                null);
        hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED, Action.class, null);
        hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID_HIDDEN, Long.class,
                null);
        hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID, String.class, null);
        hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_DIST, String.class, null);
        hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_DATETIME, String.class, null);
        hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN,
                Action.Status.class, null);
        hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_MSGS_HIDDEN, List.class, null);
        hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME, String.class, null);

    }

    private List<Object> getVisbleColumns() {
        final List<Object> visibleColumnIds = new ArrayList<>();
        visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE);
        visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_DIST);
        visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_DATETIME);
        visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_STATUS);
        visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_FORCED);
        visibleColumnIds.add(SPUIDefinitions.ACTIONS_COLUMN);

        if (managementUIState.isActionHistoryMaximized()) {
            visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME);
            visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_MSGS);
            visibleColumnIds.add(1, SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID);
        }
        return visibleColumnIds;
    }

    /**
     * fetch the target details using controller id, and set it globally.
     *
     * @param selectedTarget
     *            reference of target
     */
    public void populateTableData(final Target selectedTarget) {
        target = selectedTarget;
        refreshContainer();
    }

    /* re -create the container and get the data and set it to the table */
    private void refreshContainer() {
        getcontainerData();
        // to expand parent row , if already expanded.
        expandParentRow();

    }

    private void getcontainerData() {
        hierarchicalContainer.removeAllItems();

        if (target != null) {
            /* service method to create action history for target */
            final List<ActionWithStatusCount> actionHistory = deploymentManagement
                    .findActionsWithStatusCountByTargetOrderByIdDesc(target);

            addDetailsToContainer(actionHistory);
        }
    }

    /**
     * Populate Container for Action.
     *
     * @param isActiveActions
     *            as flag
     * @param reversedActions
     *            as action
     * @param startIdx
     *            as sort
     * @param target2
     * @param actionHistoryMode
     *            as either {@link ActionHistoryMode.NORMAL} or
     *            {@link ActionHistoryMode.MAXIMIZED}
     */
    @SuppressWarnings("unchecked")
    private void addDetailsToContainer(final List<ActionWithStatusCount> actions) {
        for (final ActionWithStatusCount actionWithStatusCount : actions) {

            final Action action = actionWithStatusCount.getAction();

            final Item item = hierarchicalContainer.addItem(actionWithStatusCount.getAction().getId());

            item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN)
                    .setValue(actionWithStatusCount.getAction().getStatus());

            /*
             * add action id.
             */
            item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID)
                    .setValue(actionWithStatusCount.getAction().getId().toString());
            /*
             * add active/inactive status to the item which will be used in
             * Column generator to generate respective icon
             */
            item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN)
                    .setValue(actionWithStatusCount.getAction().isActive() ? SPUIDefinitions.ACTIVE
                            : SPUIDefinitions.IN_ACTIVE);

            /*
             * add action Id to the item which will be used for fetching child
             * items ( previous action status ) during expand
             */
            item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID_HIDDEN)
                    .setValue(actionWithStatusCount.getAction().getId());

            /*
             * add distribution name to the item which will be displayed in the
             * table. The name should not exceed certain limit.
             */
            item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DIST)
                    .setValue(actionWithStatusCount.getDsName() + ":" + actionWithStatusCount.getDsVersion());
            item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED).setValue(action);

            /* Default no child */
            ((Hierarchical) hierarchicalContainer).setChildrenAllowed(actionWithStatusCount.getAction().getId(),
                    false);

            item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DATETIME).setValue(
                    SPDateTimeUtil.getFormattedDate(actionWithStatusCount.getAction().getLastModifiedAt()));

            item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME)
                    .setValue(actionWithStatusCount.getRolloutName());

            if (actionWithStatusCount.getActionStatusCount() > 0) {
                ((Hierarchical) hierarchicalContainer).setChildrenAllowed(actionWithStatusCount.getAction().getId(),
                        true);
            }
        }
    }

    private void addGeneratedColumns() {
        addGeneratedColumn(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE, new Table.ColumnGenerator() {
            /* Serial Verion Id */
            private static final long serialVersionUID = -8673604389011758339L;

            @Override
            public Component generateCell(final Table source, final Object itemId, final Object columnId) {
                return getActiveColumn(itemId);
            }
        });
        addGeneratedColumn(SPUIDefinitions.ACTION_HIS_TBL_STATUS, new Table.ColumnGenerator() {
            /* Serial Verion Id */
            private static final long serialVersionUID = 1L;

            @Override
            public Component generateCell(final Table source, final Object itemId, final Object columnId) {
                return getStatusColumn(itemId);
            }
        });
        // forced
        addGeneratedColumn(SPUIDefinitions.ACTION_HIS_TBL_FORCED, new Table.ColumnGenerator() {
            /* Serial Verion Id */
            private static final long serialVersionUID = 1L;

            @Override
            public Component generateCell(final Table source, final Object itemId, final Object columnId) {
                return getForcedColumn(itemId);
            }
        });

        addGeneratedColumn(SPUIDefinitions.ACTIONS_COLUMN, new Table.ColumnGenerator() {

            private static final long serialVersionUID = 1L;

            @Override
            public Component generateCell(final Table source, final Object itemId, final Object columnId) {
                return createActionBarColumn(itemId);
            }
        });
    }

    private Component getForcedColumn(final Object itemId) {
        final Action actionWithActiveStatus = (Action) hierarchicalContainer.getItem(itemId)
                .getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED).getValue();
        final Label actionLabel = new LabelBuilder().name("").buildCaptionLabel();
        actionLabel.setContentMode(ContentMode.HTML);
        actionLabel.setStyleName("action-history-table-col-forced-label");
        if (actionWithActiveStatus != null && actionWithActiveStatus.getActionType() == ActionType.FORCED) {
            actionLabel.setValue(FontAwesome.BOLT.getHtml());
            // setted Id for Forced.
            actionLabel.setId("action.history.table.forcedId");
        } else if (actionWithActiveStatus != null
                && actionWithActiveStatus.getActionType() == ActionType.TIMEFORCED) {
            return actionLabelWithTimeForceIcon(actionWithActiveStatus, actionLabel);
        }
        return actionLabel;
    }

    private Component getActiveColumn(final Object itemId) {
        final Action.Status status = (Action.Status) hierarchicalContainer.getItem(itemId)
                .getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN).getValue();
        String activeValue;
        if (status == Action.Status.SCHEDULED) {
            activeValue = Action.Status.SCHEDULED.toString().toLowerCase();
        } else {
            activeValue = (String) hierarchicalContainer.getItem(itemId)
                    .getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN).getValue();
        }
        final String distName = (String) hierarchicalContainer.getItem(itemId)
                .getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DIST).getValue();
        final Label activeStatusIcon = createActiveStatusLabel(activeValue,
                (Action.Status) hierarchicalContainer.getItem(itemId)
                        .getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN)
                        .getValue() == Action.Status.ERROR);
        activeStatusIcon.setId(new StringJoiner(".").add(distName).add(itemId.toString())
                .add(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE).add(activeValue).toString());
        return activeStatusIcon;
    }

    private HorizontalLayout createActionBarColumn(final Object itemId) {
        final HorizontalLayout actionBar = new HorizontalLayout();
        final Item item = hierarchicalContainer.getItem(itemId);
        final Long actionId = (Long) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID_HIDDEN)
                .getValue();
        final String activeValue = (String) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN)
                .getValue();
        final Action actionWithActiveStatus = (Action) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED)
                .getValue();

        if (actionWithActiveStatus == null) {
            return null;
        }
        final boolean isActionActive = target != null && SPUIDefinitions.ACTIVE.equals(activeValue);

        final Button actionCancel = SPUIComponentProvider.getButton(
                UIComponentIdProvider.ACTION_HISTORY_TABLE_CANCEL_ID, "", i18n.get("message.cancel.action"),
                ValoTheme.BUTTON_TINY, true, FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
        actionCancel.setEnabled(isActionActive && !actionWithActiveStatus.isCancelingOrCanceled());
        actionCancel.addClickListener(event -> confirmAndCancelAction(actionId));

        final Button actionForce = SPUIComponentProvider.getButton(
                UIComponentIdProvider.ACTION_HISTORY_TABLE_FORCE_ID, "", i18n.get("message.force.action"),
                ValoTheme.BUTTON_TINY, true, FontAwesome.BOLT, SPUIButtonStyleSmallNoBorder.class);
        actionForce.setEnabled(isActionActive && !actionWithActiveStatus.isForce()
                && !actionWithActiveStatus.isCancelingOrCanceled());
        actionForce.addClickListener(event -> confirmAndForceAction(actionId));

        final Button actionForceQuit = SPUIComponentProvider.getButton(
                UIComponentIdProvider.ACTION_HISTORY_TABLE_FORCE_QUIT_ID, "", i18n.get("message.forcequit.action"),
                ValoTheme.BUTTON_TINY + " redicon", true, FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
        actionForceQuit.setEnabled(isActionActive && actionWithActiveStatus.isCancelingOrCanceled());
        actionForceQuit.addClickListener(event -> confirmAndForceQuitAction(actionId));

        actionBar.addComponents(actionCancel, actionForce, actionForceQuit);

        return actionBar;
    }

    private Component getStatusColumn(final Object itemId) {
        final Action.Status status = (Action.Status) hierarchicalContainer.getItem(itemId)
                .getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN).getValue();
        return getStatusIcon(status);
    }

    /**
     * Load the rows of previous status history of the selected action row and
     * add it next to the selected action row.
     *
     * @param parentRowIdx
     *            index of the selected action row.
     */
    @SuppressWarnings("unchecked")
    private void expandParentActionRow(final Object parentRowIdx) {
        /* Get the item for which the expand is made */
        final Item item = hierarchicalContainer.getItem(parentRowIdx);
        if (null != item) {
            final Long actionId = (Long) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID_HIDDEN)
                    .getValue();

            final org.eclipse.hawkbit.repository.model.Action action = deploymentManagement
                    .findActionWithDetails(actionId);
            final Pageable pageReq = new PageRequest(0, 1000,
                    new Sort(Direction.DESC, ActionStatusFields.ID.getFieldName()));
            final Page<ActionStatus> actionStatusList;
            if (managementUIState.isActionHistoryMaximized()) {
                actionStatusList = deploymentManagement.findActionStatusByActionWithMessages(pageReq, action);
            } else {
                actionStatusList = deploymentManagement.findActionStatusByAction(pageReq, action);
            }
            final List<ActionStatus> content = actionStatusList.getContent();
            /*
             * Since the recent action status and messages are already
             * displaying with parent item, check if more than one action status
             * available.
             */
            int childIdx = 1;
            for (final ActionStatus actionStatus : content) {
                final String childId = parentRowIdx + " -> " + childIdx;
                final Item childItem = hierarchicalContainer.addItem(childId);
                if (null != childItem) {
                    /*
                     * For better UI, no need to display active/inactive icon
                     * for child items.
                     */
                    childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN).setValue("");

                    childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DIST).setValue(
                            action.getDistributionSet().getName() + ":" + action.getDistributionSet().getVersion());

                    childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DATETIME)
                            .setValue(SPDateTimeUtil.getFormattedDate(actionStatus.getCreatedAt()));
                    childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN)
                            .setValue(actionStatus.getStatus());
                    showOrHideMessage(childItem, actionStatus);
                    /* No further child items allowed for the child items */
                    ((Hierarchical) hierarchicalContainer).setChildrenAllowed(childId, false);
                    /* Assign this childItem to the parent */
                    ((Hierarchical) hierarchicalContainer).setParent(childId, parentRowIdx);
                    childIdx++;

                }
            }
        }
    }

    /**
     * Hide the rows of previous status history of the selected action row.
     *
     * @param parentRowIdx
     *            index of the selected action row.
     */
    public void collapseParentActionRow(final Object parentRowIdx) {
        /* Remove all child items for the clear the memory. */
        final Collection<?> children = ((Hierarchical) hierarchicalContainer).getChildren(parentRowIdx);
        if (children != null && !children.isEmpty()) {
            String ids = children.toString().substring(1);
            ids = ids.substring(0, ids.length() - 1);
            for (final String childId : ids.split(", ")) {
                ((Hierarchical) hierarchicalContainer).removeItem(childId);
            }
        }
    }

    /**
     * Get status icon.
     *
     * @param status
     *            as Status
     * @return Label as UI
     */
    private Label getStatusIcon(final Action.Status status) {
        final Label label = new LabelBuilder().name("").buildLabel();
        final String statusIconPending = "statusIconPending";
        label.setContentMode(ContentMode.HTML);
        if (Action.Status.FINISHED == status) {
            label.setDescription(i18n.get("label.finished"));
            label.setStyleName(STATUS_ICON_GREEN);
            label.setValue(FontAwesome.CHECK_CIRCLE.getHtml());
        } else if (Action.Status.ERROR == status) {
            label.setDescription(i18n.get("label.error"));
            label.setStyleName("statusIconRed");
            label.setValue(FontAwesome.EXCLAMATION_CIRCLE.getHtml());
        } else if (Action.Status.WARNING == status) {
            label.setStyleName("statusIconOrange");
            label.setDescription(i18n.get("label.warning"));
            label.setValue(FontAwesome.EXCLAMATION_CIRCLE.getHtml());
        } else if (Action.Status.RUNNING == status) {
            // dynamic spinner
            label.setStyleName(statusIconPending);
            label.setDescription(i18n.get("label.running"));
            label.setValue(FontAwesome.ADJUST.getHtml());
        } else if (Action.Status.CANCELING == status) {
            label.setStyleName(statusIconPending);
            label.setDescription(i18n.get("label.cancelling"));
            label.setValue(FontAwesome.TIMES_CIRCLE.getHtml());
        } else if (Action.Status.CANCELED == status) {
            label.setStyleName(statusIconPending);
            label.setDescription(i18n.get("label.cancelled"));
            label.setStyleName(STATUS_ICON_GREEN);
            label.setValue(FontAwesome.TIMES_CIRCLE.getHtml());
        } else if (Action.Status.RETRIEVED == status) {
            label.setStyleName(statusIconPending);
            label.setDescription(i18n.get("label.retrieved"));
            label.setValue(FontAwesome.CIRCLE_O.getHtml());
        } else if (Action.Status.DOWNLOAD == status) {
            label.setStyleName(statusIconPending);
            label.setDescription(i18n.get("label.download"));
            label.setValue(FontAwesome.CLOUD_DOWNLOAD.getHtml());
        } else if (Action.Status.SCHEDULED == status) {
            label.setStyleName(statusIconPending);
            label.setDescription(i18n.get("label.scheduled"));
            label.setValue(FontAwesome.HOURGLASS_1.getHtml());
        } else {
            label.setDescription("");
            label.setValue("");
        }
        return label;

    }

    // to show forced Icon
    private Component actionLabelWithTimeForceIcon(final Action actionWithActiveStatus, final Label actionLabel) {
        final long currentTimeMillis = System.currentTimeMillis();

        final HorizontalLayout hLayout = new HorizontalLayout();
        final Label autoForceLabel = new LabelBuilder().name("").id("action.history.table.timedforceId")
                .buildLabel();

        actionLabel.setValue(FontAwesome.BOLT.getHtml());
        autoForceLabel.setContentMode(ContentMode.HTML);
        autoForceLabel.setValue(FontAwesome.HISTORY.getHtml());

        hLayout.addComponent(actionLabel);
        hLayout.addComponent(autoForceLabel);

        if (actionWithActiveStatus.isHitAutoForceTime(currentTimeMillis)) {
            autoForceLabel.setDescription("autoforced");
            autoForceLabel.setStyleName(STATUS_ICON_GREEN);
            autoForceLabel.setDescription("auto forced since " + SPDateTimeUtil
                    .getDurationFormattedString(actionWithActiveStatus.getForcedTime(), currentTimeMillis, i18n));
        } else {
            autoForceLabel.setDescription("auto forcing in " + SPDateTimeUtil
                    .getDurationFormattedString(currentTimeMillis, actionWithActiveStatus.getForcedTime(), i18n));
            autoForceLabel.setStyleName("statusIconPending");
            autoForceLabel.setValue(FontAwesome.HISTORY.getHtml());
        }
        return hLayout;
    }

    /**
     * Create Status Label.
     *
     * @param activeValue
     *            as String
     * @return Labeal as UI
     */
    private static Label createActiveStatusLabel(final String activeValue, final boolean endedWithError) {
        final Label label = new LabelBuilder().name("").buildLabel();
        label.setContentMode(ContentMode.HTML);
        if (SPUIDefinitions.SCHEDULED.equals(activeValue)) {
            label.setDescription("Scheduled");
            label.setValue(FontAwesome.HOURGLASS_1.getHtml());
        } else if (SPUIDefinitions.ACTIVE.equals(activeValue)) {
            label.setDescription("Active");
            label.setStyleName("statusIconActive");
        } else if (SPUIDefinitions.IN_ACTIVE.equals(activeValue)) {
            if (endedWithError) {
                label.setStyleName("statusIconRed");
            } else {
                label.setStyleName("statusIconNeutral");
            }
            label.setDescription("In-active");
            label.setValue(FontAwesome.CHECK_CIRCLE.getHtml());
        } else {
            label.setValue("");
        }
        return label;
    }

    /**
     * Creates full sized window for action history with message.
     */
    private void createTableContentForMax() {
        setColumnCollapsingAllowed(true);
        if (!alreadyHasMessages) {
            /*
             * check to avoid DB call for fetching the messages again and again
             * if already available in container.
             */
            getcontainerData();
            // to expand parent row , if already expanded.
            expandParentRow();
            alreadyHasMessages = true;
        }

        addGeneratedColumn(SPUIDefinitions.ACTION_HIS_TBL_MSGS, new Table.ColumnGenerator() {
            private static final long serialVersionUID = 1L;

            @SuppressWarnings("unchecked")
            @Override
            public Component generateCell(final Table source, final Object itemId, final Object columnId) {
                final List<String> messages = (List<String>) hierarchicalContainer.getItem(itemId)
                        .getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_MSGS_HIDDEN).getValue();
                return createMessagesBlock(messages);
            }
        });
        setVisibleColumns(getVisbleColumns().toArray());
        setColumnExpantRatioOnTableMaximize();
    }

    private void setColumnExpantRatioOnTableMaximize() {
        /* set messages column can expand the rest of the available space */
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE, 0.1F);
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID, 0.1F);
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_STATUS, 0.1F);
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DIST, 0.2F);
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_FORCED, 0.1F);
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME, 0.1F);
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_MSGS, 0.35F);
        setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DATETIME, 0.15F);
        setColumnExpandRatio(SPUIDefinitions.ACTIONS_COLUMN, 0.2F);
    }

    /**
     * create Message block for Actions.
     *
     * @param messages
     *            as List of msg
     * @return Component as UI
     */
    protected Component createMessagesBlock(final List<String> messages) {

        final TextArea textArea = new TextArea();
        textArea.addStyleName(ValoTheme.TEXTAREA_BORDERLESS);
        textArea.addStyleName(ValoTheme.TEXTAREA_TINY);
        textArea.addStyleName("inline-icon");
        textArea.setSizeFull();
        int index = 1;
        final StringBuilder updateStatusMessages = new StringBuilder();
        if (messages != null && !messages.isEmpty()) {
            /* Messages are available */
            for (final String msg : messages) {
                updateStatusMessages.append('[').append(index).append("]: ").append(msg).append('\n');
                index++;
            }
        } else {
            /* Messages are not available */
            updateStatusMessages.append(i18n.get("message.no.available"));
        }
        textArea.setValue(updateStatusMessages.toString());
        textArea.setReadOnly(Boolean.TRUE);
        return textArea;
    }

    /**
     * Show or hide message.
     *
     * @param actionHistoryMode
     *            {@link ActionHisTableType}
     * @param childItem
     *            {@link Item}
     * @param actionStatus
     *            {@link ActionHisTableType}
     */
    @SuppressWarnings("unchecked")
    private void showOrHideMessage(final Item childItem, final ActionStatus actionStatus) {
        if (managementUIState.isActionHistoryMaximized()) {
            childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_MSGS_HIDDEN)
                    .setValue(actionStatus.getMessages());
        }
    }

    /**
     * View History Table in normal window mode.
     */
    private void normalActionHistoryTable() {
        setColumnCollapsingAllowed(false);
        managementUIState.setActionHistoryMaximized(false);
        removeGeneratedColumn(SPUIDefinitions.ACTION_HIS_TBL_MSGS);
        setVisibleColumns(getVisbleColumns().toArray());
        setColumnExpandRatioForMinimisedTable();
    }

    /**
     * Show confirmation window and if ok then only, force the action.
     *
     * @param actionId
     *            as Id if the action needs to be forced.
     */
    private void confirmAndForceAction(final Long actionId) {
        /* Display the confirmation */
        final ConfirmationDialog confirmDialog = new ConfirmationDialog(i18n.get("caption.force.action.confirmbox"),
                i18n.get("message.force.action.confirm"), i18n.get(BUTTON_OK), i18n.get(BUTTON_CANCEL), ok -> {
                    if (!ok) {
                        return;
                    }
                    deploymentManagement.forceTargetAction(actionId);
                    populateAndupdateTargetDetails(target);
                    notification.displaySuccess(i18n.get("message.force.action.success"));
                });
        UI.getCurrent().addWindow(confirmDialog.getWindow());

        confirmDialog.getWindow().bringToFront();
    }

    private void confirmAndForceQuitAction(final Long actionId) {
        /* Display the confirmation */
        final ConfirmationDialog confirmDialog = new ConfirmationDialog(
                i18n.get("caption.forcequit.action.confirmbox"), i18n.get("message.forcequit.action.confirm"),
                i18n.get(BUTTON_OK), i18n.get(BUTTON_CANCEL), ok -> {
                    if (!ok) {
                        return;
                    }
                    final boolean cancelResult = forceQuitActiveAction(actionId);
                    if (cancelResult) {
                        populateAndupdateTargetDetails(target);
                        notification.displaySuccess(i18n.get("message.forcequit.action.success"));
                    } else {
                        notification.displayValidationError(i18n.get("message.forcequit.action.failed"));
                    }
                }, FontAwesome.WARNING);
        UI.getCurrent().addWindow(confirmDialog.getWindow());

        confirmDialog.getWindow().bringToFront();
    }

    /**
     * Show confirmation window and if ok then only, cancel the action.
     *
     * @param actionId
     *            as Id if the action needs to be cancelled.
     */
    private void confirmAndCancelAction(final Long actionId) {
        if (actionId == null) {
            return;
        }

        final ConfirmationDialog confirmDialog = new ConfirmationDialog(
                i18n.get("caption.cancel.action.confirmbox"), i18n.get("message.cancel.action.confirm"),
                i18n.get(BUTTON_OK), i18n.get(BUTTON_CANCEL), ok -> {
                    if (!ok) {
                        return;
                    }
                    final boolean cancelResult = cancelActiveAction(actionId);
                    if (cancelResult) {
                        populateAndupdateTargetDetails(target);
                        notification.displaySuccess(i18n.get("message.cancel.action.success"));
                    } else {
                        notification.displayValidationError(i18n.get("message.cancel.action.failed"));
                    }
                });
        UI.getCurrent().addWindow(confirmDialog.getWindow());
        confirmDialog.getWindow().bringToFront();
    }

    private void populateAndupdateTargetDetails(final Target target) {
        // show the updated target action history details
        populateTableData(target);
        // update the target table and its pinning details
        updateTargetAndDsTable();
    }

    // service call to cancel the active action
    private boolean cancelActiveAction(final Long actionId) {
        if (actionId != null) {
            final Action activeAction = deploymentManagement.findAction(actionId);
            try {
                deploymentManagement.cancelAction(activeAction, target);
                return true;
            } catch (final CancelActionNotAllowedException e) {
                LOG.info("Cancel action not allowed exception :{}", e);
                return false;
            }
        }
        return false;
    }

    // service call to cancel the active action
    private boolean forceQuitActiveAction(final Long actionId) {
        if (actionId != null) {
            final Action activeAction = deploymentManagement.findAction(actionId);
            try {
                deploymentManagement.forceQuitAction(activeAction);
                return true;
            } catch (final CancelActionNotAllowedException e) {
                LOG.info("Force Cancel action not allowed exception :{}", e);
                return false;
            }
        }
        return false;
    }

    private void updateTargetAndDsTable() {
        eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.UPDATED_ENTITY, target));
        updateDistributionTableStyle();
    }

    /**
     * Update the colors of Assigned and installed distribution set in Target
     * Pinning.
     */
    private void updateDistributionTableStyle() {

        if (managementUIState.getDistributionTableFilters().getPinnedTargetId().isPresent()
                && null != managementUIState.getDistributionTableFilters().getPinnedTargetId().get()) {
            final String alreadyPinnedControllerId = managementUIState.getDistributionTableFilters()
                    .getPinnedTargetId().get();
            // if the current target is pinned publish a pin event again
            if (null != alreadyPinnedControllerId && alreadyPinnedControllerId.equals(target.getControllerId())) {
                eventBus.publish(this, PinUnpinEvent.PIN_TARGET);
            }
        }
    }

    /**
     * empty the container when there is no data selected in Target Table.
     */
    public void clearContainerData() {
        getContainerDataSource().removeAllItems();
    }

    /**
     * Set messages false.
     *
     * @param alreadyHasMessages
     *            the alreadyHasMessages to set
     */
    public void setAlreadyHasMessages(final boolean alreadyHasMessages) {
        this.alreadyHasMessages = alreadyHasMessages;
    }

    private void restorePreviousState() {
        if (managementUIState.isActionHistoryMaximized()) {
            createTableContentForMax();
        }
    }

    private void expandParentRow() {
        if (null != managementUIState.getExpandParentActionRowId()
                && !managementUIState.getExpandParentActionRowId().isEmpty()) {
            for (final Object obj : managementUIState.getExpandParentActionRowId()) {
                expandParentActionRow(obj);
            }
        }
    }
}