001/* 002 * Copyright 2019 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.config; 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; 024import java.util.Map.Entry; 025 026import org.ametys.runtime.i18n.I18nizableText; 027import org.ametys.runtime.model.CategorizedElementDefinitionHelper; 028import org.ametys.runtime.model.CategorizedElementDefinitionWrapper; 029import org.ametys.runtime.model.ElementDefinition; 030import org.ametys.runtime.model.Model; 031import org.ametys.runtime.model.ModelItem; 032import org.ametys.runtime.model.ModelItemGroup; 033import org.ametys.runtime.model.ModelViewItem; 034import org.ametys.runtime.model.ModelViewItemGroup; 035import org.ametys.runtime.model.View; 036import org.ametys.runtime.model.ViewElement; 037import org.ametys.runtime.model.ViewItemGroup; 038 039/** 040 * Helper for {@link ConfigParameterDefinitionWrapper} 041 */ 042public final class ConfigParameterDefinitionHelper 043{ 044 private ConfigParameterDefinitionHelper() 045 { 046 //Nothing 047 } 048 049 /** 050 * Get definitions of all elements parsed in this {@link CategorizedElementDefinitionWrapper} {@link Collection}, as a flat map. 051 * @param elements a {@link Collection} of {@link CategorizedElementDefinitionWrapper} 052 * @return a map with the definition name as key, containing all definitions 053 */ 054 public static Map<String, ElementDefinition> getFlatDefinitions(Collection<ConfigParameterDefinitionWrapper> elements) 055 { 056 Map<String, ElementDefinition> flatDefinitions = new HashMap<>(); 057 for (ConfigParameterDefinitionWrapper element : elements) 058 { 059 ElementDefinition definition = element.getDefinition(); 060 flatDefinitions.put(definition.getName(), definition); 061 } 062 return flatDefinitions; 063 } 064 065 /** 066 * Categorize the ModlItems based on the informations in the {@link CategorizedElementDefinitionWrapper} collection 067 * Category and groups are not sorted, only definitions, based on the position. 068 * Sorting of category and groups have to be done when the view is created (each usage can be different) 069 * @param elements collection of categorized elements 070 * @return a list of {@link ModelItem} with the correct tree (category/group/definitions) 071 */ 072 public static List<ModelItem> categorizeConfigParameters(Collection<ConfigParameterDefinitionWrapper> elements) 073 { 074 Model model = ConfigManager.getInstance(); 075 Map<I18nizableText, Map<I18nizableText, List<ConfigParameterDefinitionWrapper>>> categories = CategorizedElementDefinitionHelper.categorizeElementDefinitionWrappers(elements); 076 //This list is not sorted, only definition are sorted, not groups. 077 //Groups should be sorted elsewhere (when creating the view for example) 078 List<ModelItem> modelItems = new ArrayList<>(); 079 for (Entry<I18nizableText, Map<I18nizableText, List<ConfigParameterDefinitionWrapper>>> categoryEntry : categories.entrySet()) 080 { 081 ModelItemGroup category = new ModelItemGroup(); 082 category.setModel(model); 083 category.setLabel(categoryEntry.getKey()); 084 modelItems.add(category); 085 Map<I18nizableText, List<ConfigParameterDefinitionWrapper>> values = categoryEntry.getValue(); 086 for (Entry<I18nizableText, List<ConfigParameterDefinitionWrapper>> groupEntry : values.entrySet()) 087 { 088 ModelItemGroup group = new ModelItemGroup(); 089 group.setModel(model); 090 group.setLabel(groupEntry.getKey()); 091 category.addChild(group); 092 093 for (ConfigParameterDefinitionWrapper orderedDefinition : groupEntry.getValue()) 094 { 095 ElementDefinition definition = orderedDefinition.getDefinition(); 096 group.addChild(definition, orderedDefinition.isGroupSwitch()); 097 } 098 } 099 } 100 return modelItems; 101 } 102 103 /** 104 * Generate the view for a list of {@link ModelItem}, using comparators to sort the categories and the groups 105 * This works only on the very specific categories/group/fieldset hierarchy and an {@link IllegalArgumentException} will be thrown if the hierarchy is incorrect. 106 * @param categories list of {@link ModelItem} 107 * @param categoriesComparator {@link Comparator} used for the categories (can be null to keep order) 108 * @param groupsComparator {@link Comparator} for the groups (can be null to keep order) 109 * @param elementsComparator {@link Comparator} for the elements (can be null to keep order) 110 * @return A {@link View} ordered from the {@link ModelItem} using the {@link Comparator} 111 * @throws IllegalArgumentException the hierarchy of the categories/groups/elements is incorrect 112 */ 113 public static View buildConfigParametersView(Collection<? extends ModelItem> categories, Comparator<? super ModelItem> categoriesComparator, Comparator<? super ModelItem> groupsComparator, Comparator<? super ModelItem> elementsComparator) throws IllegalArgumentException 114 { 115 View view = new View(); 116 117 Collection<? extends ModelItem> sorted = _sort(categories, categoriesComparator); 118 119 for (ModelItem modelItem : sorted) 120 { 121 view.addViewItem(_buildCategoryViewItem(modelItem, groupsComparator, elementsComparator)); 122 } 123 return view; 124 } 125 126 private static ModelViewItemGroup _buildCategoryViewItem(ModelItem modelItem, Comparator<? super ModelItem> groupsComparator, Comparator<? super ModelItem> elementsComparator) throws IllegalArgumentException 127 { 128 if (modelItem instanceof ModelItemGroup) 129 { 130 ModelItemGroup category = (ModelItemGroup) modelItem; 131 ModelViewItemGroup categoryViewItem = new ModelViewItemGroup(); 132 categoryViewItem.setRole(ViewItemGroup.TAB_ROLE); 133 categoryViewItem.setDefinition(category); 134 135 Collection<? extends ModelItem> groups = _sort(category.getChildren(), groupsComparator); 136 137 for (ModelItem group : groups) 138 { 139 categoryViewItem.addViewItem(_buildGroupViewItem(group, elementsComparator)); 140 } 141 return categoryViewItem; 142 } 143 else 144 { 145 throw new IllegalArgumentException("Category " + modelItem.getPath() + " should be an instance of ModelItemGroup"); 146 } 147 } 148 149 private static ModelViewItemGroup _buildGroupViewItem(ModelItem modelItem, Comparator<? super ModelItem> elementsComparator) throws IllegalArgumentException 150 { 151 if (modelItem instanceof ModelItemGroup) 152 { 153 ModelItemGroup group = (ModelItemGroup) modelItem; 154 ModelViewItemGroup groupViewItem = new ModelViewItemGroup(); 155 groupViewItem.setRole(ViewItemGroup.FIELDSET_ROLE); 156 groupViewItem.setDefinition(group); 157 158 Collection<? extends ModelItem> items = _sort(group.getChildren(), elementsComparator); 159 160 for (ModelItem item : items) 161 { 162 groupViewItem.addViewItem(_buildElementViewItem(item)); 163 } 164 return groupViewItem; 165 } 166 else 167 { 168 throw new IllegalArgumentException("Group " + modelItem.getPath() + " should be an instance of ModelItemGroup"); 169 } 170 } 171 172 private static ModelViewItem _buildElementViewItem(ModelItem modelItem) throws IllegalArgumentException 173 { 174 if (modelItem instanceof ElementDefinition) 175 { 176 ElementDefinition definition = (ElementDefinition) modelItem; 177 178 ViewElement parameterViewItem = new ViewElement(); 179 parameterViewItem.setDefinition(definition); 180 return parameterViewItem; 181 } 182 else 183 { 184 throw new IllegalArgumentException("Item " + modelItem.getPath() + " should be an instance of ElementDefinition"); 185 } 186 } 187 188 /** 189 * sort a model item list using comparator 190 * @param items list of items to sort 191 * @param comparator a comparator, can be null to avoid sort 192 * @return a sorted list (or a copy of the list if the comparator is null) 193 */ 194 private static Collection<? extends ModelItem> _sort(Collection<? extends ModelItem> items, Comparator<? super ModelItem> comparator) 195 { 196 if (comparator == null) 197 { 198 return items; 199 } 200 else 201 { 202 List<ModelItem> sorted = new ArrayList<>(items); 203 sorted.sort(comparator); 204 return sorted; 205 } 206 } 207}