001/*
002 *  Copyright 2019 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.plugins.repository.data.ametysobject;
017
018import java.util.Collection;
019import java.util.List;
020import java.util.Map;
021import java.util.Optional;
022
023import org.xml.sax.ContentHandler;
024import org.xml.sax.SAXException;
025
026import org.ametys.plugins.repository.AmetysObject;
027import org.ametys.plugins.repository.data.DataComment;
028import org.ametys.plugins.repository.data.external.ExternalizableDataProvider.ExternalizableDataStatus;
029import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder;
030import org.ametys.plugins.repository.data.holder.group.ModelAwareComposite;
031import org.ametys.plugins.repository.data.holder.group.ModelAwareRepeater;
032import org.ametys.plugins.repository.data.holder.impl.DataHolderHelper;
033import org.ametys.plugins.repository.data.holder.values.SynchronizationContext;
034import org.ametys.runtime.model.Model;
035import org.ametys.runtime.model.ModelItem;
036import org.ametys.runtime.model.ViewItemAccessor;
037import org.ametys.runtime.model.exception.BadDataPathCardinalityException;
038import org.ametys.runtime.model.exception.BadItemTypeException;
039import org.ametys.runtime.model.exception.UndefinedItemPathException;
040import org.ametys.runtime.model.type.DataContext;
041
042/**
043 * Model aware {@link AmetysObject} that can handle data.
044 */
045public interface ModelAwareDataAwareAmetysObject extends DataAwareAmetysObject, ModelAwareDataHolder
046{
047    @Override
048    public ModelAwareDataHolder getDataHolder();
049    
050    public default ModelAwareComposite getComposite(String compositePath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
051    {
052        return getDataHolder().getComposite(compositePath);
053    }
054    
055    public default ModelAwareComposite getLocalComposite(String compositePath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
056    {
057        return getDataHolder().getLocalComposite(compositePath);
058    }
059    
060    public default ModelAwareComposite getExternalComposite(String compositePath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
061    {
062        return getDataHolder().getExternalComposite(compositePath);
063    }
064
065    public default ModelAwareRepeater getRepeater(String repeaterPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
066    {
067        return getDataHolder().getRepeater(repeaterPath);
068    }
069
070    public default ModelAwareRepeater getLocalRepeater(String repeaterPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
071    {
072        return getDataHolder().getLocalRepeater(repeaterPath);
073    }
074
075    public default ModelAwareRepeater getExternalRepeater(String repeaterPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
076    {
077        return getDataHolder().getExternalRepeater(repeaterPath);
078    }
079    
080    public default boolean hasValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
081    {
082        return DataAwareAmetysObject.super.hasValue(dataPath);
083    }
084    
085    public default boolean hasLocalValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
086    {
087        return getDataHolder().hasLocalValue(dataPath);
088    }
089    
090    public default boolean hasExternalValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
091    {
092        return getDataHolder().hasExternalValue(dataPath);
093    }
094    
095    public default boolean hasValueOrEmpty(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
096    {
097        return DataAwareAmetysObject.super.hasValueOrEmpty(dataPath);
098    }
099    
100    public default boolean hasLocalValueOrEmpty(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
101    {
102        return getDataHolder().hasLocalValueOrEmpty(dataPath);
103    }
104    
105    public default boolean hasExternalValueOrEmpty(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException
106    {
107        return getDataHolder().hasExternalValueOrEmpty(dataPath);
108    }
109    
110    default boolean hasComments(String dataName) throws IllegalArgumentException, UndefinedItemPathException
111    {
112        return getDataHolder().hasComments(dataName);
113    }
114
115    public default <T extends Object> T getValue(String dataPath, boolean allowMultiValuedPathSegments) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
116    {
117        return getDataHolder().getValue(dataPath, allowMultiValuedPathSegments);
118    }
119    
120    public default <T> T getValue(String dataPath, boolean useDefaultFromModel, T defaultValue) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
121    {
122        return getDataHolder().getValue(dataPath, useDefaultFromModel, defaultValue);
123    }
124    
125    public default <T> T getLocalValue(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
126    {
127        return getDataHolder().getLocalValue(dataPath);
128    }
129    
130    public default <T> T getExternalValue(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
131    {
132        return getDataHolder().getExternalValue(dataPath);
133    }
134    
135    public default ExternalizableDataStatus getStatus(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, BadDataPathCardinalityException
136    {
137        return getDataHolder().getStatus(dataPath);
138    }
139    
140    default List<DataComment> getComments(String dataName) throws IllegalArgumentException, UndefinedItemPathException
141    {
142        return getDataHolder().getComments(dataName);
143    }
144    
145    @SuppressWarnings("unchecked")
146    public default Collection<? extends Model> getModel()
147    {
148        return (Collection<? extends Model>) getDataHolder().getModel();
149    }
150    
151    public default ModelItem getDefinition(String path) throws IllegalArgumentException, UndefinedItemPathException
152    {
153        return getDataHolder().getDefinition(path);
154    }
155    
156    default boolean hasDefinition(String path) throws IllegalArgumentException
157    {
158        return getDataHolder().hasDefinition(path);
159    }
160    
161    public default Collection<String> getDataNames()
162    {
163        return getDataHolder().getDataNames();
164    }
165    
166    public default void dataToSAX(ContentHandler contentHandler, ViewItemAccessor viewItemAccessor, DataContext context) throws SAXException, BadItemTypeException
167    {
168        getDataHolder().dataToSAX(contentHandler, viewItemAccessor, context);
169    }
170    
171    public default void dataToSAXForEdition(ContentHandler contentHandler, ViewItemAccessor viewItemAccessor, DataContext context) throws SAXException, BadItemTypeException
172    {
173        getDataHolder().dataToSAXForEdition(contentHandler, viewItemAccessor, context);
174    }
175    
176    public default Map<String, Object> dataToJSON(ViewItemAccessor viewItemAccessor, DataContext context) throws BadItemTypeException
177    {
178        return getDataHolder().dataToJSON(viewItemAccessor, context);
179    }
180    
181    public default Map<String, Object> dataToJSONForEdition(ViewItemAccessor viewItemAccessor, DataContext context) throws BadItemTypeException
182    {
183        return getDataHolder().dataToJSONForEdition(viewItemAccessor, context);
184    }
185    
186    public default Map<String, Object> dataToMap(ViewItemAccessor viewItemAccessor, DataContext context)
187    {
188        return getDataHolder().dataToMap(viewItemAccessor, context);
189    }
190    
191    /**
192     * Check if there are differences between the given values and the current ones
193     * @param values the values to check
194     * @return <code>true</code> if there are differences, <code>false</code> otherwise
195     * @throws UndefinedItemPathException if a key in the given Map refers to a data that is not defined by the model
196     * @throws BadItemTypeException if the type defined by the model of one of the Map's key doesn't match the corresponding value
197     */
198    public default boolean hasDifferences(Map<String, Object> values) throws UndefinedItemPathException, BadItemTypeException
199    {
200        return hasDifferences(values, SynchronizationContext.newInstance());
201    }
202    
203    /**
204     * Check if there are differences between the given values and the current ones
205     * @param values the values to check
206     * @param context the context of the synchronization
207     * @return <code>true</code> if there are differences, <code>false</code> otherwise
208     * @throws UndefinedItemPathException if a key in the given Map refers to a data that is not defined by the model
209     * @throws BadItemTypeException if the type defined by the model of one of the Map's key doesn't match the corresponding value
210     */
211    public default boolean hasDifferences(Map<String, Object> values, SynchronizationContext context) throws UndefinedItemPathException, BadItemTypeException
212    {
213        ViewItemAccessor viewItemAccessor = DataHolderHelper.createViewItemAccessorFromValues(getModel(), values);
214        return hasDifferences(viewItemAccessor, values, context);
215    }
216    
217    public default boolean hasDifferences(ViewItemAccessor viewItemAccessor, Map<String, Object> values) throws UndefinedItemPathException, BadItemTypeException
218    {
219        return hasDifferences(viewItemAccessor, values, SynchronizationContext.newInstance());
220    }
221    
222    public default boolean hasDifferences(ViewItemAccessor viewItemAccessor, Map<String, Object> values, SynchronizationContext context) throws UndefinedItemPathException, BadItemTypeException
223    {
224        Map<String, Object> convertedValues = DataHolderHelper.convertValues(viewItemAccessor, values, context.ignoreIncompatibleValues()
225                                                                                                            ? DataHolderHelper::convertValueIgnoringIncompatibleOnes
226                                                                                                            : DataHolderHelper::convertValue);
227        return getDataHolder().hasDifferences(viewItemAccessor, convertedValues, context);
228    }
229
230    /**
231     * Get the collection of model items where there are differences between the given values and the current ones
232     * @param values the values to check
233     * @return a collection of model items with differences
234     * @throws UndefinedItemPathException if a key in the given Map refers to a data that is not defined by the model
235     * @throws BadItemTypeException if the type defined by the model of one of the Map's key doesn't match the corresponding value
236     */
237    public default Collection<ModelItem> getDifferences(Map<String, Object> values) throws UndefinedItemPathException, BadItemTypeException
238    {
239        return getDifferences(values, SynchronizationContext.newInstance());
240    }
241    
242    /**
243     * Get the collection of model items where there are differences between the given values and the current ones
244     * @param values the values to check
245     * @param context the context of the synchronization
246     * @return a collection of model items with differences
247     * @throws UndefinedItemPathException if a key in the given Map refers to a data that is not defined by the model
248     * @throws BadItemTypeException if the type defined by the model of one of the Map's key doesn't match the corresponding value
249     */
250    public default Collection<ModelItem> getDifferences(Map<String, Object> values, SynchronizationContext context) throws UndefinedItemPathException, BadItemTypeException
251    {
252        ViewItemAccessor viewItemAccessor = DataHolderHelper.createViewItemAccessorFromValues(getModel(), values);
253        return getDifferences(viewItemAccessor, values, context);
254    }
255    
256    public default Collection<ModelItem> getDifferences(ViewItemAccessor viewItemAccessor, Map<String, Object> values) throws UndefinedItemPathException, BadItemTypeException
257    {
258        return getDifferences(viewItemAccessor, values, SynchronizationContext.newInstance());
259    }
260    
261    public default Collection<ModelItem> getDifferences(ViewItemAccessor viewItemAccessor, Map<String, Object> values, SynchronizationContext context) throws UndefinedItemPathException, BadItemTypeException
262    {
263        Map<String, Object> convertedValues = DataHolderHelper.convertValues(viewItemAccessor, values, context.ignoreIncompatibleValues()
264                                                                                                            ? DataHolderHelper::convertValueIgnoringIncompatibleOnes
265                                                                                                            : DataHolderHelper::convertValue);
266        return getDataHolder().getDifferences(viewItemAccessor, convertedValues, context);
267    }
268    
269    public default Optional<? extends ModelAwareDataHolder> getParentDataHolder()
270    {
271        return getDataHolder().getParentDataHolder();
272    }
273    
274    public default ModelAwareDataHolder getRootDataHolder()
275    {
276        return getDataHolder().getRootDataHolder();
277    }
278}