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