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

org.apache.cassandra.config.Replacements Maven / Gradle / Ivy

Go to download

The Apache Cassandra Project develops a highly scalable second-generation distributed database, bringing together Dynamo's fully distributed design and Bigtable's ColumnFamily-based data model.

There is a newer version: 5.0-rc1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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 org.apache.cassandra.config;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.cassandra.exceptions.ConfigurationException;

public final class Replacements
{
    private Replacements()
    {
    }

    /**
     * @param klass to get replacements for
     * @return map of old names and replacements needed.
     */
    public static Map, Map> getNameReplacements(Class klass)
    {
        List replacements = getReplacementsRecursive(klass);
        Map, Map> objectOldNames = new HashMap<>();
        for (Replacement r : replacements)
        {
            Map oldNames = objectOldNames.computeIfAbsent(r.parent, ignore -> new HashMap<>());
            if (!oldNames.containsKey(r.oldName))
                oldNames.put(r.oldName, r);
            else
            {
                throw new ConfigurationException("Invalid annotations, you have more than one @Replaces annotation in " +
                                                 "Config class with same old name(" + r.oldName + ") defined.");
            }
        }
        return objectOldNames;
    }

    /**
     * @param klass to get replacements for
     * @return map of old names and replacements needed.
     */
    private static List getReplacementsRecursive(Class klass)
    {
        Set> seen = new HashSet<>(); // to make sure not to process the same type twice
        List accum = new ArrayList<>();
        getReplacementsRecursive(seen, accum, klass);
        return accum.isEmpty() ? Collections.emptyList() : accum;
    }

    private static void getReplacementsRecursive(Set> seen,
                                                 List accum,
                                                 Class klass)
    {
        accum.addAll(getReplacements(klass));
        for (Field field : klass.getDeclaredFields())
        {
            if (seen.add(field.getType()))
            {
                // first time looking at this type, walk it
                getReplacementsRecursive(seen, accum, field.getType());
            }
        }
    }

    private static List getReplacements(Class klass)
    {
        List replacements = new ArrayList<>();
        for (Field field : klass.getDeclaredFields())
        {
            String newName = field.getName();
            Class newType = field.getType();
            final ReplacesList[] byType = field.getAnnotationsByType(ReplacesList.class);
            if (byType == null || byType.length == 0)
            {
                Replaces r = field.getAnnotation(Replaces.class);
                if (r != null)
                    addReplacement(klass, replacements, newName, newType, r);
            }
            else
            {
                for (ReplacesList replacesList : byType)
                    for (Replaces r : replacesList.value())
                        addReplacement(klass, replacements, newName, newType, r);
            }
        }
        return replacements.isEmpty() ? Collections.emptyList() : replacements;
    }

    private static void addReplacement(Class klass,
                                       List replacements,
                                       String newName, Class newType,
                                       Replaces r)
    {
        String oldName = r.oldName();

        boolean deprecated = r.deprecated();

        Class oldType = r.converter().getOldType();
        if (oldType == null)
            oldType = newType;
        Class expectedNewType = r.converter().getNewType();
        if (expectedNewType != null)
            assert expectedNewType.equals(newType) : String.format("Converter is expected to return %s but %s#%s expects %s", expectedNewType, klass, newName, newType);

        replacements.add(new Replacement(klass, oldName, oldType, newName, r.converter(), deprecated));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy