All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.amazonaws.protocol.json.internal.MarshallerRegistry Maven / Gradle / Ivy

Go to download

The AWS SDK for Java - Core module holds the classes that are used by the individual service clients to interact with Amazon Web Services. Users need to depend on aws-java-sdk artifact for accessing individual client classes.

There is a newer version: 1.12.778
Show newest version
/*
 * Copyright 2011-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
package com.amazonaws.protocol.json.internal;

import com.amazonaws.SdkClientException;
import com.amazonaws.annotation.SdkInternalApi;
import com.amazonaws.protocol.MarshallLocation;
import com.amazonaws.protocol.MarshallingType;
import com.amazonaws.protocol.StructuredPojo;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

@SdkInternalApi
public class MarshallerRegistry {

    private final Map>> marshallers;
    private final Set> marshallingTypes;
    private final Map, MarshallingType> marshallingTypeCache;

    private MarshallerRegistry(Builder builder) {
        this.marshallers = builder.marshallers;
        this.marshallingTypes = builder.marshallingTypes;
        this.marshallingTypeCache = new HashMap, MarshallingType>(marshallingTypes.size());

    }

    public  JsonMarshaller getMarshaller(MarshallLocation marshallLocation, T val) {
        return getMarshaller(marshallLocation, toMarshallingType(val));
    }

    public  JsonMarshaller getMarshaller(MarshallLocation marshallLocation, MarshallingType marshallingType, T val) {
        return getMarshaller(marshallLocation,
                             val == null ? MarshallingType.NULL : marshallingType);
    }

    @SuppressWarnings("unchecked")
    private  JsonMarshaller getMarshaller(MarshallLocation marshallLocation, MarshallingType marshallingType) {
        return (JsonMarshaller) marshallers.get(marshallLocation).get(marshallingType);
    }

    @SuppressWarnings("unchecked")
    public  MarshallingType toMarshallingType(T val) {
        if (val == null) {
            return (MarshallingType) MarshallingType.NULL;
        } else if (val instanceof StructuredPojo) {
            // We don't want to cache every single POJO type so we make a special case of it here.
            return (MarshallingType) MarshallingType.STRUCTURED;
        } else if (!marshallingTypeCache.containsKey(val.getClass())) {
            return (MarshallingType) populateMarshallingTypeCache(val.getClass());
        }
        return (MarshallingType) marshallingTypeCache.get(val.getClass());
    }

    private MarshallingType populateMarshallingTypeCache(Class clzz) {
        synchronized (marshallingTypeCache) {
            if (!marshallingTypeCache.containsKey(clzz)) {
                for (MarshallingType marshallingType : marshallingTypes) {
                    if (marshallingType.isDefaultMarshallerForType(clzz)) {
                        marshallingTypeCache.put(clzz, marshallingType);
                        return marshallingType;
                    }
                }
                throw new SdkClientException("MarshallingType not found for class " + clzz);
            }
        }
        return marshallingTypeCache.get(clzz);
    }

    /**
     * Merge the given overrides with 'this' registry. Overrides are higher precedence than 'this' registry. Both 'this'
     * registry and the override registry are immutable so a new registry object is returned. If the marshallerRegistryOverrides
     * are null then this method just returns the current registry since there is nothing to merge.
     *
     * @param marshallerRegistryOverrides Override registry.
     * @return New {@link MarshallerRegistry} with marshallers merged.
     */
    public MarshallerRegistry merge(MarshallerRegistry.Builder marshallerRegistryOverrides) {
        if(marshallerRegistryOverrides == null) {
            return this;
        }
        Builder merged = MarshallerRegistry.builder();
        merged.copyMarshallersFromRegistry(this.marshallers);
        merged.copyMarshallersFromRegistry(marshallerRegistryOverrides.marshallers);
        return merged.build();
    }

    /**
     * @return Builder instance to construct a {@link MarshallerRegistry}.
     */
    public static Builder builder() {
        return new Builder();
    }

    /**
     * Builder for a {@link MarshallerRegistry}.
     */
    public static final class Builder {

        private final Map>> marshallers
                = new HashMap>>();
        private final Set> marshallingTypes
                = new HashSet>();

        private Builder() {
        }

        public  Builder payloadMarshaller(MarshallingType marshallingType,
                                             JsonMarshaller marshaller) {
            return addMarshaller(MarshallLocation.PAYLOAD, marshallingType, marshaller);
        }

        public  Builder headerMarshaller(MarshallingType marshallingType,
                                            JsonMarshaller marshaller) {
            return addMarshaller(MarshallLocation.HEADER, marshallingType, marshaller);
        }

        public  Builder queryParamMarshaller(MarshallingType marshallingType,
                                                JsonMarshaller marshaller) {
            return addMarshaller(MarshallLocation.QUERY_PARAM, marshallingType, marshaller);
        }

        public  Builder pathParamMarshaller(MarshallingType marshallingType,
                                               JsonMarshaller marshaller) {
            return addMarshaller(MarshallLocation.PATH, marshallingType, marshaller);
        }

        public  Builder greedyPathParamMarshaller(MarshallingType marshallingType,
                                                     JsonMarshaller marshaller) {
            return addMarshaller(MarshallLocation.GREEDY_PATH, marshallingType, marshaller);
        }

        public  Builder addMarshaller(MarshallLocation marshallLocation,
                                         MarshallingType marshallingType,
                                         JsonMarshaller marshaller) {
            marshallingTypes.add(marshallingType);
            if (!marshallers.containsKey(marshallLocation)) {
                marshallers.put(marshallLocation, new HashMap>());
            }
            marshallers.get(marshallLocation).put(marshallingType, marshaller);
            return this;
        }

        /**
         * @return An immutable {@link MarshallerRegistry} object.
         */
        public MarshallerRegistry build() {
            return new MarshallerRegistry(this);
        }

        /**
         * Fill this builder with marshallers from the source {@link MarshallerRegistry}. Will overwrite anything that is
         * registered with the same location and type.
         *
         * @param sourceMarshallers Marshallers to copy in.
         */
        private void copyMarshallersFromRegistry(
                Map>> sourceMarshallers) {

            for (Map.Entry>> byLocationEntry :
                    sourceMarshallers.entrySet()) {
                for (Map.Entry> byTypeEntry : byLocationEntry.getValue().entrySet()) {
                    this.addMarshaller(byLocationEntry.getKey(), byTypeEntry.getKey(), byTypeEntry.getValue());
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy