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.Collections; 021import java.util.HashMap; 022import java.util.LinkedHashMap; 023import java.util.List; 024import java.util.Map; 025 026import org.apache.cocoon.ProcessingException; 027 028import org.ametys.core.model.type.AbstractModelItemType; 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 AbstractModelItemType _type; 044 045 public Collection<ModelItem> getModelItems() 046 { 047 return getChildren(); 048 } 049 050 /** 051 * Retrieves the list of children model items 052 * @return the children 053 */ 054 public List<ModelItem> getChildren() 055 { 056 return getChildren(true); 057 } 058 059 /** 060 * Retrieves the list of children model items, with or without the switcher 061 * @param withSwitch true to retrieve the switcher with the other children 062 * @return the children with or without the switcher 063 */ 064 public List<ModelItem> getChildren(boolean withSwitch) 065 { 066 if (withSwitch || _switcher == null) 067 { 068 return Collections.unmodifiableList(_children); 069 } 070 071 List<ModelItem> childrenWithoutSwitcher = new ArrayList<>(_children); 072 childrenWithoutSwitcher.remove(_switcher); 073 return childrenWithoutSwitcher; 074 } 075 076 /** 077 * Add a child in the group 078 * @param child the item to add 079 */ 080 public void addChild(ModelItem child) 081 { 082 addChild(child, false); 083 } 084 085 /** 086 * Add a child in the group 087 * @param child the child to add 088 * @param isGroupSwitch true if the child to add is the group switch, false otherwise 089 */ 090 @SuppressWarnings("unchecked") 091 public void addChild(ModelItem child, boolean isGroupSwitch) 092 { 093 _children.add(child); 094 child.setParent(this); 095 096 if (isGroupSwitch) 097 { 098 if (_switcher == null) 099 { 100 if (child instanceof ElementDefinition) 101 { 102 ElementType type = ((ElementDefinition) child).getType(); 103 if (ModelItemTypeConstants.BOOLEAN_TYPE_ID.equals(type.getId())) 104 { 105 _switcher = (ElementDefinition<Boolean>) child; 106 } 107 } 108 109 if (_switcher == null) 110 { 111 // If switcher is still null, the type of child is not compatible 112 throw new RuntimeException("The group '" + getLabel() + "' has a switch '" + child + "' that is not valid because it is not a boolean."); 113 } 114 } 115 else 116 { 117 throw new RuntimeException("At least two group-switches have been defined for the configuration group '" + getLabel() + "'. These parameters are '" + _switcher + "' and '" + child + "'."); 118 } 119 } 120 } 121 122 /** 123 * Retrieves the switcher element definition 124 * @return the switcher 125 */ 126 public ElementDefinition<Boolean> getSwitcher() 127 { 128 return _switcher; 129 } 130 131 @Override 132 public AbstractModelItemType getType() 133 { 134 return _type; 135 } 136 137 public void setType(ModelItemType type) 138 { 139 if (type instanceof AbstractModelItemType) 140 { 141 _type = (AbstractModelItemType) type; 142 } 143 else 144 { 145 throw new IllegalArgumentException("Unable to set the type '" + type.getClass() + "' on the group '" + getName() + "'"); 146 } 147 } 148 149 @Override 150 public Map<String, Object> toJSON() throws ProcessingException 151 { 152 return toJSON(true); 153 } 154 155 /** 156 * Converts the model item group in a JSON map 157 * @param includeChildren true to iterate and add children as elements in the returned JSON map, false otherwise 158 * @return The model item as a JSON map 159 * @throws ProcessingException If an error occurs when converting the model item group 160 */ 161 public Map<String, Object> toJSON(boolean includeChildren) throws ProcessingException 162 { 163 Map<String, Object> result = super.toJSON(); 164 165 ModelItemType type = getType(); 166 result.put("type", type != null ? type.getId() : __DEFAULT_TYPE_ID); 167 168 ElementDefinition<Boolean> switcher = getSwitcher(); 169 if (switcher != null) 170 { 171 Map<String, Object> switcherToJSON = new HashMap<>(); 172 173 switcherToJSON.put("id", switcher.getName()); 174 switcherToJSON.put("label", switcher.getLabel()); 175 176 if (switcher.getType() != null) 177 { 178 switcherToJSON.put("default-value", switcher.getType().valueToJSONForClient(switcher.getDefaultValue())); 179 } 180 181 result.put("switcher", switcherToJSON); 182 } 183 184 // Do not include switcher in children because it is already included above 185 List<ModelItem> children = getChildren(false); 186 if (includeChildren && !children.isEmpty()) 187 { 188 Map<String, Object> elements = new LinkedHashMap<>(); 189 for (ModelItem child : children) 190 { 191 String name = child.getName(); 192 if (name != null) 193 { 194 elements.put(name, child.toJSON()); 195 } 196 } 197 198 result.put("elements", elements); 199 } 200 201 return result; 202 } 203}