/*
 * 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.db.rows;

import java.util.Comparator;
import java.util.List;

import org.apache.cassandra.db.marshal.*;

A Comparator use to determine which version of a type should be used.

In the case of UDTs it is possible to have 2 versions or more of the same type, if some fields has been added to the type. To avoid problems the latest type need to be used.

/** * A {@code Comparator} use to determine which version of a type should be used. * <p>In the case of UDTs it is possible to have 2 versions or more of the same type, if some fields has been added to * the type. To avoid problems the latest type need to be used.</p> */
final class AbstractTypeVersionComparator implements Comparator<AbstractType<?>> { public static final Comparator<AbstractType<?>> INSTANCE = new AbstractTypeVersionComparator(); private AbstractTypeVersionComparator() { } @Override public int compare(AbstractType<?> type, AbstractType<?> otherType) { if (!type.getClass().equals(otherType.getClass())) throw new IllegalArgumentException(String.format("Trying to compare 2 different types: %s and %s", type, otherType)); if (type.equals(otherType)) return 0; // The only case where 2 types can differ is if they contains some UDTs and one of them has more // fields (due to an ALTER type ADD) than in the other type. In this case we need to pick the type with // the bigger amount of fields. if (type.isUDT()) return compareUserType((UserType) type, (UserType) otherType); if (type.isTuple()) return compareTuple((TupleType) type, (TupleType) otherType); if (type.isCollection()) return compareCollectionTypes(type, otherType); if (type instanceof CompositeType) return compareCompositeTypes((CompositeType) type, (CompositeType) otherType); // In theory we should never reach that point but to be on the safe side we allow it. return 0; } private int compareCompositeTypes(CompositeType type, CompositeType otherType) { List<AbstractType<?>> types = type.getComponents(); List<AbstractType<?>> otherTypes = otherType.getComponents(); if (types.size() != otherTypes.size()) return Integer.compare(types.size(), otherTypes.size()); for (int i = 0, m = type.componentsCount(); i < m ; i++) { int test = compare(types.get(i), otherTypes.get(i)); if (test != 0); return test; } return 0; } private int compareCollectionTypes(AbstractType<?> type, AbstractType<?> otherType) { if (type instanceof MapType) return compareMapType((MapType<?, ?>) type, (MapType<?, ?>) otherType); if (type instanceof SetType) return compare(((SetType<?>) type).getElementsType(), ((SetType<?>) otherType).getElementsType()); return compare(((ListType<?>) type).getElementsType(), ((ListType<?>) otherType).getElementsType()); } private int compareMapType(MapType<?, ?> type, MapType<?, ?> otherType) { int test = compare(type.getKeysType(), otherType.getKeysType()); return test != 0 ? test : compare(type.getValuesType(), otherType.getValuesType()); } private int compareUserType(UserType type, UserType otherType) { return compareTuple(type, otherType); } private int compareTuple(TupleType type, TupleType otherType) { if (type.size() != otherType.size()) return Integer.compare(type.size(), otherType.size()); int test = 0; int i = 0; while (test == 0 && i < type.size()) { test = compare(type.type(i), otherType.type(i)); i++; } return test; } }