001/* 002 * Copyright 2018 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.runtime.model; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.Comparator; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Map; 024 025import org.slf4j.Logger; 026 027import org.ametys.runtime.i18n.I18nizableText; 028import org.ametys.runtime.model.disableconditions.DisableConditionsEvaluator; 029import org.ametys.runtime.parameter.ValidationResult; 030import org.ametys.runtime.parameter.ValidationResults; 031 032/** 033 * Helper for {@link CategorizedElementDefinitionWrapper} 034 */ 035public final class CategorizedElementDefinitionHelper 036{ 037 private CategorizedElementDefinitionHelper() 038 { 039 //Nothing 040 } 041 042 /** 043 * Generate the view for categorized element definition wrappers, using comparators to sort the categories, groups and elements 044 * @param <T> type of the wrappers 045 * @param wrappers the wrappers 046 * @param categoriesComparator {@link Comparator} used for the categories (can be null to keep order) 047 * @param groupsComparator {@link Comparator} for the groups (can be null to keep order) 048 * @param elementsComparator {@link Comparator} for the elements (can be null to keep order) 049 * @return A {@link View} ordered from the {@link ModelItem} using the {@link Comparator} 050 */ 051 public static <T extends CategorizedElementDefinitionWrapper> View buildViewFromCategories(Collection<T> wrappers, Comparator<I18nizableText> categoriesComparator, Comparator<I18nizableText> groupsComparator, Comparator<T> elementsComparator) 052 { 053 View view = new View(); 054 055 Map<I18nizableText, Map<I18nizableText, List<T>>> categories = categorizeElementDefinitionWrappers(wrappers); 056 057 Collection<I18nizableText> sortedCategories = _sort(categories.keySet(), categoriesComparator); 058 for (I18nizableText categoryLabel : sortedCategories) 059 { 060 ViewItem categoryViewItem = _buildCategoryViewItem(categoryLabel, categories.get(categoryLabel), groupsComparator, elementsComparator); 061 view.addViewItem(categoryViewItem); 062 } 063 return view; 064 } 065 066 /** 067 * Organize a collection of categorized element definition wrappers by categories and groups. 068 * @param <T> type of the wrappers 069 * @param wrappers a collection of element definition wrappers. 070 * @return a Map with the same element definition wrappers, sorted first by category then by group. 071 */ 072 public static <T extends CategorizedElementDefinitionWrapper> Map<I18nizableText, Map<I18nizableText, List<T>>> categorizeElementDefinitionWrappers(Collection<T> wrappers) 073 { 074 Map<I18nizableText, Map<I18nizableText, List<T>>> categories = new HashMap<>(); 075 076 // Classify parameters by groups and categories 077 for (T parameter : wrappers) 078 { 079 I18nizableText displayCategory = parameter.getDisplayCategory(); 080 I18nizableText displayGroup = parameter.getDisplayGroup(); 081 082 // Get the map of groups of the category 083 Map<I18nizableText, List<T>> category = categories.get(displayCategory); 084 if (category == null) 085 { 086 category = new HashMap<>(); 087 categories.put(displayCategory, category); 088 } 089 090 // Get the map of parameters of the group 091 List<T> group = category.get(displayGroup); 092 if (group == null) 093 { 094 group = new ArrayList<>(); 095 category.put(displayGroup, group); 096 } 097 098 group.add(parameter); 099 } 100 101 return categories; 102 } 103 104 private static <T extends CategorizedElementDefinitionWrapper> ViewItem _buildCategoryViewItem(I18nizableText categoryLabel, Map<I18nizableText, List<T>> groups, Comparator<I18nizableText> groupsComparator, Comparator<T> elementsComparator) throws IllegalArgumentException 105 { 106 SimpleViewItemGroup categoryViewItem = new SimpleViewItemGroup(); 107 categoryViewItem.setRole(ViewItemGroup.TAB_ROLE); 108 categoryViewItem.setLabel(categoryLabel); 109 110 Collection<I18nizableText> sortedGroups = _sort(groups.keySet(), groupsComparator); 111 for (I18nizableText groupLabel : sortedGroups) 112 { 113 ViewItem groupViewItem = _buildGroupViewItem(groupLabel, groups.get(groupLabel), elementsComparator); 114 categoryViewItem.addViewItem(groupViewItem); 115 } 116 return categoryViewItem; 117 } 118 119 private static <T extends CategorizedElementDefinitionWrapper> ViewItem _buildGroupViewItem(I18nizableText groupLabel, List<T> wrappers, Comparator<T> elementsComparator) throws IllegalArgumentException 120 { 121 SimpleViewItemGroup groupViewItem = new SimpleViewItemGroup(); 122 groupViewItem.setRole(ViewItemGroup.FIELDSET_ROLE); 123 groupViewItem.setLabel(groupLabel); 124 125 Collection<T> items = _sort(wrappers, elementsComparator); 126 for (T item : items) 127 { 128 ViewElement parameterViewItem = new ViewElement(); 129 parameterViewItem.setDefinition(item.getDefinition()); 130 groupViewItem.addViewItem(parameterViewItem); 131 } 132 133 return groupViewItem; 134 } 135 136 /** 137 * Sort a model item list using comparator 138 * @param <T> The type of item to compare 139 * @param items list of items to sort 140 * @param comparator a comparator, can be null to avoid sort 141 * @return a sorted list (or a copy of the list if the comparator is null) 142 */ 143 private static <T> Collection<T> _sort(Collection<T> items, Comparator<T> comparator) 144 { 145 if (comparator == null) 146 { 147 return items; 148 } 149 else 150 { 151 List<T> sorted = new ArrayList<>(items); 152 sorted.sort(comparator); 153 return sorted; 154 } 155 } 156 157 /** 158 * Validate parameters before writing 159 * @param <T> Type of object containing the values 160 * @param values a map of all parameters and their values 161 * @param definitions collection of {@link ElementDefinition} from the model file 162 * @param disableConditionsEvaluator the disable conditions evaluator for the given object 163 * @param logger a logger 164 * @return a map containing the potential errors 165 */ 166 public static <T> ValidationResults validateValuesForWriting (Map<String, Object> values, Collection<ElementDefinition> definitions, DisableConditionsEvaluator<T> disableConditionsEvaluator, Logger logger) 167 { 168 ValidationResults results = new ValidationResults(); 169 170 for (ElementDefinition definition : definitions) 171 { 172 boolean isGroupSwitchOn = ModelHelper.isGroupSwitchOn(definition, values); 173 boolean isDisabled = disableConditionsEvaluator.evaluateDisableConditions(definition, definition.getName(), values); 174 175 if (isGroupSwitchOn && !isDisabled) 176 { 177 Object value = values.get(definition.getName()); 178 ValidationResult result = ModelHelper.validateValue(definition, value); 179 results.addResult(definition.getName(), result); 180 181 if (result.hasErrors()) 182 { 183 logger.warn("The configuration parameter '{}' is not valid", definition.getName()); 184 } 185 } 186 } 187 188 if (results.hasErrors()) 189 { 190 logger.debug("Failed to save configuration because of invalid parameter values"); 191 } 192 193 return results; 194 } 195 196 /** 197 * Compares the two given wrappers' position. 198 * Returns a negative integer, zero, or a positive integer as the position of the first wrapper 199 * is less than, equal to, or greater than the second. 200 * @param <T> type of the wrappers to compare 201 * @param wrapper1 the first wrapper 202 * @param wrapper2 the second wrapper 203 * @return a negative integer, zero, or a positive integer as the position of the first wrapper 204 * is less than, equal to, or greater than the second. 205 */ 206 public static <T extends CategorizedElementDefinitionWrapper> int compareWrapperPositions(T wrapper1, T wrapper2) 207 { 208 int positionComparison = ((Long) wrapper1.getPosition()).compareTo(wrapper2.getPosition()); 209 if (wrapper1.getPosition() < 0 && wrapper2.getPosition() < 0) 210 { 211 positionComparison = 0; 212 } 213 else if (wrapper1.getPosition() < 0 && wrapper2.getPosition() >= 0) 214 { 215 positionComparison = 1; 216 } 217 else if (wrapper2.getPosition() < 0) 218 { 219 positionComparison = -1; 220 } 221 222 return positionComparison; 223 } 224}