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.List; 020import java.util.Map; 021import java.util.Objects; 022 023import org.apache.cocoon.ProcessingException; 024import org.apache.cocoon.xml.AttributesImpl; 025import org.apache.commons.lang3.StringUtils; 026import org.xml.sax.ContentHandler; 027import org.xml.sax.SAXException; 028 029import org.ametys.core.util.SizeUtils.ExcludeFromSizeCalculation; 030import org.ametys.core.util.XMLUtils; 031import org.ametys.runtime.i18n.I18nizableText; 032import org.ametys.runtime.model.exception.BadItemTypeException; 033 034/** 035 * View reference to a group of model items 036 */ 037public class ModelViewItemGroup extends AbstractViewItemGroup implements ModelViewItem<ModelItemGroup> 038{ 039 @ExcludeFromSizeCalculation 040 private ModelItemGroup _definition; 041 042 /** 043 * Creates a {@link ModelViewItemGroup} with the items of the given {@link ModelItemGroup} 044 * @param modelItem the model item group 045 * @return the created {@link ModelViewItemGroup} 046 * @throws IllegalArgumentException if the model item is <code>null</code> 047 */ 048 public static ModelViewItemGroup of(ModelItemGroup modelItem) throws IllegalArgumentException 049 { 050 if (modelItem == null) 051 { 052 throw new IllegalArgumentException("Unable to create the view from a null model"); 053 } 054 else 055 { 056 return ViewHelper.createViewItemAccessor(List.of(modelItem)); 057 } 058 } 059 060 /** 061 * Creates a {@link ModelViewItemGroup} with the given items 062 * @param modelItem the model item containing items definitions 063 * @param itemPaths the paths of the items to put in the view item 064 * @return the created {@link ModelViewItemGroup} 065 * @throws IllegalArgumentException if the model item is <code>null</code> or if an item path is <code>null</code>, empty, or is not defined in the given model items 066 * @throws BadItemTypeException if a segment in a path (but not the last) does not represent a group item 067 */ 068 public static ModelViewItemGroup of(ModelItemGroup modelItem, String... itemPaths) throws IllegalArgumentException, BadItemTypeException 069 { 070 if (modelItem == null) 071 { 072 throw new IllegalArgumentException("Unable to create the view from a null model"); 073 } 074 else 075 { 076 return ViewHelper.createViewItemAccessor(List.of(modelItem), itemPaths); 077 } 078 } 079 080 public ModelItemGroup getDefinition() 081 { 082 return _definition; 083 } 084 085 public void setDefinition(ModelItemGroup definition) 086 { 087 if (definition == null) 088 { 089 throw new IllegalArgumentException("Try to set a null definition to the model view item group"); 090 } 091 092 _definition = definition; 093 } 094 095 public String getName() 096 { 097 if (_definition != null) 098 { 099 return _definition.getName(); 100 } 101 else 102 { 103 return null; 104 } 105 } 106 107 @Override 108 public I18nizableText getLabel() 109 { 110 I18nizableText label = super.getLabel(); 111 if (label != null) 112 { 113 return label; 114 } 115 116 return getDefinition().getLabel(); 117 } 118 119 @Override 120 public I18nizableText getDescription() 121 { 122 I18nizableText desc = super.getDescription(); 123 if (desc != null) 124 { 125 return desc; 126 } 127 128 return getDefinition().getDescription(); 129 } 130 131 public Map<String, Object> toJSON(DefinitionContext context) throws ProcessingException 132 { 133 ModelItemGroup definition = getDefinition(); 134 if (definition != null) 135 { 136 Map<String, Object> result = definition.toJSON(context, false); 137 138 // use overridden label and description if present 139 result.put("label", getLabel()); 140 result.put("description", getDescription()); 141 result.put("role", getRole()); 142 143 if (StringUtils.isEmpty(getName())) 144 { 145 result.put("unnamed-group", true); 146 } 147 148 List<ViewItem> viewItems = _getChildrenWithoutSwitcher(); 149 if (!viewItems.isEmpty()) 150 { 151 result.put("elements", ViewHelper.viewItemsToJSON(viewItems, context)); 152 } 153 154 return result; 155 } 156 157 return Map.of(); 158 } 159 160 @SuppressWarnings("static-access") 161 public void toSAX(ContentHandler contentHandler, DefinitionContext context) throws SAXException 162 { 163 ModelItemGroup definition = getDefinition(); 164 if (definition != null) 165 { 166 AttributesImpl attributes = new AttributesImpl(); 167 attributes.addCDATAAttribute("name", definition.getName()); 168 attributes.addCDATAAttribute("plugin", definition.getPluginName()); 169 attributes.addCDATAAttribute("path", definition.getPath()); 170 171 String typeId = definition.getType() != null ? definition.getType().getId() : ModelItemGroup.DEFAULT_TYPE_ID; 172 attributes.addCDATAAttribute("type", typeId); 173 174 XMLUtils.startElement(contentHandler, "metadata", attributes); 175 176 XMLUtils.createElementIfNotNull(contentHandler, "role", getRole()); 177 XMLUtils.createI18nElementIfNotNull(contentHandler, "label", getLabel()); 178 XMLUtils.createI18nElementIfNotNull(contentHandler, "description", getDescription()); 179 180 definition.toSAX(contentHandler, context); 181 182 for (ViewItem viewItem : _getChildrenWithoutSwitcher()) 183 { 184 viewItem.toSAX(contentHandler, context); 185 } 186 187 XMLUtils.endElement(contentHandler, "metadata"); 188 } 189 } 190 191 private List<ViewItem> _getChildrenWithoutSwitcher() 192 { 193 ElementDefinition switcher = getDefinition().getSwitcher(); 194 if (switcher == null) 195 { 196 return getViewItems(); 197 } 198 199 List<ViewItem> childrenWithoutSwitcher = new ArrayList<>(); 200 for (ViewItem child : getViewItems()) 201 { 202 if (child instanceof ViewElement) 203 { 204 ElementDefinition childDefinitonReference = ((ViewElement) child).getDefinition(); 205 if (!switcher.equals(childDefinitonReference)) 206 { 207 childrenWithoutSwitcher.add(child); 208 } 209 } 210 } 211 212 return childrenWithoutSwitcher; 213 } 214 215 @Override 216 public void copyTo(ViewItem item) 217 { 218 super.copyTo(item); 219 220 assert item instanceof ModelViewItemGroup; 221 ((ModelViewItemGroup) item).setDefinition(getDefinition()); 222 } 223 224 public ModelViewItemGroup createInstance() 225 { 226 return new ModelViewItemGroup(); 227 } 228 229 @Override 230 public int hashCode() 231 { 232 final int prime = 31; 233 int result = super.hashCode(); 234 result = prime * result + Objects.hash(_definition); 235 return result; 236 } 237 238 @Override 239 public boolean equals(Object obj) 240 { 241 if (this == obj) 242 { 243 return true; 244 } 245 if (!super.equals(obj)) 246 { 247 return false; 248 } 249 if (getClass() != obj.getClass()) 250 { 251 return false; 252 } 253 ModelViewItemGroup other = (ModelViewItemGroup) obj; 254 return Objects.equals(_definition, other._definition); 255 } 256 257 @Override 258 public String toString() 259 { 260 return _definition.toString() + ": " + _children.toString(); 261 } 262}