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