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