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.Map;
019import java.util.Objects;
020
021import org.apache.cocoon.xml.AttributesImpl;
022import org.apache.commons.lang3.StringUtils;
023import org.xml.sax.ContentHandler;
024import org.xml.sax.SAXException;
025
026import org.ametys.core.util.SizeUtils.ExcludeFromSizeCalculation;
027import org.ametys.core.util.XMLUtils;
028import org.ametys.plugins.core.ui.help.HelpLink;
029import org.ametys.runtime.i18n.I18nizableText;
030
031/**
032 * View reference to an element definition
033 */
034public class ViewElement implements ModelViewItem<ElementDefinition>
035{
036    @ExcludeFromSizeCalculation
037    private ElementDefinition _definition;
038    
039    @ExcludeFromSizeCalculation
040    private ViewItemAccessor _parent;
041    
042    private I18nizableText _label;
043    private I18nizableText _description;
044    
045    public ElementDefinition getDefinition()
046    {
047        return _definition;
048    }
049
050    public void setDefinition(ElementDefinition definition)
051    {
052        if (definition == null)
053        {
054            throw new IllegalArgumentException("Try to set a null definition to the view element");
055        }
056        _definition = definition;
057    }
058    
059    public ViewItemAccessor getParent()
060    {
061        return _parent;
062    }
063    
064    public void setParent(ViewItemAccessor parent)
065    {
066        _parent = parent;
067    }
068    
069    public String getName()
070    {
071        if (_definition != null)
072        {
073            return _definition.getName();
074        }
075        else
076        {
077            return null;
078        }
079    }
080    
081    public void setLabel(I18nizableText label)
082    {
083        _label = label;
084    }
085    
086    public void setDescription(I18nizableText description)
087    {
088        _description = description;
089    }
090
091    @Override
092    public I18nizableText getLabel()
093    {
094        return _label != null ? _label : getDefinition().getLabel();
095    }
096    
097    @Override
098    public I18nizableText getDescription()
099    {
100        return _description != null ? _description : getDefinition().getDescription();
101    }
102    
103    public Map<String, Object> toJSON(DefinitionContext context)
104    {
105        ElementDefinition definition = getDefinition();
106        if (definition != null)
107        {
108            Map<String, Object> result = definition.toJSON(context);
109            if (!result.isEmpty())
110            {
111                // use overridden label and description if present  
112                result.put("label", getLabel());
113                result.put("description", getDescription());
114    
115                Model model = definition.getModel();
116                if (model != null)
117                {
118                    String modelId = model.getId();
119                    String family = model.getFamilyId();
120                    
121                    String path = definition.getPath();
122                    //If there is a path, and it does not starts with '/', we add one at the beginning
123                    if (StringUtils.isNotBlank(path))
124                    {
125                        path = StringUtils.prependIfMissing(path, ModelItem.ITEM_PATH_SEPARATOR);
126                    }
127                    String featureId = StringUtils.join(modelId, path);
128                    //Remove the starting '/' if present
129                    featureId = StringUtils.removeStart(featureId, ModelItem.ITEM_PATH_SEPARATOR);
130        
131                    HelpLink help = new HelpLink(family, featureId, null);
132                    result.put("help", help);
133                }
134                
135                return result;
136            }
137        }
138        
139        return Map.of();
140    }
141    
142    @SuppressWarnings("static-access")
143    public void toSAX(ContentHandler contentHandler, DefinitionContext context) throws SAXException
144    {
145        ElementDefinition definition = getDefinition();
146        if (definition != null)
147        {
148            String tagName = context.getItemTagName().orElse(DEFAULT_ITEM_TAG_NAME);
149            
150            AttributesImpl attributes = new AttributesImpl();
151            attributes.addCDATAAttribute("name", definition.getName());
152            attributes.addCDATAAttribute("plugin", definition.getPluginName());
153            attributes.addCDATAAttribute("path", definition.getPath());
154            attributes.addCDATAAttribute("type", definition.getType().getId());
155            attributes.addCDATAAttribute("multiple", String.valueOf(definition.isMultiple()));
156            
157            XMLUtils.startElement(contentHandler, tagName, attributes);
158            
159            XMLUtils.createI18nElementIfNotNull(contentHandler, "label", getLabel());
160            XMLUtils.createI18nElementIfNotNull(contentHandler, "description", getDescription());
161            
162            definition.toSAX(contentHandler, context);
163            
164            XMLUtils.endElement(contentHandler, tagName);
165        }
166    }
167    
168    public void copyTo(ViewItem item)
169    {
170        assert item instanceof ViewElement;
171        ViewElement viewElement = (ViewElement) item;
172
173        viewElement.setDefinition(getDefinition());
174        viewElement.setLabel(getLabel());
175        viewElement.setDescription(getDescription());
176    }
177    
178    public ViewElement createInstance()
179    {
180        return new ViewElement();
181    }
182
183    @Override
184    public int hashCode()
185    {
186        return Objects.hash(_definition);
187    }
188
189    @Override
190    public boolean equals(Object obj)
191    {
192        if (this == obj)
193        {
194            return true;
195        }
196        if (obj == null)
197        {
198            return false;
199        }
200        if (getClass() != obj.getClass())
201        {
202            return false;
203        }
204        ViewElement other = (ViewElement) obj;
205        return Objects.equals(_definition, other._definition);
206    }
207
208    @Override
209    public boolean equals(Object obj, boolean checkDetails)
210    {
211        if (!equals(obj))
212        {
213            return false;
214        }
215        else if (checkDetails)
216        {
217            ViewElement other = (ViewElement) obj;
218            return Objects.equals(_label, other._label) && Objects.equals(_description, other._description);
219        }
220        else
221        {
222            return true;
223        }
224    }
225    
226    @Override
227    public String toString()
228    {
229        return _definition.toString();
230    }
231}