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.Collections;
020import java.util.HashMap;
021import java.util.HashSet;
022import java.util.List;
023import java.util.Map;
024import java.util.Set;
025
026import org.apache.avalon.framework.component.Component;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.cocoon.ProcessingException;
029
030import org.ametys.runtime.i18n.I18nizableText;
031import org.ametys.runtime.model.checker.ItemCheckerDescriptor;
032
033/**
034 * Abstract class for model items
035 */
036public abstract class AbstractModelItem implements ModelItem
037{
038    /** The service manager */
039    protected static ServiceManager __serviceManager;
040    
041    private String _name;
042    private I18nizableText _label;
043    private I18nizableText _description;
044    private Set<ItemCheckerDescriptor> _itemCheckers = new HashSet<>();
045    
046    private Model _model;
047    private ModelItemGroup _parent;
048
049    /**
050     * Default constructor.
051     */
052    public AbstractModelItem()
053    {
054        // Empty constructor
055    }
056    
057    /**
058     * Constructor used to create simple models and items 
059     * @param name the name of the item
060     */
061    public AbstractModelItem(String name)
062    {
063        _name = name;
064    }
065
066    /**
067     * Constructor by copying an existing {@link AbstractModelItem}.
068     * @param modelItemToCopy The {@link AbstractModelItem} to copy
069     */
070    public AbstractModelItem(AbstractModelItem modelItemToCopy)
071    {
072        setName(modelItemToCopy.getName());
073        setLabel(modelItemToCopy.getLabel());
074        setDescription(modelItemToCopy.getDescription());
075        for (ItemCheckerDescriptor itemChecker : modelItemToCopy.getItemCheckers())
076        {
077            addItemChecker(itemChecker);
078        }
079        setModel(modelItemToCopy.getModel());
080        setParent(modelItemToCopy.getParent());
081    }
082    
083    public String getName()
084    {
085        return _name;
086    }
087    
088    public void setName(String name)
089    {
090        _name = name;
091    }
092    
093    public I18nizableText getLabel()
094    {
095        return _label;
096    }
097
098    public void setLabel(I18nizableText label)
099    {
100        _label = label;
101    }
102
103    public I18nizableText getDescription()
104    {
105        return _description;
106    }
107
108    public void setDescription(I18nizableText description)
109    {
110        _description = description;
111    }
112    
113    public void addItemChecker(ItemCheckerDescriptor itemChecker)
114    {
115        _itemCheckers.add(itemChecker);
116    }
117    
118    public Set<ItemCheckerDescriptor> getItemCheckers()
119    {
120        return Collections.unmodifiableSet(_itemCheckers);
121    }
122
123    public String getPath()
124    {
125        if (getName() == null)
126        {
127            return null;
128        }
129        
130        StringBuilder path = new StringBuilder();
131        
132        ModelItemGroup parent = getParent();
133        if (parent != null && parent.getPath() != null)
134        {
135            path.append(parent.getPath()).append(ITEM_PATH_SEPARATOR);
136        }
137        
138        path.append(getName());
139        return path.toString();
140    }
141
142    public Model getModel()
143    {
144        return _model;
145    }
146    
147    public void setModel(Model model)
148    {
149        _model = model;
150    }
151
152    public ModelItemGroup getParent()
153    {
154        return _parent;
155    }
156    
157    public void setParent(ModelItemGroup parent)
158    {
159        _parent = parent;
160    }
161    
162    public Map<String, Object> toJSON() throws ProcessingException
163    {
164        Map<String, Object> result = new HashMap<>();
165        
166        result.put("name", getName());
167        result.put("label", getLabel());
168        result.put("description", getDescription());
169        
170        if (!getItemCheckers().isEmpty())
171        {
172            List<Map<String, Object>> checkers2json = new ArrayList<>();
173            for (ItemCheckerDescriptor paramChecker : getItemCheckers())
174            {
175                checkers2json.add(paramChecker.toJSON());
176            }
177            
178            result.put("field-checker", checkers2json);
179        }
180        
181        return result;
182    }
183    
184    public int compareTo(ModelItem item)
185    {
186        if (item == null)
187        {
188            return 1;
189        }
190        
191        String name = getName();
192        if (name != null)
193        {
194            return name.compareTo(item.getName());
195        }
196        
197        I18nizableText label = getLabel();
198        if (label != null)
199        {
200            I18nizableText otherLabel = item.getLabel();
201            if (otherLabel == null)
202            {
203                return 1;
204            }
205            return label.toString().compareTo(otherLabel.toString());
206        }
207        return 0;
208    }
209    
210    @Override
211    public boolean equals(Object obj)
212    {
213        if (obj == null)
214        {
215            return false;
216        }
217        
218        if (!(obj instanceof ModelItem))
219        {
220            return false;
221        }
222        
223        ModelItem item = (ModelItem) obj;
224        
225        if (getName() != null)
226        {
227            return getName().equals(item.getName());
228        }
229        
230        if (getLabel() != null)
231        {
232            return getLabel().equals(item.getLabel());
233        }
234        
235        return true;
236    }
237
238    @Override
239    public int hashCode()
240    {
241        if (getName() != null)
242        {
243            return getName().hashCode();
244        }
245        
246        return getLabel().hashCode();
247    }
248    
249    @Override
250    public String toString()
251    {
252        if (getName() != null)
253        {
254            return getName();
255        }
256        return getLabel().toString();
257    }
258    
259    /**
260     * Set the service manager
261     * The {@link ServiceManager} is used in the model items creation methods to get the model item type.
262     * {@link ModelItem} is not a {@link Component} and can't have a {@link ServiceManager} itself. Another {@link Component} has to set it
263     * @param manager the service manager to set
264     */
265    public static void setServiceManager(ServiceManager manager)
266    {
267        __serviceManager = manager;
268    }
269}