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