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