001/*
002 * Units of Measurement Jakarta JSON-B Library
003 * Copyright (c) 2005-2021, Werner Keil and others.
004 *
005 * All rights reserved.
006 *
007 * Redistribution and use in source and binary forms, with or without modification,
008 * are permitted provided that the following conditions are met:
009 *
010 * 1. Redistributions of source code must retain the above copyright notice,
011 *    this list of conditions and the following disclaimer.
012 *
013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
014 *    and the following disclaimer in the documentation and/or other materials provided with the distribution.
015 *
016 * 3. Neither the name of JSR-385, Indriya nor the names of their contributors may be used to endorse or promote products
017 *    derived from this software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package tech.uom.lib.yasson;
031
032import java.lang.reflect.Type;
033import java.util.HashMap;
034import java.util.Map;
035import java.util.Set;
036import java.util.stream.Collectors;
037
038import javax.json.JsonObject;
039import javax.json.bind.serializer.DeserializationContext;
040import javax.json.bind.serializer.JsonbDeserializer;
041import javax.json.stream.JsonParser;
042import javax.measure.Dimension;
043import tech.units.indriya.unit.UnitDimension;
044
045/**
046 * @author Werner Keil
047 * @version 0.8
048 */
049public class DimensionJsonDeserializer implements JsonbDeserializer<Dimension> {
050
051        // TODO make this available package-local
052    private static Dimension parseBaseDimension(String symbol) {
053        switch (symbol) {
054            case "[N]":
055                return UnitDimension.AMOUNT_OF_SUBSTANCE;
056            case "[I]":
057                return UnitDimension.ELECTRIC_CURRENT;
058            case "[L]":
059                return UnitDimension.LENGTH;
060            case "[J]":
061                return UnitDimension.LUMINOUS_INTENSITY;
062            case "[M]":
063                return UnitDimension.MASS;
064            case "[\u0398]":
065                return UnitDimension.TEMPERATURE;
066            case "[T]":
067                return UnitDimension.TIME;
068            default:
069                throw new IllegalArgumentException(String.format(
070                        "dimension " + "symbol '%s' not supported, maybe dimensionless or " + "wrong universe?", symbol));
071        }
072    }
073
074    /**
075     * Deserializes a dimension by decomposing it's base dimension map.
076     *
077     * @param parser            the JSON parser
078     * @param ctx                       the DeserializationContext as provided by {@link JsonbDeserializer}
079     * @param runtimeType       the type of the returned object
080     */
081        @Override
082        public Dimension deserialize(JsonParser parser, DeserializationContext ctx, Type runtimeType) {
083                //JsonArray array = parser.getArray(); //.getArrayStream().collect(Collectors.toMap(p -> p.getId(), p -> p));
084                JsonObject obj = parser.getObject();
085                Set<String> keys = obj.keySet();                
086                //Map<String, Integer> baseDimensionsStrings = parser.readValueAs(Map.class);
087                Map<String, Integer> baseDimensionsStrings = new HashMap<>();
088                
089                for (String key : keys) {
090                        baseDimensionsStrings.put(key, obj.getInt(key));
091                }
092                
093        final Map<Dimension, Integer> baseDimensions = new HashMap<>(baseDimensionsStrings.entrySet().stream()
094                .collect(Collectors.toMap(entry -> parseBaseDimension(entry.getKey()), entry -> entry.getValue())));
095        Dimension retValue = UnitDimension.NONE;
096        for (Dimension baseDimension : baseDimensions.keySet()) {
097            int exp = baseDimensions.get(baseDimension);
098            retValue = retValue.multiply(baseDimension.pow(exp));
099        }
100        return retValue;
101        }
102}