1/*
2 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @summary Comparator API narrowing type test
27 * @bug 8009736 8033590
28 * @run testng TypeTest
29 */
30
31import java.util.function.Function;
32import java.util.Map;
33import java.util.TreeMap;
34import java.util.Comparator;
35import org.testng.annotations.Test;
36
37import static org.testng.Assert.assertTrue;
38
39@Test(groups = "unit")
40public class TypeTest {
41    static class Person {
42        String name;
43        static Comparator<Person> C = (p1, p2) -> p1.name.compareTo(p2.name);
44
45        Person(String name) {
46            this.name = name;
47        }
48
49        String getName() { return name; }
50    }
51
52    static class Employee extends Person {
53        int id;
54        static Comparator<Employee> C = (e1, e2) -> e1.id - e2.id;
55
56        Employee(int id, String name) {
57            super(name);
58            this.id = id;
59        }
60    }
61
62    static class Manager extends Employee {
63        long reports;
64        static Comparator<Manager> C = (e1, e2) -> (int) (e1.reports - e2.reports);
65
66        Manager(String name, int id, long reports) {
67            super(id, name);
68            this.reports = reports;
69        }
70    }
71
72    static class Department {
73        Manager mgr;
74        String hr_code;
75
76        Department(Manager mgr, String hr) {
77            this.mgr = mgr;
78            this.hr_code = hr;
79        }
80
81        Manager getManager() {
82            return mgr;
83        }
84
85        String getHR() {
86            return hr_code;
87        }
88    }
89
90    static <T> void assertOrder(T o1, T o2, Comparator<? super T> cmp) {
91        if (cmp.compare(o1, o2) > 0) {
92            System.out.println("Fail!!");
93        }
94        if (cmp.compare(o1, o2) == 0) {
95            System.out.println("Equal!!");
96        }
97    }
98
99    // Type tests just to make sure the code can compile and build
100    // Not necessarily need a meaningful result
101    public void testOrder() {
102        Manager m1 = new Manager("Manager", 2, 2000);
103        Manager m2 = new Manager("Manager", 4, 1300);
104
105        // Comparator<Employee> tmp = Person.C;
106
107        // Comparator<Manager> cmp = Employee.C.thenComparing(Person.C);
108        Comparator<Employee> cmp = Employee.C.thenComparing(Person.C);
109        assertOrder(m1, m2, Employee.C.thenComparing(Person.C));
110        assertOrder(m1, m2, cmp);
111        assertOrder(m1, new Employee(1, "Z"), Person.C);
112        assertOrder(new Employee(1, "Z"), m2, Employee.C);
113
114        assertOrder(m1, m2, Comparator.comparing(Employee::getName, String.CASE_INSENSITIVE_ORDER));
115
116        Map<String, Integer> map = new TreeMap<>();
117        map.entrySet().stream().sorted(Map.Entry.comparingByKey(String.CASE_INSENSITIVE_ORDER));
118    }
119
120    public void testJDK8033590() {
121        Manager a = new Manager("John Doe", 1234, 16);
122        Manager b = new Manager("Jane Roe", 2468, 16);
123        Department da = new Department(a, "X");
124        Department db = new Department(b, "X");
125
126        Comparator<Department> cmp = Comparator.comparing(Department::getHR)
127                .thenComparing(Department::getManager, Employee.C);
128        assertTrue(cmp.compare(da, db) < 0);
129
130        cmp = Comparator.comparing(Department::getHR)
131                .thenComparing(Department::getManager, Manager.C);
132        assertTrue(cmp.compare(da, db) == 0);
133
134        cmp = Comparator.comparing(Department::getHR)
135                .thenComparing(Department::getManager, Person.C);
136        assertTrue(cmp.compare(da, db) > 0);
137    }
138}
139