Java tutorial
/** * 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.targettable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.FilterParams; import org.eclipse.hawkbit.repository.MaintenanceScheduleHelper; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.event.remote.entity.RemoteEntityEvent; import org.eclipse.hawkbit.repository.exception.InvalidMaintenanceScheduleException; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult; import org.eclipse.hawkbit.repository.model.RepositoryModelConstants; import org.eclipse.hawkbit.repository.model.Tag; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetWithActionType; import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.UiProperties; import org.eclipse.hawkbit.ui.common.ConfirmationDialog; import org.eclipse.hawkbit.ui.common.ManagementEntityState; import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.common.confirmwindow.layout.ConfirmationTab; import org.eclipse.hawkbit.ui.common.entity.DistributionSetIdName; import org.eclipse.hawkbit.ui.common.entity.TargetIdName; import org.eclipse.hawkbit.ui.common.table.AbstractTable; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.dd.criteria.ManagementViewClientCriterion; import org.eclipse.hawkbit.ui.management.event.ManagementUIEvent; import org.eclipse.hawkbit.ui.management.event.PinUnpinEvent; import org.eclipse.hawkbit.ui.management.event.SaveActionWindowEvent; import org.eclipse.hawkbit.ui.management.event.TargetAddUpdateWindowEvent; import org.eclipse.hawkbit.ui.management.event.TargetFilterEvent; import org.eclipse.hawkbit.ui.management.event.TargetTableEvent; import org.eclipse.hawkbit.ui.management.event.TargetTableEvent.TargetComponentEvent; import org.eclipse.hawkbit.ui.management.miscs.AbstractActionTypeOptionGroupLayout.ActionTypeOption; import org.eclipse.hawkbit.ui.management.miscs.ActionTypeOptionGroupAssignmentLayout; import org.eclipse.hawkbit.ui.management.miscs.MaintenanceWindowLayout; import org.eclipse.hawkbit.ui.management.state.ManagementUIState; import org.eclipse.hawkbit.ui.management.state.TargetTableFilters; import org.eclipse.hawkbit.ui.push.CancelTargetAssignmentEventContainer; import org.eclipse.hawkbit.ui.push.TargetUpdatedEventContainer; import org.eclipse.hawkbit.ui.utils.AssignInstalledDSTooltipGenerator; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.eclipse.hawkbit.ui.utils.TableColumn; import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider; import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory; import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer; import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition; import org.vaadin.spring.events.EventBus.UIEventBus; import org.vaadin.spring.events.EventScope; import org.vaadin.spring.events.annotation.EventBusListenerMethod; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.vaadin.data.Container; import com.vaadin.data.Item; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; import com.vaadin.server.FontAwesome; import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.CheckBox; import com.vaadin.ui.DragAndDropWrapper; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Link; import com.vaadin.ui.Table; import com.vaadin.ui.UI; import com.vaadin.ui.themes.ValoTheme; /** * Concrete implementation of Target table which is displayed on the Deployment * View. */ public class TargetTable extends AbstractTable<Target> { private static final long serialVersionUID = 1L; private static final Logger LOG = LoggerFactory.getLogger(TargetTable.class); private static final String TARGET_PINNED = "targetPinned"; private static final int PROPERTY_DEPT = 3; private final transient TargetManagement targetManagement; private final transient DistributionSetManagement distributionSetManagement; private final transient TargetTagManagement tagManagement; private final transient DeploymentManagement deploymentManagement; private final ManagementViewClientCriterion managementViewClientCriterion; private final ManagementUIState managementUIState; private Button targetPinnedBtn; private boolean targetPinned; private final UiProperties uiProperties; private ConfirmationDialog confirmDialog; private final ActionTypeOptionGroupAssignmentLayout actionTypeOptionGroupLayout; private final MaintenanceWindowLayout maintenanceWindowLayout; public TargetTable(final UIEventBus eventBus, final VaadinMessageSource i18n, final UINotification notification, final TargetManagement targetManagement, final ManagementUIState managementUIState, final SpPermissionChecker permChecker, final ManagementViewClientCriterion managementViewClientCriterion, final DistributionSetManagement distributionSetManagement, final TargetTagManagement tagManagement, final DeploymentManagement deploymentManagement, final UiProperties uiProperties) { super(eventBus, i18n, notification, permChecker); this.targetManagement = targetManagement; this.managementViewClientCriterion = managementViewClientCriterion; this.managementUIState = managementUIState; this.distributionSetManagement = distributionSetManagement; this.tagManagement = tagManagement; this.deploymentManagement = deploymentManagement; this.uiProperties = uiProperties; this.actionTypeOptionGroupLayout = new ActionTypeOptionGroupAssignmentLayout(i18n); this.maintenanceWindowLayout = new MaintenanceWindowLayout(i18n); setItemDescriptionGenerator(new AssignInstalledDSTooltipGenerator()); addNewContainerDS(); setColumnProperties(); setDataAvailable(getContainerDataSource().size() != 0); } @EventBusListenerMethod(scope = EventScope.UI) void onCancelTargetAssignmentEvents(final CancelTargetAssignmentEventContainer eventContainer) { // workaround until push is available for action // history, re-select // the updated target so the action history gets // refreshed. publishTargetSelectedEntityForRefresh(eventContainer.getEvents().stream()); } @EventBusListenerMethod(scope = EventScope.UI) void onTargetUpdatedEvents(final TargetUpdatedEventContainer eventContainer) { @SuppressWarnings("unchecked") final List<Long> visibleItemIds = (List<Long>) getVisibleItemIds(); if (isFilterEnabled()) { refreshTargets(); } else { eventContainer.getEvents().stream().filter(event -> visibleItemIds.contains(event.getEntityId())) .filter(Objects::nonNull).forEach(event -> updateVisibleItemOnEvent(event.getEntity())); } publishTargetSelectedEntityForRefresh(eventContainer.getEvents().stream()); } private void publishTargetSelectedEntityForRefresh( final Stream<? extends RemoteEntityEvent<Target>> targetEntityEventStream) { targetEntityEventStream.filter(event -> isLastSelectedTarget(event.getEntityId())).filter(Objects::nonNull) .findAny().ifPresent(event -> getEventBus().publish(this, new TargetTableEvent(BaseEntityEventType.SELECTED_ENTITY, event.getEntity()))); } @EventBusListenerMethod(scope = EventScope.UI) void onEvent(final PinUnpinEvent pinUnpinEvent) { UI.getCurrent().access(() -> { if (pinUnpinEvent == PinUnpinEvent.PIN_DISTRIBUTION) { refreshFilter(); styleTargetTableOnPinning(); } else if (pinUnpinEvent == PinUnpinEvent.UNPIN_DISTRIBUTION) { refreshFilter(); restoreTargetTableStyle(); } }); } @EventBusListenerMethod(scope = EventScope.UI) void addOrEditEvent(final TargetAddUpdateWindowEvent targetUIEvent) { if (BaseEntityEventType.UPDATED_ENTITY != targetUIEvent.getEventType()) { return; } UI.getCurrent().access(() -> updateTarget(targetUIEvent.getEntity())); } @EventBusListenerMethod(scope = EventScope.UI) void onEvent(final TargetFilterEvent filterEvent) { UI.getCurrent().access(() -> { if (checkFilterEvent(filterEvent)) { refreshFilter(); getEventBus().publish(this, ManagementUIEvent.TARGET_TABLE_FILTER); } }); } @EventBusListenerMethod(scope = EventScope.UI) void onEvent(final ManagementUIEvent managementUIEvent) { UI.getCurrent().access(() -> { if (managementUIEvent == ManagementUIEvent.UNASSIGN_TARGET_TAG || managementUIEvent == ManagementUIEvent.ASSIGN_TARGET_TAG) { refreshFilter(); } }); } @EventBusListenerMethod(scope = EventScope.UI) void onEvent(final SaveActionWindowEvent event) { if (event == SaveActionWindowEvent.SAVED_ASSIGNMENTS) { refreshContainer(); } } @EventBusListenerMethod(scope = EventScope.UI) void onEvent(final TargetTableEvent event) { onBaseEntityEvent(event); } @Override protected String getTableId() { return UIComponentIdProvider.TARGET_TABLE_ID; } @Override protected Container createContainer() { // ADD all the filters to the query config final Map<String, Object> queryConfig = prepareQueryConfigFilters(); // Create TargetBeanQuery factory with the query config. final BeanQueryFactory<TargetBeanQuery> targetQF = new BeanQueryFactory<>(TargetBeanQuery.class); targetQF.setQueryConfiguration(queryConfig); // create lazy query container with lazy defination and query final LazyQueryContainer targetTableContainer = new LazyQueryContainer( new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, SPUILabelDefinitions.VAR_ID), targetQF); targetTableContainer.getQueryView().getQueryDefinition().setMaxNestedPropertyDepth(PROPERTY_DEPT); return targetTableContainer; } @Override protected void addContainerProperties(final Container container) { final LazyQueryContainer targetTableContainer = (LazyQueryContainer) container; targetTableContainer.addContainerProperty(SPUILabelDefinitions.VAR_CONT_ID, String.class, "", false, false); targetTableContainer.addContainerProperty(SPUILabelDefinitions.VAR_NAME, String.class, "", false, true); targetTableContainer.addContainerProperty(SPUILabelDefinitions.VAR_TARGET_STATUS, TargetUpdateStatus.class, TargetUpdateStatus.UNKNOWN, false, false); targetTableContainer.addContainerProperty(SPUILabelDefinitions.ASSIGNED_DISTRIBUTION_ID, Long.class, null, false, false); targetTableContainer.addContainerProperty(SPUILabelDefinitions.INSTALLED_DISTRIBUTION_ID, Long.class, null, false, false); targetTableContainer.addContainerProperty(SPUILabelDefinitions.ASSIGNED_DISTRIBUTION_NAME_VER, String.class, "", false, true); targetTableContainer.addContainerProperty(SPUILabelDefinitions.INSTALLED_DISTRIBUTION_NAME_VER, String.class, "", false, true); targetTableContainer.addContainerProperty(SPUILabelDefinitions.LAST_QUERY_DATE, Date.class, null, false, false); targetTableContainer.addContainerProperty(SPUILabelDefinitions.VAR_CREATED_BY, String.class, null, false, true); targetTableContainer.addContainerProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_BY, String.class, null, false, true); targetTableContainer.addContainerProperty(SPUILabelDefinitions.VAR_CREATED_DATE, String.class, null, false, true); targetTableContainer.addContainerProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE, String.class, null, false, true); targetTableContainer.addContainerProperty(SPUILabelDefinitions.VAR_POLL_STATUS_TOOL_TIP, String.class, null, false, true); targetTableContainer.addContainerProperty(SPUILabelDefinitions.VAR_DESC, String.class, "", false, true); targetTableContainer.addContainerProperty(SPUILabelDefinitions.ASSIGN_DIST_SET, DistributionSet.class, null, false, true); targetTableContainer.addContainerProperty(SPUILabelDefinitions.INSTALL_DIST_SET, DistributionSet.class, null, false, true); } @Override protected void addCustomGeneratedColumns() { addGeneratedColumn(SPUIDefinitions.TARGET_STATUS_PIN_TOGGLE_ICON, (source, itemId, columnId) -> getTagetPinButton(itemId)); addGeneratedColumn(SPUIDefinitions.TARGET_STATUS_POLL_TIME, (source, itemId, columnId) -> getTargetPollTime(itemId)); } @Override protected Object getItemIdToSelect() { return managementUIState.getSelectedTargetId().isEmpty() ? null : managementUIState.getSelectedTargetId(); } @Override protected void publishSelectedEntityEvent(final Target selectedLastEntity) { getEventBus().publish(this, new TargetTableEvent(BaseEntityEventType.SELECTED_ENTITY, selectedLastEntity)); } @Override protected void setLastSelectedEntityId(final Long selectedLastEntityId) { managementUIState.setLastSelectedTargetId(selectedLastEntityId); } @Override protected Optional<Target> findEntityByTableValue(final Long lastSelectedId) { return targetManagement.get(lastSelectedId); } @Override protected void setManagementEntityStateValues(final Set<Long> values, final Long lastId) { managementUIState.setSelectedTargetId(values); managementUIState.setLastSelectedTargetId(lastId); } @Override protected ManagementEntityState getManagementEntityState() { return null; } @Override protected boolean isMaximized() { return managementUIState.isTargetTableMaximized(); } @Override protected List<TableColumn> getTableVisibleColumns() { final List<TableColumn> columnList = super.getTableVisibleColumns(); if (!isMaximized()) { columnList.add(new TableColumn(SPUIDefinitions.TARGET_STATUS_POLL_TIME, "", 0.0F)); columnList.add(new TableColumn(SPUIDefinitions.TARGET_STATUS_PIN_TOGGLE_ICON, "", 0.0F)); } return columnList; } @Override public AcceptCriterion getDropAcceptCriterion() { return managementViewClientCriterion; } private Map<String, Object> prepareQueryConfigFilters() { final Map<String, Object> queryConfig = Maps.newHashMapWithExpectedSize(7); managementUIState.getTargetTableFilters().getSearchText().ifPresent( value -> queryConfig.put(SPUIDefinitions.FILTER_BY_TEXT, value)); managementUIState.getTargetTableFilters().getDistributionSet().ifPresent( value -> queryConfig.put(SPUIDefinitions.FILTER_BY_DISTRIBUTION, value.getId())); managementUIState.getTargetTableFilters().getPinnedDistId().ifPresent( value -> queryConfig.put(SPUIDefinitions.ORDER_BY_DISTRIBUTION, value)); managementUIState.getTargetTableFilters().getTargetFilterQuery().ifPresent( value -> queryConfig.put(SPUIDefinitions.FILTER_BY_TARGET_FILTER_QUERY, value)); queryConfig.put(SPUIDefinitions.FILTER_BY_NO_TAG, managementUIState.getTargetTableFilters().isNoTagSelected()); if ( isFilteredByTags()) { final List<String> list = new ArrayList<>(); list.addAll(managementUIState.getTargetTableFilters().getClickedTargetTags()); queryConfig.put(SPUIDefinitions.FILTER_BY_TAG, list.toArray(new String[list.size()])); } if (isFilteredByStatus()) { final List<TargetUpdateStatus> statusList = managementUIState.getTargetTableFilters() .getClickedStatusTargetTags(); queryConfig.put(SPUIDefinitions.FILTER_BY_STATUS, statusList); } if (managementUIState.getTargetTableFilters().isOverdueFilterEnabled()) { queryConfig.put(SPUIDefinitions.FILTER_BY_OVERDUE_STATE, Boolean.TRUE); } return queryConfig; } private Label getTargetPollTime(final Object itemId) { final Label statusLabel = new Label(); statusLabel.addStyleName(ValoTheme.LABEL_SMALL); statusLabel.setHeightUndefined(); statusLabel.setContentMode(ContentMode.HTML); final String pollStatusToolTip = (String) getContainerDataSource().getItem(itemId) .getItemProperty(SPUILabelDefinitions.VAR_POLL_STATUS_TOOL_TIP).getValue(); if (StringUtils.hasText(pollStatusToolTip)) { statusLabel.setValue(FontAwesome.EXCLAMATION_CIRCLE.getHtml()); statusLabel.setDescription(pollStatusToolTip); } else { statusLabel.setValue(FontAwesome.CLOCK_O.getHtml()); statusLabel.setDescription(getI18n().getMessage(UIMessageIdProvider.TOOLTIP_IN_TIME)); } return statusLabel; } private Button getTagetPinButton(final Object itemId) { final Button pinBtn = new Button(); final String controllerId = (String) getContainerDataSource().getItem(itemId) .getItemProperty(SPUILabelDefinitions.VAR_CONT_ID).getValue(); final TargetIdName pinnedTarget = new TargetIdName((Long) itemId, controllerId); final StringBuilder pinBtnStyle = new StringBuilder(ValoTheme.BUTTON_BORDERLESS_COLORED); pinBtnStyle.append(' '); pinBtnStyle.append(ValoTheme.BUTTON_SMALL); pinBtnStyle.append(' '); pinBtnStyle.append(ValoTheme.BUTTON_ICON_ONLY); pinBtn.setStyleName(pinBtnStyle.toString()); pinBtn.setHeightUndefined(); pinBtn.setData(pinnedTarget); pinBtn.setId(UIComponentIdProvider.TARGET_PIN_ICON + controllerId); pinBtn.addClickListener(this::addPinClickListener); pinBtn.setDescription(getI18n().getMessage(UIMessageIdProvider.TOOLTIP_TARGET_PIN)); if (isPinned(pinnedTarget)) { pinBtn.addStyleName(TARGET_PINNED); targetPinned = Boolean.TRUE; targetPinnedBtn = pinBtn; getEventBus().publish(this, PinUnpinEvent.PIN_TARGET); } pinBtn.addStyleName(SPUIStyleDefinitions.TARGET_STATUS_PIN_TOGGLE); HawkbitCommonUtil.applyStatusLblStyle(this, pinBtn, itemId); return pinBtn; } private boolean isPinned(final TargetIdName target) { return managementUIState.getDistributionTableFilters().getPinnedTarget() .map(pinnedTarget -> pinnedTarget.equals(target)).orElse(false); } private void addPinClickListener(final ClickEvent event) { checkifAlreadyPinned(event.getButton()); if (targetPinned) { pinTarget(event.getButton()); } else { unPinTarget(event.getButton()); } } private void checkifAlreadyPinned(final Button eventBtn) { final TargetIdName newPinnedTargetItemId = (TargetIdName) eventBtn.getData(); final TargetIdName targetId = managementUIState.getDistributionTableFilters().getPinnedTarget() .orElse(null); if (targetId == null) { targetPinned = !targetPinned; managementUIState.getDistributionTableFilters().setPinnedTarget(newPinnedTargetItemId); } else if (targetId.equals(newPinnedTargetItemId)) { targetPinned = Boolean.FALSE; } else { targetPinned = true; managementUIState.getDistributionTableFilters().setPinnedTarget(newPinnedTargetItemId); if (null != targetPinnedBtn) { resetPinStyle(targetPinnedBtn); } } targetPinnedBtn = eventBtn; } private void pinTarget(final Button eventBtn) { /* if distribution set is pinned ,unpin target if pinned */ managementUIState.getTargetTableFilters().setPinnedDistId(null); /* on unpin of target dist table should refresh Dist table restyle */ getEventBus().publish(this, PinUnpinEvent.PIN_TARGET); /* change target table styling */ styleTargetTable(); eventBtn.addStyleName(TARGET_PINNED); targetPinned = Boolean.FALSE; } private void unPinTarget(final Button eventBtn) { managementUIState.getDistributionTableFilters().setPinnedTarget(null); getEventBus().publish(this, PinUnpinEvent.UNPIN_TARGET); resetPinStyle(eventBtn); } private void resetPinStyle(final Button pinBtn) { pinBtn.removeStyleName(TARGET_PINNED); pinBtn.addStyleName(SPUIStyleDefinitions.TARGET_STATUS_PIN_TOGGLE); final TargetIdName targetIdname = (TargetIdName) pinBtn.getData(); HawkbitCommonUtil.applyStatusLblStyle(this, pinBtn, targetIdname.getTargetId()); } private void styleTargetTable() { setCellStyleGenerator((source, itemId, propertyId) -> null); } @Override protected void onDropEventFromTable(final DragAndDropEvent event) { assignDsToTarget(event); } @Override protected void onDropEventFromWrapper(final DragAndDropEvent event) { if (isNoTagAssigned(event)) { tagAssignment(event); } } private Boolean isNoTagAssigned(final DragAndDropEvent event) { final String tagName = ((DragAndDropWrapper) (event.getTransferable().getSourceComponent())).getData() .toString(); if (tagName.equals(getI18n().getMessage(UIMessageIdProvider.CAPTION_TARGET_TAG))) { getNotification().displayValidationError(getI18n().getMessage("message.tag.cannot.be.assigned", getI18n().getMessage("label.no.tag.assigned"))); return false; } return true; } private void tagAssignment(final DragAndDropEvent event) { final List<Long> targetList = getDraggedTargetList(event).stream().collect(Collectors.toList()); final String targTagName = HawkbitCommonUtil.removePrefix( event.getTransferable().getSourceComponent().getId(), SPUIDefinitions.TARGET_TAG_ID_PREFIXS); if (targetList.isEmpty()) { final String actionDidNotWork = getI18n().getMessage("message.action.did.not.work"); getNotification().displayValidationError(actionDidNotWork); return; } final TargetTagAssignmentResult result = toggleTagAssignment(targetList, targTagName); final List<String> tagsClickedList = managementUIState.getTargetTableFilters().getClickedTargetTags(); if (result.getUnassigned() >= 1 && !tagsClickedList.isEmpty()) { refreshFilter(); } } /** * Toggles {@link TargetTag} assignment to given target ids by means that if * some (or all) of the targets in the list have the {@link Tag} not yet * assigned, they will be. If all of theme have the tag already assigned * they will be removed instead. Additionally a success popup is shown. * * @param targetIds * to toggle for * @param targTagName * to toggle * @return TagAssigmentResult with all meta data of the assignment outcome. */ public TargetTagAssignmentResult toggleTagAssignment(final Collection<Long> targetIds, final String targTagName) { final List<String> controllerIds = targetManagement.get(targetIds).stream().map(Target::getControllerId) .collect(Collectors.toList()); if (controllerIds.isEmpty()) { getNotification().displayWarning(getI18n().getMessage("targets.not.exists")); return new TargetTagAssignmentResult(0, 0, 0, Lists.newArrayListWithCapacity(0), Lists.newArrayListWithCapacity(0), null); } final Optional<TargetTag> tag = tagManagement.getByName(targTagName); if (!tag.isPresent()) { getNotification().displayWarning(getI18n().getMessage("targettag.not.exists", targTagName)); return new TargetTagAssignmentResult(0, 0, 0, Lists.newArrayListWithCapacity(0), Lists.newArrayListWithCapacity(0), null); } final TargetTagAssignmentResult result = targetManagement.toggleTagAssignment(controllerIds, targTagName); getNotification().displaySuccess(HawkbitCommonUtil.createAssignmentMessage(targTagName, result, getI18n())); return result; } @Override protected boolean validateDragAndDropWrapper(final DragAndDropWrapper wrapperSource) { final String tagName = HawkbitCommonUtil.removePrefix(wrapperSource.getId(), SPUIDefinitions.TARGET_TAG_ID_PREFIXS); if (wrapperSource.getId().startsWith(SPUIDefinitions.TARGET_TAG_ID_PREFIXS)) { if (getI18n().getMessage("label.no.tag").equals(tagName)) { getNotification().displayValidationError( getI18n().getMessage(UIMessageIdProvider.MESSAGE_ACTION_NOT_ALLOWED)); return false; } } else { getNotification() .displayValidationError(getI18n().getMessage(UIMessageIdProvider.MESSAGE_ACTION_NOT_ALLOWED)); return false; } return true; } @Override protected String getDropTableId() { return UIComponentIdProvider.DIST_TABLE_ID; } @Override protected List<String> hasMissingPermissionsForDrop() { return getPermChecker().hasUpdateTargetPermission() ? Collections.emptyList() : Arrays.asList(SpPermission.UPDATE_TARGET); } /** * To update target details in the table. * * @param updatedTarget * as reference */ @SuppressWarnings("unchecked") public void updateTarget(final Target updatedTarget) { if (updatedTarget != null) { final Item item = getItem(updatedTarget.getId()); // TO DO update SPUILabelDefinitions.ASSIGNED_DISTRIBUTION_NAME_VER // & // SPUILabelDefinitions.ASSIGNED_DISTRIBUTION_NAME_VER /* * Update the status which will trigger the value change lister * registered for the target update status. That listener will * update the new status icon showing for this target in the table. */ item.getItemProperty(SPUILabelDefinitions.VAR_TARGET_STATUS).setValue(updatedTarget.getUpdateStatus()); /* * Update the last query which will trigger the value change lister * registered for the target last query column. That listener will * update the latest query date for this target in the tooltip. */ item.getItemProperty(SPUILabelDefinitions.LAST_QUERY_DATE).setValue(updatedTarget.getLastTargetQuery()); item.getItemProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_BY) .setValue(UserDetailsFormatter.loadAndFormatLastModifiedBy(updatedTarget)); item.getItemProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE) .setValue(SPDateTimeUtil.getFormattedDate(updatedTarget.getLastModifiedAt())); item.getItemProperty(SPUILabelDefinitions.VAR_DESC).setValue(updatedTarget.getDescription()); /* Update the new Name, Description and poll date */ item.getItemProperty(SPUILabelDefinitions.VAR_NAME).setValue(updatedTarget.getName()); } } private static boolean checkFilterEvent(final TargetFilterEvent filterEvent) { return isNormalFilter(filterEvent) || isRemoveFilterEvent(filterEvent) || isStatusFilterEvent(filterEvent); } private static boolean isStatusFilterEvent(final TargetFilterEvent filterEvent) { return filterEvent == TargetFilterEvent.FILTER_BY_STATUS || filterEvent == TargetFilterEvent.REMOVE_FILTER_BY_STATUS; } private static boolean isRemoveFilterEvent(final TargetFilterEvent filterEvent) { return filterEvent == TargetFilterEvent.REMOVE_FILTER_BY_TEXT || filterEvent == TargetFilterEvent.REMOVE_FILTER_BY_TAG || filterEvent == TargetFilterEvent.REMOVE_FILTER_BY_DISTRIBUTION || filterEvent == TargetFilterEvent.REMOVE_FILTER_BY_TARGET_FILTER_QUERY; } private static boolean isNormalFilter(final TargetFilterEvent filterEvent) { return filterEvent == TargetFilterEvent.FILTER_BY_TEXT || filterEvent == TargetFilterEvent.FILTER_BY_TAG || filterEvent == TargetFilterEvent.FILTER_BY_DISTRIBUTION || filterEvent == TargetFilterEvent.FILTER_BY_TARGET_FILTER_QUERY; } private String getTargetTableStyle(final Long assignedDistributionSetId, final Long installedDistributionSetId) { return managementUIState.getTargetTableFilters().getPinnedDistId().map(distPinned -> { if (distPinned.equals(installedDistributionSetId)) { return SPUIDefinitions.HIGHLIGHT_GREEN; } if (distPinned.equals(assignedDistributionSetId)) { return SPUIDefinitions.HIGHLIGHT_ORANGE; } return null; }).orElse(null); } private String createTargetTableStyle(final Object itemId, final Object propertyId) { if (propertyId == null) { final Item item = getItem(itemId); final Long assignedDistributionSetId = (Long) item .getItemProperty(SPUILabelDefinitions.ASSIGNED_DISTRIBUTION_ID).getValue(); final Long installedDistributionSetId = (Long) item .getItemProperty(SPUILabelDefinitions.INSTALLED_DISTRIBUTION_ID).getValue(); return getTargetTableStyle(assignedDistributionSetId, installedDistributionSetId); } return null; } private void styleTargetTableOnPinning() { setCellStyleGenerator(new Table.CellStyleGenerator() { private static final long serialVersionUID = 1L; @Override public String getStyle(final Table source, final Object itemId, final Object propertyId) { return createTargetTableStyle(itemId, propertyId); } }); } private void restoreTargetTableStyle() { setCellStyleGenerator(new Table.CellStyleGenerator() { private static final long serialVersionUID = 1L; @Override public String getStyle(final Table source, final Object itemId, final Object propertyId) { return null; } }); } private void refreshTargets() { final LazyQueryContainer targetContainer = (LazyQueryContainer) getContainerDataSource(); final int size = targetContainer.size(); if (size < SPUIDefinitions.MAX_TABLE_ENTRIES) { super.refreshContainer(); } else { // If table is not refreshed , explicitly target total count and // truncated count has to be updated resetTargetCountDetails(); } if (size != 0) { setData(getI18n().getMessage(UIMessageIdProvider.MESSAGE_DATA_AVAILABLE)); } getEventBus().publish(this, new TargetTableEvent(TargetComponentEvent.REFRESH_TARGETS)); } @Override public void refreshContainer() { super.refreshContainer(); getEventBus().publish(this, new TargetTableEvent(TargetComponentEvent.REFRESH_TARGETS)); } @SuppressWarnings("unchecked") private void updateVisibleItemOnEvent(final Target target) { final Long targetId = target.getId(); final LazyQueryContainer targetContainer = (LazyQueryContainer) getContainerDataSource(); final Item item = targetContainer.getItem(targetId); item.getItemProperty(SPUILabelDefinitions.VAR_TARGET_STATUS).setValue(target.getUpdateStatus()); item.getItemProperty(SPUILabelDefinitions.VAR_NAME).setValue(target.getName()); item.getItemProperty(SPUILabelDefinitions.VAR_POLL_STATUS_TOOL_TIP) .setValue(HawkbitCommonUtil.getPollStatusToolTip(target.getPollStatus(), getI18n())); } private boolean isLastSelectedTarget(final Long targetId) { final Optional<Long> currentTargetId = managementUIState.getLastSelectedTargetId(); return currentTargetId.isPresent() && currentTargetId.get().equals(targetId); } private boolean isFilterEnabled() { final TargetTableFilters targetTableFilters = managementUIState.getTargetTableFilters(); return targetTableFilters.getSearchText().isPresent() || !targetTableFilters.getClickedTargetTags().isEmpty() || !targetTableFilters.getClickedStatusTargetTags().isEmpty() || targetTableFilters.getTargetFilterQuery().isPresent(); } /** * Select all rows in the table. */ @Override public void selectAll() { // As Vaadin Table only returns the current ItemIds which are visible // you don't need to search explicit for them. setValue(getItemIds()); } @Override protected void setDataAvailable(final boolean available) { managementUIState.setNoDataAvailableTarget(!available); } /** * Set total target count and count of targets truncated in target table. */ private void resetTargetCountDetails() { final long totalTargetsCount = getTotalTargetsCount(); managementUIState.setTargetsCountAll(totalTargetsCount); final boolean noTagClicked = managementUIState.getTargetTableFilters().isNoTagSelected(); final Long distributionId = managementUIState.getTargetTableFilters().getDistributionSet() .map(DistributionSetIdName::getId).orElse(null); final Long pinnedDistId = managementUIState.getTargetTableFilters().getPinnedDistId().orElse(null); final String searchText = managementUIState.getTargetTableFilters().getSearchText().map(text -> { if (StringUtils.isEmpty(text)) { return null; } return String.format("%%%s%%", text); }).orElse(null); String[] targetTags = null; if (isFilteredByTags()) { targetTags = managementUIState.getTargetTableFilters().getClickedTargetTags().toArray(new String[0]); } Collection<TargetUpdateStatus> status = null; if (isFilteredByStatus()) { status = managementUIState.getTargetTableFilters().getClickedStatusTargetTags(); } Boolean overdueState = null; if (managementUIState.getTargetTableFilters().isOverdueFilterEnabled()) { overdueState = managementUIState.getTargetTableFilters().isOverdueFilterEnabled(); } final long size = getTargetsCountWithFilter(totalTargetsCount, pinnedDistId, new FilterParams(status, overdueState, searchText, distributionId, noTagClicked, targetTags)); if (size > SPUIDefinitions.MAX_TABLE_ENTRIES) { managementUIState.setTargetsTruncated(size - SPUIDefinitions.MAX_TABLE_ENTRIES); } } private long getTargetsCountWithFilter(final long totalTargetsCount, final Long pinnedDistId, final FilterParams filterParams) { final Optional<Long> query = managementUIState.getTargetTableFilters().getTargetFilterQuery(); final long size; if (query.isPresent()) { size = targetManagement.countByTargetFilterQuery(query.get()); } else if (noFilterSelected(filterParams.getFilterByStatus(), pinnedDistId, filterParams.getSelectTargetWithNoTag(), filterParams.getFilterByTagNames(), filterParams.getFilterBySearchText())) { size = totalTargetsCount; } else { size = targetManagement.countByFilters(filterParams.getFilterByStatus(), filterParams.getOverdueState(), filterParams.getFilterBySearchText(), filterParams.getFilterByDistributionId(), filterParams.getSelectTargetWithNoTag(), filterParams.getFilterByTagNames()); } return size; } private static boolean noFilterSelected(final Collection<TargetUpdateStatus> status, final Long distributionId, final Boolean noTagClicked, final String[] targetTags, final String searchText) { return CollectionUtils.isEmpty(status) && distributionId == null && StringUtils.isEmpty(searchText) && !isTagSelected(targetTags, noTagClicked); } private static Boolean isTagSelected(final String[] targetTags, final Boolean noTagClicked) { return targetTags == null && !noTagClicked; } private long getTotalTargetsCount() { return targetManagement.count(); } private boolean isFilteredByStatus() { return !managementUIState.getTargetTableFilters().getClickedStatusTargetTags().isEmpty(); } private boolean isFilteredByTags() { return !managementUIState.getTargetTableFilters().getClickedTargetTags().isEmpty(); } // Code for assignment start private void saveAllAssignments() { final Set<TargetIdName> itemIds = managementUIState.getAssignedList().keySet(); Long distId; List<TargetIdName> targetIdSetList; List<TargetIdName> tempIdList; final ActionType actionType = ((ActionTypeOption) actionTypeOptionGroupLayout.getActionTypeOptionGroup() .getValue()).getActionType(); final long forcedTimeStamp = (((ActionTypeOption) actionTypeOptionGroupLayout.getActionTypeOptionGroup() .getValue()) == ActionTypeOption.AUTO_FORCED) ? actionTypeOptionGroupLayout.getForcedTimeDateField().getValue().getTime() : RepositoryModelConstants.NO_FORCE_TIME; final Map<Long, List<TargetIdName>> saveAssignedList = Maps.newHashMapWithExpectedSize(itemIds.size()); for (final TargetIdName itemId : itemIds) { final DistributionSetIdName distitem = managementUIState.getAssignedList().get(itemId); distId = distitem.getId(); if (saveAssignedList.containsKey(distId)) { targetIdSetList = saveAssignedList.get(distId); } else { targetIdSetList = new ArrayList<>(); } targetIdSetList.add(itemId); saveAssignedList.put(distId, targetIdSetList); } final String maintenanceSchedule = maintenanceWindowLayout.getMaintenanceSchedule(); final String maintenanceDuration = maintenanceWindowLayout.getMaintenanceDuration(); final String maintenanceTimeZone = maintenanceWindowLayout.getMaintenanceTimeZone(); for (final Map.Entry<Long, List<TargetIdName>> mapEntry : saveAssignedList.entrySet()) { tempIdList = saveAssignedList.get(mapEntry.getKey()); final DistributionSetAssignmentResult distributionSetAssignmentResult = deploymentManagement .assignDistributionSet(mapEntry.getKey(), tempIdList.stream().map(t -> maintenanceWindowLayout.isEnabled() ? new TargetWithActionType(t.getControllerId(), actionType, forcedTimeStamp, maintenanceSchedule, maintenanceDuration, maintenanceTimeZone) : new TargetWithActionType(t.getControllerId(), actionType, forcedTimeStamp)) .collect(Collectors.toList())); if (distributionSetAssignmentResult.getAssigned() > 0) { getNotification().displaySuccess(getI18n().getMessage("message.target.assignment", distributionSetAssignmentResult.getAssigned())); } if (distributionSetAssignmentResult.getAlreadyAssigned() > 0) { getNotification().displaySuccess(getI18n().getMessage("message.target.alreadyAssigned", distributionSetAssignmentResult.getAlreadyAssigned())); } } resfreshPinnedDetails(saveAssignedList); managementUIState.getAssignedList().clear(); getNotification().displaySuccess(getI18n().getMessage("message.target.ds.assign.success")); getEventBus().publish(this, SaveActionWindowEvent.SAVED_ASSIGNMENTS); } private void resfreshPinnedDetails(final Map<Long, List<TargetIdName>> saveAssignedList) { final Optional<Long> pinnedDist = managementUIState.getTargetTableFilters().getPinnedDistId(); final Optional<TargetIdName> pinnedTarget = managementUIState.getDistributionTableFilters() .getPinnedTarget(); if (pinnedDist.isPresent()) { if (saveAssignedList.keySet().contains(pinnedDist.get())) { getEventBus().publish(this, PinUnpinEvent.PIN_DISTRIBUTION); } } else if (pinnedTarget.isPresent()) { final Set<TargetIdName> assignedTargetIds = managementUIState.getAssignedList().keySet(); if (assignedTargetIds.contains(pinnedTarget.get())) { getEventBus().publish(this, PinUnpinEvent.PIN_TARGET); } } } private boolean isMaintenanceWindowValid() { if (maintenanceWindowLayout.isEnabled()) { try { MaintenanceScheduleHelper.validateMaintenanceSchedule( maintenanceWindowLayout.getMaintenanceSchedule(), maintenanceWindowLayout.getMaintenanceDuration(), maintenanceWindowLayout.getMaintenanceTimeZone()); } catch (final InvalidMaintenanceScheduleException e) { LOG.error("Maintenance window is not valid", e); getNotification().displayValidationError(e.getMessage()); return false; } } return true; } private void assignDsToTarget(final DragAndDropEvent event) { final TableTransferable transferable = (TableTransferable) event.getTransferable(); final AbstractTable<?> source = (AbstractTable<?>) transferable.getSourceComponent(); final Set<Long> ids = source.getSelectedEntitiesByTransferable(transferable); // only one distribution can be assigned to a target final Long idToSelect = ids.iterator().next(); selectDraggedEntities(source, new HashSet<>(Arrays.asList(idToSelect))); final AbstractSelectTargetDetails dropData = (AbstractSelectTargetDetails) event.getTargetDetails(); final Object targetItemId = dropData.getItemIdOver(); LOG.debug("Adding a log to check if targetItemId is null : {} ", targetItemId); if (targetItemId == null) { getNotification().displayWarning(getI18n().getMessage(TARGETS_NOT_EXISTS, "")); return; } final Long targetId = (Long) targetItemId; selectDroppedEntities(targetId); final Optional<Target> target = targetManagement.get(targetId); if (!target.isPresent()) { getNotification().displayWarning(getI18n().getMessage(TARGETS_NOT_EXISTS, "")); return; } final TargetIdName createTargetIdName = new TargetIdName(target.get()); final List<DistributionSet> findDistributionSetById = distributionSetManagement .get(new HashSet<>(Arrays.asList(idToSelect))); if (findDistributionSetById.isEmpty()) { getNotification().displayWarning(getI18n().getMessage(DISTRIBUTIONSET_NOT_EXISTS)); return; } final DistributionSet distributionSetToAssign = findDistributionSetById.get(0); addNewTargetToAssignmentList(createTargetIdName, distributionSetToAssign); openConfirmationWindowForAssignment(distributionSetToAssign.getName(), createTargetIdName.getTargetName()); } private void openConfirmationWindowForAssignment(final String distributionNameToAssign, final String targetName) { confirmDialog = new ConfirmationDialog(getI18n().getMessage(CAPTION_ENTITY_ASSIGN_ACTION_CONFIRMBOX), getI18n().getMessage(MESSAGE_CONFIRM_ASSIGN_ENTITY, distributionNameToAssign, "target", targetName), getI18n().getMessage(UIMessageIdProvider.BUTTON_OK), getI18n().getMessage(UIMessageIdProvider.BUTTON_CANCEL), ok -> { if (ok && isMaintenanceWindowValid()) { saveAllAssignments(); } else { managementUIState.getAssignedList().clear(); } }, createAssignmentTab(), UIComponentIdProvider.DIST_SET_TO_TARGET_ASSIGNMENT_CONFIRM_ID); UI.getCurrent().addWindow(confirmDialog.getWindow()); confirmDialog.getWindow().bringToFront(); } private ConfirmationTab createAssignmentTab() { final ConfirmationTab assignmentTab = new ConfirmationTab(); actionTypeOptionGroupLayout.selectDefaultOption(); assignmentTab.addComponent(actionTypeOptionGroupLayout); assignmentTab.addComponent(enableMaintenanceWindowLayout()); initMaintenanceWindow(); assignmentTab.addComponent(maintenanceWindowLayout); return assignmentTab; } private HorizontalLayout enableMaintenanceWindowLayout() { final HorizontalLayout layout = new HorizontalLayout(); layout.addComponent(enableMaintenanceWindowControl()); layout.addComponent(maintenanceWindowHelpLinkControl()); return layout; } private CheckBox enableMaintenanceWindowControl() { final CheckBox enableMaintenanceWindow = new CheckBox( getI18n().getMessage("caption.maintenancewindow.enabled")); enableMaintenanceWindow.setId(UIComponentIdProvider.MAINTENANCE_WINDOW_ENABLED_ID); enableMaintenanceWindow.addStyleName(ValoTheme.CHECKBOX_SMALL); enableMaintenanceWindow.addStyleName("dist-window-maintenance-window-enable"); enableMaintenanceWindow.addValueChangeListener(event -> { final Boolean isMaintenanceWindowEnabled = enableMaintenanceWindow.getValue(); maintenanceWindowLayout.setVisible(isMaintenanceWindowEnabled); maintenanceWindowLayout.setEnabled(isMaintenanceWindowEnabled); enableSaveButton(!isMaintenanceWindowEnabled); maintenanceWindowLayout.clearAllControls(); }); return enableMaintenanceWindow; } private Link maintenanceWindowHelpLinkControl() { final String maintenanceWindowHelpUrl = uiProperties.getLinks().getDocumentation() .getMaintenanceWindowView(); return SPUIComponentProvider.getHelpLink(getI18n(), maintenanceWindowHelpUrl); } private void initMaintenanceWindow() { maintenanceWindowLayout.setVisible(false); maintenanceWindowLayout.setEnabled(false); maintenanceWindowLayout.getScheduleControl() .addTextChangeListener(event -> enableSaveButton(maintenanceWindowLayout.onScheduleChange(event))); maintenanceWindowLayout.getDurationControl() .addTextChangeListener(event -> enableSaveButton(maintenanceWindowLayout.onDurationChange(event))); } private void enableSaveButton(final boolean enabled) { confirmDialog.getOkButton().setEnabled(enabled); } private void addNewTargetToAssignmentList(final TargetIdName createTargetIdName, final DistributionSet findDistributionSetAllById) { final DistributionSetIdName distributionNameId = new DistributionSetIdName(findDistributionSetAllById); managementUIState.getAssignedList().put(createTargetIdName, distributionNameId); } @Override protected void handleOkDelete(final List<Long> entitiesToDelete) { targetManagement.delete(entitiesToDelete); getEventBus().publish(this, new TargetTableEvent(BaseEntityEventType.REMOVE_ENTITY, entitiesToDelete)); getNotification().displaySuccess(getI18n().getMessage("message.delete.success", entitiesToDelete.size() + " " + getI18n().getMessage("caption.target") + "(s)")); managementUIState.getDistributionTableFilters().getPinnedTarget().ifPresent(this::unPinDeletedTarget); managementUIState.getSelectedTargetId().clear(); } private void unPinDeletedTarget(final TargetIdName pinnedTarget) { final Set<Long> deletedTargetIds = managementUIState.getSelectedTargetId(); if (deletedTargetIds.contains(pinnedTarget.getTargetId())) { managementUIState.getDistributionTableFilters().setPinnedTarget(null); getEventBus().publish(this, PinUnpinEvent.UNPIN_TARGET); } } @Override protected String getEntityId(final Object itemId) { final String targetId = String.valueOf( getContainerDataSource().getItem(itemId).getItemProperty(SPUILabelDefinitions.VAR_ID).getValue()); return "target." + targetId; } @Override protected Set<Long> getSelectedEntities() { return managementUIState.getSelectedTargetId(); } @Override protected String getEntityType() { return getI18n().getMessage("caption.target"); } @Override protected boolean hasDeletePermission() { return getPermChecker().hasDeleteRepositoryPermission() || getPermChecker().hasDeleteTargetPermission(); } @Override protected String getDeletedEntityName(final Long entityId) { final Optional<Target> target = targetManagement.get(entityId); if (target.isPresent()) { return target.get().getName(); } return ""; } }