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.plugins.repository.data.holder;
017
018import java.util.Collection;
019import java.util.List;
020import java.util.Map;
021import java.util.Optional;
022
023import org.apache.commons.lang3.StringUtils;
024import org.xml.sax.ContentHandler;
025import org.xml.sax.SAXException;
026
027import org.ametys.plugins.repository.data.DataComment;
028import org.ametys.plugins.repository.data.external.ExternalizableDataProvider.ExternalizableDataStatus;
029import org.ametys.plugins.repository.data.holder.group.ModelAwareComposite;
030import org.ametys.plugins.repository.data.holder.group.ModelAwareRepeater;
031import org.ametys.plugins.repository.data.holder.impl.DataHolderHelper;
032import org.ametys.plugins.repository.model.RepeaterDefinition;
033import org.ametys.runtime.model.ElementDefinition;
034import org.ametys.runtime.model.ModelHelper;
035import org.ametys.runtime.model.ModelItem;
036import org.ametys.runtime.model.ModelItemContainer;
037import org.ametys.runtime.model.ViewHelper;
038import org.ametys.runtime.model.ViewItemAccessor;
039import org.ametys.runtime.model.exception.BadDataPathCardinalityException;
040import org.ametys.runtime.model.exception.BadItemTypeException;
041import org.ametys.runtime.model.exception.UndefinedItemPathException;
042import org.ametys.runtime.model.type.DataContext;
043import org.ametys.runtime.model.type.ModelItemType;
044
045/**
046 * Interface for data containers with models
047 */
048public interface ModelAwareDataHolder extends DataHolder
049{
050    /** Suffix used for the alternative value */
051    public static final String ALTERNATIVE_SUFFIX = "__alt";
052    /** Suffix used for the status value */
053    public static final String STATUS_SUFFIX = "__status";
054    /** Suffix used for the comments */
055    public static final String COMMENTS_SUFFIX = "_comments";
056    
057    /**
058     * {@inheritDoc}
059     * @throws UndefinedItemPathException if the given composite path is not defined by the model
060     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 
061     */
062    public ModelAwareComposite getComposite(String compositePath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException;
063    
064    /**
065     * Retrieves the local composite at the given path
066     * @param compositePath path of the externalizable composite to retrieve
067     * @return the composite or <code>null</code> if not exists or is empty
068     * @throws IllegalArgumentException if the given composite path is null or empty
069     * @throws BadItemTypeException if the stored value at the given path is not a composite
070     * @throws UndefinedItemPathException if the given composite path is not defined by the model
071     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 
072     */
073    public ModelAwareComposite getLocalComposite(String compositePath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException;
074    
075    /**
076     * Retrieves the external composite at the given path
077     * @param compositePath path of the externalizable composite to retrieve
078     * @return the composite or <code>null</code> if not exists or is empty
079     * @throws IllegalArgumentException if the given composite path is null or empty
080     * @throws BadItemTypeException if the stored value at the given path is not a composite
081     * @throws UndefinedItemPathException if the given composite path is not defined by the model
082     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple 
083     */
084    public ModelAwareComposite getExternalComposite(String compositePath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException;
085    
086    /**
087     * Retrieves the repeater at the given path
088     * @param repeaterPath path of the repeater to retrieve
089     * @return the repeater or <code>null</code> if not exists or is empty
090     * @throws IllegalArgumentException if the given repeater path is null or empty
091     * @throws BadItemTypeException if the stored value at the given path is not a repeater
092     * @throws UndefinedItemPathException if the given repeater path is not defined by the model
093     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
094     */
095    public ModelAwareRepeater getRepeater(String repeaterPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException;
096    
097    /**
098     * Retrieves the local repeater at the given path
099     * @param repeaterPath path of the externalizable repeater to retrieve
100     * @return the repeater or <code>null</code> if not exists or is empty
101     * @throws IllegalArgumentException if the given repeater path is null or empty
102     * @throws BadItemTypeException if the stored value at the given path is not a repeater
103     * @throws UndefinedItemPathException if the given repeater path is not defined by the model
104     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
105     */
106    public ModelAwareRepeater getLocalRepeater(String repeaterPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException;
107    
108    /**
109     * Retrieves the external repeater at the given path
110     * @param repeaterPath path of the externalizable repeater to retrieve
111     * @return the repeater or <code>null</code> if not exists or is empty
112     * @throws IllegalArgumentException if the given repeater path is null or empty
113     * @throws BadItemTypeException if the stored value at the given path is not a repeater
114     * @throws UndefinedItemPathException if the given repeater path is not defined by the model
115     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
116     */
117    public ModelAwareRepeater getExternalRepeater(String repeaterPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException;
118    
119    /**
120     * {@inheritDoc}
121     * @return <code>true</code> if the data at the given path is defined by the model, if there is a non empty value for the data and if the type of this value matches the type of the definition. <code>false</code> otherwise
122     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
123     */
124    @Override
125    public boolean hasValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException;
126    
127    /**
128     * Checks if there is a non empty local value for the data at the given path
129     * @param dataPath path of the externalizable data
130     * @return <code>true</code> if the data at the given path is defined by the model, if there is a non empty local value for the data and if the type of this value matches the type of the definition. <code>false</code> otherwise
131     * @throws IllegalArgumentException if the given data path is null or empty
132     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
133     */
134    public boolean hasLocalValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException;
135    
136    /**
137     * Checks if there is a non empty external value for the data at the given path
138     * @param dataPath path of the externalizable data
139     * @return <code>true</code> if the data at the given path is defined by the model, if there is a non empty external value for the data and if the type of this value matches the type of the definition. <code>false</code> otherwise
140     * @throws IllegalArgumentException if the given data path is null or empty
141     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
142     */
143    public boolean hasExternalValue(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException;
144    
145    /**
146     * {@inheritDoc}
147     * @return <code>true</code> if the data at the given path is defined by the model, if there is a value for the data, even empty, and if the type of this value matches the type of the definition. <code>false</code> otherwise
148     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
149     */
150    @Override
151    public boolean hasValueOrEmpty(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException;
152    
153    /**
154     * Checks if there is a local value for the data at the given path
155     * @param dataPath path of the externalizable data
156     * @return <code>true</code> if the data at the given path is defined by the model, if there is a local value for the data, even empty, and if the type of this value matches the type of the definition. <code>false</code> otherwise
157     * @throws IllegalArgumentException if the given data path is null or empty
158     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
159     */
160    public boolean hasLocalValueOrEmpty(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException;
161    
162    /**
163     * Checks if there is an external value for the data at the given path
164     * @param dataPath path of the externalizable data
165     * @return <code>true</code> if the data at the given path is defined by the model, if there is an external value for the data, even empty, and if the type of this value matches the type of the definition. <code>false</code> otherwise
166     * @throws IllegalArgumentException if the given data path is null or empty
167     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
168     */
169    public boolean hasExternalValueOrEmpty(String dataPath) throws IllegalArgumentException, BadDataPathCardinalityException;
170    
171    /**
172     * Checks if there is are comments on the data with the given name
173     * @param dataName name of the data
174     * @return <code>true</code> if there are comments on the data, <code>false</code> otherwise
175     * @throws IllegalArgumentException if the given data name is null or empty
176     * @throws UndefinedItemPathException if the given data name is not defined by the model
177     */
178    public boolean hasComments(String dataName) throws IllegalArgumentException, UndefinedItemPathException;
179    
180    /**
181     * {@inheritDoc}
182     * @return the names of the data contained by this data holder and that are defined by the model
183     */
184    @Override
185    public Collection<String> getDataNames();
186    
187    /**
188     * Retrieves the value of the data at the given path
189     * @param <T> type of the value to retrieve
190     * @param dataPath path of the data
191     * @return the value of the data or <code>null</code> if not exists or is empty. The object returned may be of a generic class defined by the storage (if the model is unknown). For example, an url may be returned as a String.
192     * @throws IllegalArgumentException if the given data path is null or empty
193     * @throws UndefinedItemPathException if the given data path is not defined by the model
194     * @throws BadItemTypeException if the type defined by the model doesn't match the type of the stored value
195     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
196     */
197    public default <T extends Object> T getValue(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException
198    {
199        return getValue(dataPath, false);
200    }
201    
202    /**
203     * Retrieves the value of the data at the given path
204     * @param <T> type of the value to retrieve
205     * @param dataPath path of the data 
206     * @param allowMultiValuedPathSegments <code>true</code> to allow multi-valued segments in the path (not necessarily at the last segment), <code>false</code> otherwise.
207     *      If <code>true</code>, if there is no indicated entry for a repeater, the values of all the entries are retrieved
208     *      If <code>true</code> and if there are multiple values, all data are retrieved in one array
209     * @return the value of the data or <code>null</code> if allowMultiValuedPathSegments is <code>false</code> and there is no non empty value. The object returned may be of a generic class defined by the storage (if the model is unknown). For example, an url may be returned as a String.
210     * @throws IllegalArgumentException if the given data path is null or empty
211     * @throws UndefinedItemPathException if the given data path is not defined by the model
212     * @throws BadItemTypeException if the type defined by the model doesn't match the type of the stored value
213     * @throws BadDataPathCardinalityException if the managesMultiples boolean is <code>false</code> and the definition of a part of the data path is multiple. Only the last part can be multiple
214     */
215    public <T extends Object> T getValue(String dataPath, boolean allowMultiValuedPathSegments) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException;
216    
217    /**
218     * Retrieves the value of the data at the given path, or the default value
219     * The returned value is one of those ones, in the order:
220     * <ol>
221     * <li>The value of the data if exists and is not empty</li>
222     * <li>The default value from the model if useDefaultFromModel is <code>true</code> and there is a default value defined by the model</li>
223     * <li>The given default value</li>
224     * </ol>
225     * @param <T> type of the value to retrieve
226     * @param dataPath path of the data
227     * @param useDefaultFromModel true to use the default value from the model, false to use the given default value
228     * @param defaultValue default value used if value is null and useDefaultFromModel is false, or if there is no default value on model
229     * @return the value of the data at the given path
230     * @throws IllegalArgumentException if the given data path is null or empty
231     * @throws UndefinedItemPathException if the given data path is not defined by the model
232     * @throws BadItemTypeException if the type defined by the model doesn't match the type of the stored value
233     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
234     */
235    public <T extends Object> T getValue(String dataPath, boolean useDefaultFromModel, T defaultValue) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException;
236    
237    /**
238     * Retrieves the local value of the data at the given path
239     * @param <T> type of the value to retrieve
240     * @param dataPath path of the externalizable data
241     * @return the local value of the data or <code>null</code> if not exists or is empty. The object returned may be of a generic class defined by the storage (if the model is unknown). For example, an url may be returned as a String.
242     * @throws IllegalArgumentException if the given data path is null or empty
243     * @throws UndefinedItemPathException if the given data path is not defined by the model
244     * @throws BadItemTypeException if the type defined by the model doesn't match the type of the stored value
245     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
246     */
247    public <T extends Object> T getLocalValue(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException;
248    
249    /**
250     * Retrieves the external value of the data at the given path
251     * @param <T> type of the value to retrieve
252     * @param dataPath path of the externalizable data
253     * @return the external value of the data or <code>null</code> if not exists or is empty. The object returned may be of a generic class defined by the storage (if the model is unknown). For example, an url may be returned as a String.
254     * @throws IllegalArgumentException if the given data path is null or empty
255     * @throws UndefinedItemPathException if the given data path is not defined by the model
256     * @throws BadItemTypeException if the type defined by the model doesn't match the type of the stored value
257     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
258     */
259    public <T extends Object> T getExternalValue(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, BadItemTypeException, BadDataPathCardinalityException;
260    
261    /**
262     * Retrieves the status of the externalizable data at the given path
263     * Warning: This method won't check that your data is externalizable. But there is no sense to call it with a non externalizable data
264     * @param dataPath path of the externalizable data
265     * @return the status of the externalizable data at the given path
266     * @throws IllegalArgumentException if the given data path is null or empty
267     * @throws UndefinedItemPathException if the given data path is not defined by the model
268     * @throws BadDataPathCardinalityException if the definition of a part of the data path is multiple. Only the last part can be multiple
269     */
270    public ExternalizableDataStatus getStatus(String dataPath) throws IllegalArgumentException, UndefinedItemPathException, BadDataPathCardinalityException;
271    
272    /**
273     * Retrieve the comments of the data with the given name
274     * @param dataName name of the data
275     * @return the comments of the data
276     * @throws IllegalArgumentException if the given data name is null or empty
277     * @throws UndefinedItemPathException if the given data name is not defined by the model
278     */
279    public List<DataComment> getComments(String dataName) throws IllegalArgumentException, UndefinedItemPathException;
280    
281    /**
282     * Checks if the definition of the element at the given path is multiple
283     * @param path path of the element. No matter if it is a definition or data path (with repeater entry positions)
284     * @return <code>true</code> if the element is multiple, <code>false</code> otherwise
285     * @throws IllegalArgumentException if the given path is null or empty
286     * @throws UndefinedItemPathException if the given path is not defined by the model
287     */
288    public default boolean isMultiple(String path) throws IllegalArgumentException, UndefinedItemPathException
289    {
290        ModelItem item = getDefinition(path);
291        if (item instanceof ElementDefinition)
292        {
293            return ((ElementDefinition) item).isMultiple();
294        }
295        else if (item instanceof RepeaterDefinition)
296        {
297            // If the given path represents a repeater , but with no specified entry, consider the data as multiple
298            return !DataHolderHelper.isRepeaterEntryPath(path);
299        }
300        else
301        {
302            // Composites are not multiples
303            return false;
304        }
305    }
306    
307    /**
308     * Retrieves the type of the data at the given path
309     * @param <X> type of the item type
310     * @param path path of the data. No matter if it is a definition or data path (with repeater entry positions)
311     * @return the type of the data
312     * @throws IllegalArgumentException if the given data path is null or empty
313     * @throws UndefinedItemPathException if the given data path is not defined by the model
314     */
315    @SuppressWarnings("unchecked")
316    public default <X extends ModelItemType> X getType(String path) throws IllegalArgumentException, UndefinedItemPathException
317    {
318        return (X) getDefinition(path).getType();
319    }
320    
321    /**
322     * Retrieves the data holder's model
323     * @return the data holder's model
324     */
325    public Collection<? extends ModelItemContainer> getModel();
326    
327    /**
328     * Retrieves the definition of the data at the given path
329     * @param path path of the data. No matter if it is a definition or data path (with repeater entry positions)
330     * @return the definition of the data
331     * @throws IllegalArgumentException if the given path is null or empty
332     * @throws UndefinedItemPathException if the given path is not defined by the model
333     */
334    public default ModelItem getDefinition(String path) throws IllegalArgumentException, UndefinedItemPathException
335    {
336        return ModelHelper.getModelItem(path, getModel());
337    }
338    
339    /**
340     * Checks if there is a definition at the given path
341     * @param path path of the data. No matter if it is a definition or data path (with repeater entry positions)
342     * @return <code>true</code> if there is definition at the given path, <code>false</code> otherwise
343     * @throws IllegalArgumentException if the given path is null or empty
344     */
345    public default boolean hasDefinition(String path) throws IllegalArgumentException
346    {
347        try
348        {
349            getDefinition(path);
350            return true;
351        }
352        catch (UndefinedItemPathException e)
353        {
354            return false;
355        }
356    }
357    
358    /**
359     * Generates SAX events for the data in the model of the current {@link DataHolder}
360     * @param contentHandler the {@link ContentHandler} that will receive the SAX events
361     * @throws SAXException if an error occurs during the SAX events generation
362     * @throws BadItemTypeException if the saxed value's type does not matches the stored data
363     */
364    public default void dataToSAX(ContentHandler contentHandler) throws SAXException, BadItemTypeException
365    {
366        dataToSAX(contentHandler, DataContext.newInstance());
367    }
368    
369    /**
370     * Generates SAX events for the data in the model of the current {@link DataHolder}
371     * @param contentHandler the {@link ContentHandler} that will receive the SAX events
372     * @param context The context of the data to SAX
373     * @throws SAXException if an error occurs during the SAX events generation
374     * @throws BadItemTypeException if the saxed value's type does not matches the stored data
375     */
376    public default void dataToSAX(ContentHandler contentHandler, DataContext context) throws SAXException, BadItemTypeException
377    {
378        ViewItemAccessor viewItemAccessor = ViewHelper.createViewItemAccessor(getModel());
379        dataToSAX(contentHandler, viewItemAccessor, context);
380    }
381    
382    /**
383     * Generates SAX events for the data in the given view in the current {@link DataHolder}
384     * @param contentHandler the {@link ContentHandler} that will receive the SAX events
385     * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items for which generate SAX events
386     * @throws SAXException if an error occurs during the SAX events generation
387     * @throws BadItemTypeException if the saxed value's type does not matches the stored data
388     */
389    public default void dataToSAX(ContentHandler contentHandler, ViewItemAccessor viewItemAccessor) throws SAXException, BadItemTypeException
390    {
391        dataToSAX(contentHandler, viewItemAccessor, DataContext.newInstance());
392    }
393    
394    /**
395     * Generates SAX events for the data in the given view in the current {@link DataHolder}
396     * @param contentHandler the {@link ContentHandler} that will receive the SAX events
397     * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items for which generate SAX events
398     * @param context The context of the data to SAX
399     * @throws SAXException if an error occurs during the SAX events generation
400     * @throws BadItemTypeException if the saxed value's type does not matches the stored data
401     */
402    public void dataToSAX(ContentHandler contentHandler, ViewItemAccessor viewItemAccessor, DataContext context) throws SAXException, BadItemTypeException;
403    
404    /**
405     * Generates SAX events for the data in the given view in edition mode in the current {@link DataHolder}
406     * @param contentHandler the {@link ContentHandler} that will receive the SAX events
407     * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items for which generate SAX events
408     * @param context The context of the data to SAX
409     * @throws SAXException if an error occurs during the SAX events generation
410     * @throws BadItemTypeException if the saxed value's type does not matches the stored data
411     */
412    public void dataToSAXForEdition(ContentHandler contentHandler, ViewItemAccessor viewItemAccessor, DataContext context) throws SAXException, BadItemTypeException;
413    
414    /**
415     * Convert the data in the model of the current {@link DataHolder}
416     * @return The data of the current {@link DataHolder} as JSON
417     * @throws BadItemTypeException if the value's type does not matches the stored data
418     */
419    public default Map<String, Object> dataToJSON() throws BadItemTypeException
420    {
421        return dataToJSON(DataContext.newInstance());
422    }
423    
424    /**
425     * Convert the data in the model of the current {@link DataHolder}
426     * @param context The context of the data to convert
427     * @return The data of the current {@link DataHolder} as JSON
428     * @throws BadItemTypeException if the value's type does not matches the stored data
429     */
430    public default Map<String, Object> dataToJSON(DataContext context) throws BadItemTypeException
431    {
432        ViewItemAccessor viewItemAccessor = ViewHelper.createViewItemAccessor(getModel());
433        return dataToJSON(viewItemAccessor, context);
434    }
435    
436    /**
437     * Convert the data in the given view of the current {@link DataHolder}
438     * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items to convert
439     * @return The data of the given view as JSON
440     * @throws BadItemTypeException if the value's type does not matches the stored data
441     */
442    public default Map<String, Object> dataToJSON(ViewItemAccessor viewItemAccessor) throws BadItemTypeException
443    {
444        return dataToJSON(viewItemAccessor, DataContext.newInstance());
445    }
446    
447    /**
448     * Convert the data in the given view of the current {@link DataHolder}
449     * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items to convert
450     * @param context The context of the data to convert
451     * @return The data of the given view as JSON
452     * @throws BadItemTypeException if the value's type does not matches the stored data
453     */
454    public Map<String, Object> dataToJSON(ViewItemAccessor viewItemAccessor, DataContext context) throws BadItemTypeException;
455    
456    /**
457     * Convert the data in the given view in edition mode in the current {@link DataHolder}
458     * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items to convert
459     * @param context The context of the data to convert
460     * @return The data of the given view as JSON
461     * @throws BadItemTypeException if the value's type does not matches the stored data
462     */
463    public Map<String, Object> dataToJSONForEdition(ViewItemAccessor viewItemAccessor, DataContext context) throws BadItemTypeException;
464    
465    /**
466     * Generates SAX events for the comments of the data in the given view in the current {@link DataHolder}
467     * @param contentHandler the {@link ContentHandler} that will receive the SAX events
468     * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items for which generate SAX events
469     * @throws SAXException if an error occurs during the SAX events generation
470     */
471    public default void commentsToSAX(ContentHandler contentHandler, ViewItemAccessor viewItemAccessor) throws SAXException
472    {
473        DataHolderHelper.commentsToSAX(this, contentHandler, viewItemAccessor, StringUtils.EMPTY);
474    }
475    
476    /**
477     * Retrieves all data of this DataHolder as a typed-values Map.
478     * @return a Map containing all data.
479     */
480    public default Map<String, Object> dataToMap()
481    {
482        return dataToMap(DataContext.newInstance());
483    }
484    
485    /**
486     * Retrieves all data of this DataHolder as a typed-values Map.
487     * @param context The context of the data
488     * @return  a Map containing all data.
489     */
490    public default Map<String, Object> dataToMap(DataContext context)
491    {
492        ViewItemAccessor viewItemAccessor = ViewHelper.createViewItemAccessor(getModel());
493        return dataToMap(viewItemAccessor, context);
494    }
495    
496    /**
497     * Retrieves data of this DataHolder as a typed-values Map.
498     * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items to include in the resulting Map
499     * @return a Map containing all data.
500     */
501    public default Map<String, Object> dataToMap(ViewItemAccessor viewItemAccessor)
502    {
503        return dataToMap(viewItemAccessor, DataContext.newInstance());
504    }
505    
506    /**
507     * Retrieves data of this DataHolder as a typed-values Map.
508     * @param viewItemAccessor the {@link ViewItemAccessor} referencing the items to include in the resulting Map
509     * @param context The context of the data
510     * @return a Map containing all data.
511     */
512    public Map<String, Object> dataToMap(ViewItemAccessor viewItemAccessor, DataContext context);
513    
514    @Override
515    public Optional<? extends ModelAwareDataHolder> getParentDataHolder();
516    
517    @Override
518    public ModelAwareDataHolder getRootDataHolder();
519}