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.xml;
017
018import java.util.ArrayList;
019import java.util.List;
020
021import org.apache.avalon.framework.configuration.Configuration;
022import org.apache.cocoon.xml.XMLUtils;
023import org.apache.commons.lang3.StringUtils;
024import org.xml.sax.ContentHandler;
025import org.xml.sax.SAXException;
026
027import org.ametys.runtime.model.exception.BadItemTypeException;
028import org.ametys.runtime.model.type.ElementType;
029
030/**
031 * Interfaces for XML parameter types
032 * @param <T> Type of the parameter value
033 */
034public interface XMLElementType<T> extends ElementType<T>
035{
036    /**
037     * Read the value in the given XML configuration
038     * @param parentConfiguration XML configuration containing the value
039     * @param name the name of the element to read
040     * @return the value
041     * @throws BadItemTypeException if the reading value doesn't match this element type
042     */
043    public default Object read(Configuration parentConfiguration, String name) throws BadItemTypeException
044    {
045        Configuration elementConfiguration = parentConfiguration.getChild(name);
046        
047        return readValueFromNode(elementConfiguration, name);
048    }
049    
050    /**
051     * Read the value in the given XML configuration (the node directly, not the parent configuration)
052     * @param elementConfiguration XML configuration node containing the value
053     * @param name the name of the element to read
054     * @return the value
055     * @throws BadItemTypeException if the reading value doesn't match this element type
056     */
057    public default Object readValueFromNode(Configuration elementConfiguration, String name) throws BadItemTypeException
058    {
059        if (elementConfiguration == null)
060        {
061            return null;
062        }
063        
064        // Multiple element management
065        Configuration[] valuesConfiguration = elementConfiguration.getChildren("value");
066        if (valuesConfiguration.length > 0)
067        {
068            List<Object> values = new ArrayList<>();
069            for (Configuration valueConfiguration : valuesConfiguration)
070            {
071                String value = valueConfiguration.getChild(name).getValue(null);
072                if (value != null)
073                {
074                    values.add(castValue(value));
075                }
076            }
077            return values.toArray(new Object[values.size()]);
078        }
079        
080        // Simple element management
081        String value = elementConfiguration.getValue(null);
082        return castValue(value);
083    }
084    
085    /**
086     * Write the value into the given content handler
087     * @param contentHandler the content handler where to SAX into.
088     * @param name the name of the element to write
089     * @param value the value to write
090     * @throws SAXException if an errors occurs during the value writing
091     * @throws BadItemTypeException If the given value doesn't match this element type
092     */
093    @SuppressWarnings("unchecked")
094    public default void write(ContentHandler contentHandler, String name, Object value) throws SAXException, BadItemTypeException
095    {
096        if (value == null)
097        {
098            XMLUtils.createElement(contentHandler, name);
099        }
100        else if (getManagedClass().isInstance(value))
101        {
102            XMLUtils.createElement(contentHandler, name, StringUtils.defaultString(toString((T) value)));
103        }
104        else if (getManagedClassArray().isInstance(value))
105        {
106            XMLUtils.startElement(contentHandler, name);
107            for (T singleValue : (T[]) value)
108            {
109                XMLUtils.createElement(contentHandler, "value", StringUtils.defaultString(toString(singleValue)));
110            }
111            XMLUtils.endElement(contentHandler, name);
112        }
113        else
114        {
115            throw new BadItemTypeException("Try to write the non " + getManagedClass().getName() + " value '" + value + "' on element named '" + name + "'");
116        }
117    }
118}