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.Arrays; 020import java.util.Collection; 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.LinkedHashMap; 024import java.util.List; 025import java.util.Map; 026 027import org.apache.cocoon.ProcessingException; 028 029import org.ametys.runtime.model.type.ElementType; 030import org.ametys.runtime.model.type.ModelItemType; 031import org.ametys.runtime.model.type.ModelItemTypeConstants; 032 033/** 034 * Class for group of model items 035 */ 036public class ModelItemGroup extends AbstractModelItem implements ModelItemContainer 037{ 038 /** Id for model item group types */ 039 private static final String __DEFAULT_TYPE_ID = "composite"; 040 041 private List<ModelItem> _children = new ArrayList<>(); 042 private ElementDefinition<Boolean> _switcher; 043 private ModelItemType _type; 044 045 /** 046 * Default constructor. 047 */ 048 public ModelItemGroup() 049 { 050 super(); 051 } 052 053 /** 054 * Constructor used to create simple models and items 055 * @param name the name of the definition 056 * @param children the group's children 057 */ 058 public ModelItemGroup(String name, ModelItem... children) 059 { 060 super(name); 061 Arrays.stream(children) 062 .forEach(item -> addChild(item)); 063 } 064 065 public Collection<ModelItem> getModelItems() 066 { 067 return getChildren(); 068 } 069 070 /** 071 * Retrieves the list of children model items 072 * @return the children 073 */ 074 public List<ModelItem> getChildren() 075 { 076 return getChildren(true); 077 } 078 079 /** 080 * Retrieves the list of children model items, with or without the switcher 081 * @param withSwitch true to retrieve the switcher with the other children 082 * @return the children with or without the switcher 083 */ 084 public List<ModelItem> getChildren(boolean withSwitch) 085 { 086 if (withSwitch || _switcher == null) 087 { 088 return Collections.unmodifiableList(_children); 089 } 090 091 List<ModelItem> childrenWithoutSwitcher = new ArrayList<>(_children); 092 childrenWithoutSwitcher.remove(_switcher); 093 return childrenWithoutSwitcher; 094 } 095 096 /** 097 * Add a child in the group 098 * @param child the item to add 099 */ 100 public void addChild(ModelItem child) 101 { 102 addChild(child, false); 103 } 104 105 /** 106 * Add a child in the group 107 * @param child the child to add 108 * @param isGroupSwitch true if the child to add is the group switch, false otherwise 109 */ 110 @SuppressWarnings("unchecked") 111 public void addChild(ModelItem child, boolean isGroupSwitch) 112 { 113 _children.add(child); 114 child.setParent(this); 115 116 if (isGroupSwitch) 117 { 118 if (_switcher == null) 119 { 120 if (child instanceof ElementDefinition) 121 { 122 ElementType type = ((ElementDefinition) child).getType(); 123 if (ModelItemTypeConstants.BOOLEAN_TYPE_ID.equals(type.getId())) 124 { 125 _switcher = (ElementDefinition<Boolean>) child; 126 } 127 } 128 129 if (_switcher == null) 130 { 131 // If switcher is still null, the type of child is not compatible 132 throw new RuntimeException("The group '" + getLabel() + "' has a switch '" + child + "' that is not valid because it is not a boolean."); 133 } 134 } 135 else 136 { 137 throw new RuntimeException("At least two group-switches have been defined for the configuration group '" + getLabel() + "'. These parameters are '" + _switcher + "' and '" + child + "'."); 138 } 139 } 140 } 141 142 /** 143 * Retrieves the switcher element definition 144 * @return the switcher 145 */ 146 public ElementDefinition<Boolean> getSwitcher() 147 { 148 return _switcher; 149 } 150 151 @Override 152 public void setModel(Model model) 153 { 154 super.setModel(model); 155 for (ModelItem modelItem : _children) 156 { 157 modelItem.setModel(model); 158 } 159 } 160 161 @Override 162 public ModelItemType getType() 163 { 164 return _type; 165 } 166 167 public void setType(ModelItemType type) 168 { 169 _type = type; 170 } 171 172 @Override 173 public Map<String, Object> toJSON() throws ProcessingException 174 { 175 return toJSON(true); 176 } 177 178 /** 179 * Converts the model item group in a JSON map 180 * @param includeChildren true to iterate and add children as elements in the returned JSON map, false otherwise 181 * @return The model item as a JSON map 182 * @throws ProcessingException If an error occurs when converting the model item group 183 */ 184 public Map<String, Object> toJSON(boolean includeChildren) throws ProcessingException 185 { 186 Map<String, Object> result = super.toJSON(); 187 188 ModelItemType type = getType(); 189 result.put("type", type != null ? type.getId() : __DEFAULT_TYPE_ID); 190 191 ElementDefinition<Boolean> switcher = getSwitcher(); 192 if (switcher != null) 193 { 194 Map<String, Object> switcherToJSON = new HashMap<>(); 195 196 switcherToJSON.put("id", switcher.getName()); 197 switcherToJSON.put("label", switcher.getLabel()); 198 199 if (switcher.getType() != null) 200 { 201 switcherToJSON.put("default-value", switcher.getType().valueToJSONForClient(switcher.getDefaultValue())); 202 } 203 204 result.put("switcher", switcherToJSON); 205 } 206 207 // Do not include switcher in children because it is already included above 208 List<ModelItem> children = getChildren(false); 209 if (includeChildren && !children.isEmpty()) 210 { 211 Map<String, Object> elements = new LinkedHashMap<>(); 212 for (ModelItem child : children) 213 { 214 String name = child.getName(); 215 if (name != null) 216 { 217 elements.put(name, child.toJSON()); 218 } 219 } 220 221 result.put("elements", elements); 222 } 223 224 return result; 225 } 226 227 /** 228 * Creates a {@link ModelItemGroup} 229 * @param name the group's name 230 * @param children the group's children 231 * @return the created {@link ModelItemGroup} 232 */ 233 public static ModelItemGroup of(String name, ModelItem... children) 234 { 235 return new ModelItemGroup(name, children); 236 } 237}