/* * Copyright (c) 2010-2015 Evolveum * * 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 com.evolveum.midpoint.model.impl.integrity; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Summary report from shadow checking task run. * * @author Pavol Mederly */ public class Statistics { public static final String NON_NORMALIZED_IDENTIFIER_VALUE = "Non-normalized identifier value"; public static final String DUPLICATE_SHADOWS = "Duplicate shadows"; public static final String NO_RESOURCE_OID = "No resource ref or OID"; public static final String NO_RESOURCE = "No resource"; public static final String CANNOT_GET_RESOURCE = "Cannot get resource object"; public static final String NO_KIND_SPECIFIED = "No kind specified"; public static final String NO_INTENT_SPECIFIED = "No intent specified"; public static final String NO_RESOURCE_REFINED_SCHEMA = "No resource refined schema"; public static final String CANNOT_GET_REFINED_SCHEMA = "Cannot get resource refined schema"; public static final String NO_OBJECT_CLASS_REFINED_SCHEMA = "No object class refined schema"; public static final String OTHER_FAILURE = "Other failure"; public static final String CANNOT_APPLY_FIX = "Cannot apply fix"; public static final String CANNOT_FETCH_RESOURCE_OBJECT = "Cannot fetch resource object"; public static final String MULTIPLE_OWNERS = "Multiple owners"; public static final String LINKED_WITH_NO_OWNER = "Linked shadow with no owner"; public static final String NOT_LINKED_WITH_OWNER = "Not linked shadow with an owner"; public static final String EXTRA_ACTIVATION_DATA = "Extra activation data present"; private int resources; private int shadows; private int shadowsWithErrors; private int shadowsWithWarnings; private int unfinishedShadows; private String[] codeList = { NON_NORMALIZED_IDENTIFIER_VALUE, NO_RESOURCE_OID, NO_RESOURCE, CANNOT_GET_RESOURCE, NO_KIND_SPECIFIED, NO_INTENT_SPECIFIED, NO_RESOURCE_REFINED_SCHEMA, CANNOT_GET_REFINED_SCHEMA, NO_OBJECT_CLASS_REFINED_SCHEMA, CANNOT_FETCH_RESOURCE_OBJECT, MULTIPLE_OWNERS, LINKED_WITH_NO_OWNER, NOT_LINKED_WITH_OWNER, EXTRA_ACTIVATION_DATA, OTHER_FAILURE, CANNOT_APPLY_FIX }; private List<String> fixable = Arrays.asList(NON_NORMALIZED_IDENTIFIER_VALUE, NO_INTENT_SPECIFIED, EXTRA_ACTIVATION_DATA, NO_RESOURCE_OID, NO_RESOURCE); // problem code -> number of occurrences [0] and number of shadows [1] private Map<String,Counts> problemCount = new HashMap<>(); public void incrementResources() { resources++; } public void incrementShadows() { shadows++; } public void incrementShadowsWithErrors() { shadowsWithErrors++; } public void incrementShadowsWithWarnings() { shadowsWithWarnings++; } public void incrementUnfinishedShadows() { unfinishedShadows++; } public int getResources() { return resources; } public void setResources(int resources) { this.resources = resources; } public int getShadows() { return shadows; } public void setShadows(int shadows) { this.shadows = shadows; } public int getShadowsWithErrors() { return shadowsWithErrors; } public void setShadowsWithErrors(int shadowsWithErrors) { this.shadowsWithErrors = shadowsWithErrors; } public int getShadowsWithWarnings() { return shadowsWithWarnings; } public void setShadowsWithWarnings(int shadowsWithWarnings) { this.shadowsWithWarnings = shadowsWithWarnings; } public int getUnfinishedShadows() { return unfinishedShadows; } public void setUnfinishedShadows(int unfinishedShadows) { this.unfinishedShadows = unfinishedShadows; } public void registerProblemCodeOccurrences(List<String> problemCodes) { Set<String> alreadySeen = new HashSet<>(); for (String code : problemCodes) { Counts value = problemCount.computeIfAbsent(code, k -> new Counts()); value.cases++; if (alreadySeen.add(code)) { value.shadows++; } } } public void registerProblemsFixes(List<String> problemCodesFixed) { Set<String> alreadySeen = new HashSet<>(); for (String code : problemCodesFixed) { // shouldn't occur Counts value = problemCount.computeIfAbsent(code, k -> new Counts()); value.casesFixed++; if (alreadySeen.add(code)) { value.shadowsFixed++; } } } public String getDetailsFormatted(boolean dryRun) { StringBuilder sb = new StringBuilder(); for (String code : codeList) { Counts counts = problemCount.get(code); if (counts == null) { counts = new Counts(); } sb.append(" - ").append(code).append(": "); sb.append(counts.cases).append(" cases"); if (counts.cases > 0) { sb.append(" (").append(counts.shadows).append(" shadows)"); } if (fixable.contains(code)) { sb.append("; fixed "); if (dryRun) { sb.append("(if not run in dry-run mode) "); } sb.append(counts.casesFixed).append(" cases"); if (counts.casesFixed > 0) { sb.append(" (").append(counts.shadowsFixed).append(" shadows)"); } } sb.append(".\n"); } return sb.toString(); } public static class Counts { int cases = 0; int shadows = 0; int casesFixed = 0; int shadowsFixed = 0; } }