12637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin/*
22637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin * Copyright (c) 2015 Mockito contributors
32637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin * This program is made available under the terms of the MIT License.
42637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin */
52637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
62637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinpackage org.mockito.internal.util.reflection;
72637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
82637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport java.lang.reflect.Field;
92637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport java.util.ArrayList;
102637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport java.util.Collection;
112637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport java.util.Collections;
122637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport java.util.Comparator;
132637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinimport java.util.List;
142637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
152637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin/**
162637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin * Sort fields in an order suitable for injection, by name with superclasses
172637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin * moved after their subclasses.
182637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin */
192637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffinpublic class SuperTypesLastSorter {
202637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
212637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin    private SuperTypesLastSorter() {
222637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin    }
232637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
242637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin    /**
252637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin     * Return a new collection with the fields sorted first by name,
262637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin     * then with any fields moved after their supertypes.
272637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin     */
282637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin    public static List<Field> sortSuperTypesLast(Collection<? extends Field> unsortedFields) {
292637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin        List<Field> fields = new ArrayList<Field>(unsortedFields);
302637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
312637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin        Collections.sort(fields, compareFieldsByName);
322637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
332637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin        int i = 0;
342637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
352637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin        while (i < fields.size() - 1) {
362637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin            Field f = fields.get(i);
372637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin            Class<?> ft = f.getType();
382637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin            int newPos = i;
392637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin            for (int j = i + 1; j < fields.size(); j++) {
402637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin                Class<?> t = fields.get(j).getType();
412637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
422637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin                if (ft != t && ft.isAssignableFrom(t)) {
432637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin                    newPos = j;
442637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin                }
452637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin            }
462637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
472637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin            if (newPos == i) {
482637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin                i++;
492637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin            } else {
502637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin                fields.remove(i);
512637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin                fields.add(newPos, f);
522637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin            }
532637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin        }
542637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
552637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin        return fields;
562637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin    }
572637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
582637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin
592637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin    private static final Comparator<Field> compareFieldsByName = new Comparator<Field>() {
602637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin        @Override
612637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin        public int compare(Field o1, Field o2) {
622637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin            return o1.getName().compareTo(o2.getName());
632637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin        }
642637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin    };
652637d96c202372854a7c71466ddcc6e90fc4fc53Paul Duffin}
66