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 if (!result.isEmpty()) 138 { 139 // use overridden label and description if present 140 result.put("label", getLabel()); 141 result.put("description", getDescription()); 142 result.put("role", getRole()); 143 144 if (StringUtils.isEmpty(getName())) 145 { 146 result.put("unnamed-group", true); 147 } 148 149 List<ViewItem> viewItems = _getChildrenWithoutSwitcher(); 150 if (!viewItems.isEmpty()) 151 { 152 result.put("elements", ViewHelper.viewItemsToJSON(viewItems, context)); 153 } 154 } 155 return result; 156 } 157 158 return Map.of(); 159 } 160 161 @SuppressWarnings("static-access") 162 public void toSAX(ContentHandler contentHandler, DefinitionContext context) throws SAXException 163 { 164 ModelItemGroup definition = getDefinition(); 165 if (definition != null) 166 { 167 AttributesImpl attributes = new AttributesImpl(); 168 attributes.addCDATAAttribute("name", definition.getName()); 169 attributes.addCDATAAttribute("plugin", definition.getPluginName()); 170 attributes.addCDATAAttribute("path", definition.getPath()); 171 172 String typeId = definition.getType() != null ? definition.getType().getId() : ModelItemGroup.DEFAULT_TYPE_ID; 173 attributes.addCDATAAttribute("type", typeId); 174 175 XMLUtils.startElement(contentHandler, "metadata", attributes); 176 177 XMLUtils.createElementIfNotNull(contentHandler, "role", getRole()); 178 XMLUtils.createI18nElementIfNotNull(contentHandler, "label", getLabel()); 179 XMLUtils.createI18nElementIfNotNull(contentHandler, "description", getDescription()); 180 181 definition.toSAX(contentHandler, context); 182 183 for (ViewItem viewItem : _getChildrenWithoutSwitcher()) 184 { 185 viewItem.toSAX(contentHandler, context); 186 } 187 188 XMLUtils.endElement(contentHandler, "metadata"); 189 } 190 } 191 192 private List<ViewItem> _getChildrenWithoutSwitcher() 193 { 194 ElementDefinition switcher = getDefinition().getSwitcher(); 195 if (switcher == null) 196 { 197 return getViewItems(); 198 } 199 200 List<ViewItem> childrenWithoutSwitcher = new ArrayList<>(); 201 for (ViewItem child : getViewItems()) 202 { 203 if (child instanceof ViewElement) 204 { 205 ElementDefinition childDefinitonReference = ((ViewElement) child).getDefinition(); 206 if (!switcher.equals(childDefinitonReference)) 207 { 208 childrenWithoutSwitcher.add(child); 209 } 210 } 211 } 212 213 return childrenWithoutSwitcher; 214 } 215 216 @Override 217 public void copyTo(ViewItem item) 218 { 219 super.copyTo(item); 220 221 assert item instanceof ModelViewItemGroup; 222 ((ModelViewItemGroup) item).setDefinition(getDefinition()); 223 } 224 225 public ModelViewItemGroup createInstance() 226 { 227 return new ModelViewItemGroup(); 228 } 229 230 @Override 231 public int hashCode() 232 { 233 final int prime = 31; 234 int result = super.hashCode(); 235 result = prime * result + Objects.hash(_definition); 236 return result; 237 } 238 239 @Override 240 public boolean equals(Object obj) 241 { 242 if (this == obj) 243 { 244 return true; 245 } 246 if (!super.equals(obj)) 247 { 248 return false; 249 } 250 if (getClass() != obj.getClass()) 251 { 252 return false; 253 } 254 ModelViewItemGroup other = (ModelViewItemGroup) obj; 255 return Objects.equals(_definition, other._definition); 256 } 257 258 @Override 259 public String toString() 260 { 261 return _definition.toString() + ": " + _children.toString(); 262 } 263}