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.type;
017
018import java.util.Optional;
019import java.util.stream.Stream;
020
021import org.apache.avalon.framework.configuration.Configuration;
022import org.apache.avalon.framework.configuration.ConfigurationException;
023import org.apache.commons.lang3.tuple.Triple;
024import org.w3c.dom.Element;
025
026import org.ametys.runtime.model.compare.DataChangeType;
027import org.ametys.runtime.model.compare.DataChangeTypeDetail;
028import org.ametys.runtime.model.exception.BadItemTypeException;
029
030/**
031 * Interface for element types
032 * @param <T> Type of the element value
033 */
034public interface ElementType<T> extends ModelItemType
035{
036    /**
037     * Cast the given value to an object of the corresponding type.<br>
038     * It may be an untyped String value, or another Object, depending of what the type is actually compatible with.
039     * @param value the value to cast
040     * @return An object of the parameterized type representing the given value. Returns null if value cannot be cast
041     * @throws BadItemTypeException if the given value can't be cast to the type
042     */
043    public T castValue(Object value) throws BadItemTypeException;
044    
045    /**
046     * Cast a typed value to a String
047     * @param value the value to cast
048     * @return the String representation of the value
049     */
050    public String toString(T value);
051    
052    /**
053     * Convert the given client side JSON object to the types value 
054     * @param json the JSON object to convert
055     * @param context the context of the data to retrieve
056     * @return the typed value corresponding to the JSON object
057     */
058    public Object fromJSONForClient(Object json, DataContext context);
059    
060    /**
061     * Parses the given configuration to get the typed value
062     * @param configuration the configuration to parse
063     * @return The typed value in the configuration
064     * @throws ConfigurationException if an error occurs while parsing the configuration
065     */
066    public T parseConfiguration(Configuration configuration) throws ConfigurationException;
067    
068    /**
069     * Parses the given DOM node to get the typed value
070     * @param parent the DOM element containing the value
071     * @param name the name of the item to read
072     * @param additionalData additional data needed to get the typed value
073     * @return the value
074     */
075    public Object valueFromXML(Element parent, String name, Optional<Object> additionalData);
076    
077    /**
078     * Compares the given values and retrieves the changes as a stream of {@link Triple}s. A {@link Triple} contains:
079     * <ul>
080     * <li>the general type of the change (added, modified or removed) as a {@link DataChangeType},</li>
081     * <li>some details about this change if possible (after or before for a date, more or less for a number, ...) as a {@link DataChangeTypeDetail}</li>
082     * <li>The data concerned by this change if not the element itself (or an empty String)</li>
083     * </ul>
084     * @param value1 the 1st value
085     * @param value2 the 2nd value
086     * @return the changes between the two given values as a stream of {@link Triple}. Retrieves an empty stream if there is no change
087     */
088    public Stream<Triple<DataChangeType, DataChangeTypeDetail, String>> compareValues(Object value1, Object value2);
089    
090    /**
091     * Checks if the value is compatible with the element type 
092     * @param value the value to check
093     * @return <code>true</code> if the value matches the current type, <code>false</code> otherwise
094     */
095    public boolean isCompatible(Object value);
096    
097    /**
098     * Determines if this type is simple or not.
099     * A simple element type is a type of elements that can be edited in a grid
100     * @return <code>true</code> if the type is simple, <code>false</code> otherwise
101     */
102    public boolean isSimple();
103    
104    /**
105     * Get the class managed by the implementation
106     * @return The class managed (T.class)
107     */
108    public Class<T> getManagedClass();
109
110    /**
111     * Get the class representing an array of managed class by the implementation
112     * @return The class managed (T[].class)
113     */
114    public Class<T[]> getManagedClassArray();
115}