InstallPlan.java
package org.entando.kubernetes.controller.digitalexchange.job.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Builder.Default;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.entando.kubernetes.model.bundle.ComponentType;
import org.springframework.util.CollectionUtils;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@JsonIgnoreProperties(ignoreUnknown = true)
public class InstallPlan {
@Default
private Boolean hasConflicts = null;
@Default
private Map<String, ComponentInstallPlan> widgets = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> fragments = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> pages = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> pageTemplates = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> contents = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> contentTemplates = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> contentTypes = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> assets = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> directories = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> resources = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> plugins = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> categories = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> groups = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> labels = new HashMap<>();
@Default
private Map<String, ComponentInstallPlan> languages = new HashMap<>();
public Map<String, ComponentInstallPlan> getPlanByType(ComponentType type) {
switch (type) {
case WIDGET:
return widgets;
case FRAGMENT:
return fragments;
case PAGE:
return pages;
case PAGE_TEMPLATE:
return pageTemplates;
case CONTENT:
return contents;
case CONTENT_TEMPLATE:
return contentTemplates;
case CONTENT_TYPE:
return contentTypes;
case ASSET:
return assets;
case DIRECTORY:
return directories;
case RESOURCE:
return resources;
case PLUGIN:
return plugins;
case CATEGORY:
return categories;
case GROUP:
return groups;
case LABEL:
return labels;
case LANGUAGE:
return languages;
default:
return new HashMap<>();
}
}
/**
* merge the current AnalysisReport and the received one.
*
* @param other the AnalysisReport to merge with the current one
* @return a new AnalysisReport resulting by the merge
*/
public InstallPlan merge(InstallPlan other) {
if (null == other) {
return this;
}
return InstallPlan.builder()
.hasConflicts(
Boolean.TRUE.equals(this.hasConflicts) || Boolean.TRUE.equals(other.hasConflicts))
.widgets(this.getNotNullInstallPlanComponent(InstallPlan::getWidgets, other))
.fragments(this.getNotNullInstallPlanComponent(InstallPlan::getFragments, other))
.pages(this.getNotNullInstallPlanComponent(InstallPlan::getPages, other))
.pageTemplates(this.getNotNullInstallPlanComponent(InstallPlan::getPageTemplates, other))
.contents(this.getNotNullInstallPlanComponent(InstallPlan::getContents, other))
.contentTemplates(this.getNotNullInstallPlanComponent(InstallPlan::getContentTemplates, other))
.contentTypes(this.getNotNullInstallPlanComponent(InstallPlan::getContentTypes, other))
.assets(this.getNotNullInstallPlanComponent(InstallPlan::getAssets, other))
.resources(this.getNotNullInstallPlanComponent(InstallPlan::getResources, other))
.plugins(this.getNotNullInstallPlanComponent(InstallPlan::getPlugins, other))
.categories(this.getNotNullInstallPlanComponent(InstallPlan::getCategories, other))
.groups(this.getNotNullInstallPlanComponent(InstallPlan::getGroups, other))
.labels(this.getNotNullInstallPlanComponent(InstallPlan::getLabels, other))
.languages(this.getNotNullInstallPlanComponent(InstallPlan::getLanguages, other))
.build();
}
/**
* apply the received function to the current InstallPlan. if the result is not null, return it. otherwise apply
* the function to the other InstallPlan received and return its result
*
* @param getInstallPlanComponentFn a function that get an InstallPlan and returns the desired Map object
* @param other the other InstallPlan
* @return the result of the received function on the current object if the result is not null, otherwise the result
* of the received function on the other object
*/
private Map<String, ComponentInstallPlan> getNotNullInstallPlanComponent(
Function<InstallPlan, Map<String, ComponentInstallPlan>> getInstallPlanComponentFn, InstallPlan other) {
return !CollectionUtils.isEmpty(getInstallPlanComponentFn.apply(this))
? getInstallPlanComponentFn.apply(this)
: getInstallPlanComponentFn.apply(other);
}
/**
* if there is at least an action different from CREATE, the installation is custom.
* a bundle installation becomes custom when the bundle is not installed entirely (one or more components are
* skipped or overridden)
* @return true if the installation is custom, false otherwise
*/
@JsonIgnore
public boolean isCustomInstallation() {
return doComponentsHaveSkipAction(this.getWidgets())
|| doComponentsHaveSkipAction(this.getFragments())
|| doComponentsHaveSkipAction(this.getPages())
|| doComponentsHaveSkipAction(this.getPageTemplates())
|| doComponentsHaveSkipAction(this.getContents())
|| doComponentsHaveSkipAction(this.getContentTemplates())
|| doComponentsHaveSkipAction(this.getContentTypes())
|| doComponentsHaveSkipAction(this.getAssets())
|| doComponentsHaveSkipAction(this.getResources())
|| doComponentsHaveSkipAction(this.getPlugins())
|| doComponentsHaveSkipAction(this.getCategories())
|| doComponentsHaveSkipAction(this.getGroups())
|| doComponentsHaveSkipAction(this.getLabels())
|| doComponentsHaveSkipAction(this.getLanguages());
}
/**
* check if at least one of the received ComponentInstallPlan has install action different from CREATE.
* @param componentInstallPlanMap the map of ComponentInstallPlan co check
* @return true if at least one ComponentInstallPlan has install action different from CREATE
*/
private boolean doComponentsHaveSkipAction(Map<String, ComponentInstallPlan> componentInstallPlanMap) {
if (CollectionUtils.isEmpty(componentInstallPlanMap)) {
return false;
}
return componentInstallPlanMap.values().stream()
.map(componentInstallPlan -> componentInstallPlan.getAction() == InstallAction.SKIP)
.reduce((customInstallAction1, customInstallAction2) -> customInstallAction1 || customInstallAction2)
.orElse(false);
}
}