/*
 * Copyright 2004-2005 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 * @test
 * @bug 4847959 6191402
 * @summary Test newly-generified APIs
 * @author Eamonn McManus
 * @run clean GenericTest
 * @run build GenericTest
 * @run main GenericTest
 */

import java.lang.management.ManagementFactory;
import java.lang.reflect.*;
import java.util.*;
import javax.management.*;
import javax.management.openmbean.*;
import javax.management.relation.*;
import javax.management.timer.Timer;
import javax.management.timer.TimerMBean;

public class GenericTest {
    private static int failures;

    public static void main(String[] args) throws Exception {
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

        // Check we are really using the generified version
        boolean generic;
        Method findmbs = MBeanServerFactory.class.getMethod("findMBeanServer",
                                                            String.class);
        Type findmbstype = findmbs.getGenericReturnType();
        if (!(findmbstype instanceof ParameterizedType)) {
            System.out.println("FAILURE: API NOT GENERIC!");
            System.out.println("  MBeanServerFactory.findMBeanServer -> " +
                               findmbstype);
            failures++;
            generic = false;
        } else {
            System.out.println("OK: this API is generic");
            generic = true;
        }

        ArrayList<MBeanServer> mbsList1 =
            MBeanServerFactory.findMBeanServer(null);
        checked(mbsList1, MBeanServer.class);
        ArrayList mbsList2 = MBeanServerFactory.findMBeanServer(null);
        check("ArrayList<MBeanServer> findMBeanServer", mbsList1.size() == 1);
        check("ArrayList findMBeanServer", mbsList1.equals(mbsList2));

        Set<ObjectName> names1 =
            checked(mbs.queryNames(null, null), ObjectName.class);
        Set names2 = mbs.queryNames(null, null);
        Set<ObjectName> names3 =
            checked(((MBeanServerConnection) mbs).queryNames(null, null),
                    ObjectName.class);
        check("Set<ObjectName> MBeanServer.queryNames", names1.size() >= 1);
        check("Set MBeanServer.queryNames", names2.size() >= 1);
        check("Set<ObjectName> MBeanServerConnection.queryNames",
              names3.size() >= 1);
        check("queryNames sets same",
              names1.equals(names2) && names2.equals(names3));

        Set<ObjectInstance> mbeans1 =
            checked(mbs.queryMBeans(null, null), ObjectInstance.class);
        Set mbeans2 = mbs.queryMBeans(null, null);
        Set<ObjectInstance> mbeans3 =
            checked(((MBeanServerConnection) mbs).queryMBeans(null, null),
                    ObjectInstance.class);
        check("Set<ObjectInstsance> MBeanServer.queryMBeans",
              mbeans1.size() >= 1);
        check("Set MBeanServer.queryMBeans", mbeans2.size() >= 1);
        check("Set<ObjectInstsance> MBeanServerConnection.queryMBeans",
              mbeans3.size() >= 1);
        check("queryMBeans sets same",
              mbeans1.equals(mbeans2) && mbeans2.equals(mbeans3));


        AttributeChangeNotificationFilter acnf =
            new AttributeChangeNotificationFilter();
        acnf.enableAttribute("foo");
        Vector<String> acnfs = acnf.getEnabledAttributes();
        checked(acnfs, String.class);
        check("Vector<String> AttributeChangeNotificationFilter.getEnabled" +
              "Attributes", acnfs.equals(Arrays.asList(new String[] {"foo"})));

        if (generic) {
            Attribute a = new Attribute("foo", "bar");
            AttributeList al1 = new AttributeList();
            al1.add(a);
            AttributeList al2 =
                new AttributeList(Arrays.asList(new Attribute[] {a}));
            check("new AttributeList(List<Attribute>)", al1.equals(al2));
            List<Attribute> al3 = checked(al1.asList(), Attribute.class);
            al3.remove(a);
            check("List<Attribute> AttributeList.asList()",
                  al1.equals(al3) && al1.isEmpty());
        }

        List<ObjectName> namelist1 = new ArrayList<ObjectName>(names1);
        Role role = new Role("rolename", namelist1);
        List<ObjectName> namelist2 =
            checked(role.getRoleValue(), ObjectName.class);
        check("new Role(String,List<ObjectName>).getRoleValue() -> " +
              "List<ObjectName>", namelist1.equals(namelist2));

        RoleList rl1 = new RoleList();
        rl1.add(role);
        RoleList rl2 = new RoleList(Arrays.asList(new Role[] {role}));
        check("new RoleList(List<Role>)", rl1.equals(rl2));
        if (generic) {
            List<Role> rl3 = checked(rl1.asList(), Role.class);
            rl3.remove(role);
            check("List<Role> RoleList.asList()",
                  rl1.equals(rl3) && rl1.isEmpty());
        }

        RoleUnresolved ru =
            new RoleUnresolved("rolename", namelist1,
                               RoleStatus.LESS_THAN_MIN_ROLE_DEGREE);
        List<ObjectName> namelist3 =
            checked(ru.getRoleValue(), ObjectName.class);
        check("new RoleUnresolved(...List<ObjectName>...).getRoleValue() -> " +
              "List<ObjectName>", namelist1.equals(namelist3));

        RoleUnresolvedList rul1 = new RoleUnresolvedList();
        rul1.add(ru);
        RoleUnresolvedList rul2 =
            new RoleUnresolvedList(Arrays.asList(new RoleUnresolved[] {ru}));
        check("new RoleUnresolvedList(List<RoleUnresolved>", rul1.equals(rul2));
        if (generic) {
            List<RoleUnresolved> rul3 =
                checked(rul1.asList(), RoleUnresolved.class);
            rul3.remove(ru);
            check("List<RoleUnresolved> RoleUnresolvedList.asList()",
                  rul1.equals(rul3) && rul1.isEmpty());
        }

        // This case basically just tests that we can compile this sort of thing
        OpenMBeanAttributeInfo ombai1 =
            new OpenMBeanAttributeInfoSupport("a", "a descr",
                                                SimpleType.INTEGER,
                                                true, true, false);
        CompositeType ct =
            new CompositeType("ct", "ct descr", new String[] {"item1"},
                              new String[] {"item1 descr"},
                              new OpenType[] {SimpleType.INTEGER});
        OpenMBeanAttributeInfo ombai2 =
            new OpenMBeanAttributeInfoSupport("a", "a descr",
                                                      ct, true, true, false);
        TabularType tt =
            new TabularType("tt", "tt descr", ct, new String[] {"item1"});
        OpenMBeanAttributeInfo ombai3 =
            new OpenMBeanAttributeInfoSupport("a", "a descr",
                                                    tt, true, true, false);
        ArrayType<String[][]> at =
            new ArrayType<String[][]>(2, SimpleType.STRING);
        OpenMBeanAttributeInfo ombai4 =
            new OpenMBeanAttributeInfoSupport("a", "a descr",
                                                   at, true, true, false);
        OpenMBeanAttributeInfo ombai4a =
            new OpenMBeanAttributeInfoSupport("a", "a descr",
                                              (ArrayType) at,
                                              true, true, false);
        OpenMBeanAttributeInfo ombai5 =
            new OpenMBeanAttributeInfoSupport("a", "a descr",
                                                       SimpleType.INTEGER,
                                                       true, true, false,
                                                       5, 1, 9);
        OpenMBeanAttributeInfo ombai6 =
            new OpenMBeanAttributeInfoSupport("a", "a descr",
                                                       SimpleType.INTEGER,
                                                       true, true, false,
                                                       5, new Integer[] {1, 5});

        OpenMBeanInfo ombi =
            new OpenMBeanInfoSupport("a.a", "a.a descr",
                                     new OpenMBeanAttributeInfo[] {
                                         ombai1, ombai2, ombai3, ombai4,
                                         ombai5, ombai6,
                                     },
                                     null, null, null);

        Map<String,Integer> itemMap =
            checked(singletonMap("item1", 5),
                    String.class, Integer.class);
        CompositeData cd =
            new CompositeDataSupport(ct, itemMap);
        check("CompositeDataSupport(CompositeType, Map<String,?>",
              cd.get("item1").equals(5));

        Set<String> ctkeys = checked(ct.keySet(), String.class);
        check("Set<String> CompositeType.keySet()",
              ctkeys.equals(singleton("item1")));

        List<String> ttindex = checked(tt.getIndexNames(), String.class);
        check("Set<String> TabularType.getIndexNames()",
              ttindex.equals(singletonList("item1")));

        TabularData td = new TabularDataSupport(tt);
        td.putAll(new CompositeData[] {cd});
        List<Integer> tdkey = checked(singletonList(5), Integer.class);
        Set<List<Integer>> tdkeys = checked(singleton(tdkey),
            (Class<List<Integer>>) tdkey.getClass());
        Collection<CompositeData> tdvalues = checked(singleton(cd),
            CompositeData.class);
        check("Set<List<?>> TabularDataSupport.keySet()",
              td.keySet().equals(tdkeys));
        check("Collection<CompositeData> TabularDataSupport.values()",
              td.values().iterator().next().equals(tdvalues.iterator().next()));

        ObjectName stupidName = new ObjectName("stupid:a=b");
        mbs.registerMBean(new Stupid(), stupidName);
        StupidMBean proxy =
            MBeanServerInvocationHandler.newProxyInstance(mbs,
                                                          stupidName,
                                                          StupidMBean.class,
                                                          false);
        check("MBeanServerInvocationHandler.newProxyInstance",
              proxy.getFive() == 5);
        mbs.unregisterMBean(stupidName);

        mbs.registerMBean(new StandardMBean(new Stupid(), StupidMBean.class),
                          stupidName);
        check("<T> StandardMBean(T impl, Class<T> intf)",
              proxy.getFive() == 5);

        // Following is based on the package.html for javax.management.relation
        // Create the Relation Service MBean
        ObjectName relSvcName = new ObjectName(":type=RelationService");
        RelationService relSvcObject = new RelationService(true);
        mbs.registerMBean(relSvcObject, relSvcName);

        // Create an MBean proxy for easier access to the Relation Service
        RelationServiceMBean relSvc =
        MBeanServerInvocationHandler.newProxyInstance(mbs, relSvcName,
                                                      RelationServiceMBean.class,
                                                      false);

        // Define the DependsOn relation type
        RoleInfo[] dependsOnRoles = {
            new RoleInfo("dependent", Module.class.getName()),
            new RoleInfo("dependedOn", Module.class.getName())
        };
        relSvc.createRelationType("DependsOn", dependsOnRoles);

        // Now define a relation instance "moduleA DependsOn moduleB"

        ObjectName moduleA = new ObjectName(":type=Module,name=A");
        ObjectName moduleB = new ObjectName(":type=Module,name=B");

        // Following two lines added to example:
        mbs.registerMBean(new Module(), moduleA);
        mbs.registerMBean(new Module(), moduleB);

        Role dependent = new Role("dependent", singletonList(moduleA));
        Role dependedOn = new Role("dependedOn", singletonList(moduleB));
        Role[] roleArray = {dependent, dependedOn};
        RoleList roles = new RoleList(Arrays.asList(roleArray));
        relSvc.createRelation("A-DependsOn-B", "DependsOn", roles);

        // Query the Relation Service to find what modules moduleA depends on
        Map<ObjectName,List<String>> dependentAMap =
        relSvc.findAssociatedMBeans(moduleA, "DependsOn", "dependent");
        Set<ObjectName> dependentASet = dependentAMap.keySet();
        dependentASet = checked(dependentASet, ObjectName.class);
        // Set of ObjectName containing moduleB
        check("Map<ObjectName,List<String>> RelationService.findAssociatedMBeans",
              dependentAMap.size() == 1 &&
              dependentASet.equals(singleton(moduleB)));

        Map<String,List<String>> refRels =
            relSvc.findReferencingRelations(moduleA, "DependsOn", "dependent");
        List<String> refRoles =
            checked(refRels.get("A-DependsOn-B"), String.class);
        check("Map<String,List<String>> RelationService.findReferencingRelations",
              refRoles.equals(singletonList("dependent")));

        List<String> relsOfType = relSvc.findRelationsOfType("DependsOn");
        relsOfType = checked(relsOfType, String.class);
        check("List<String> RelationService.findRelationsOfType",
              relsOfType.equals(singletonList("A-DependsOn-B")));

        List<String> allRelIds = relSvc.getAllRelationIds();
        allRelIds = checked(allRelIds, String.class);
        check("List<String> RelationService.getAllRelationIds()",
              allRelIds.equals(singletonList("A-DependsOn-B")));

        List<String> allRelTypes = relSvc.getAllRelationTypeNames();
        allRelTypes = checked(allRelTypes, String.class);
        check("List<String> RelationService.getAllRelationTypeNames",
              allRelTypes.equals(singletonList("DependsOn")));

        Map<ObjectName,List<String>> refdMBeans =
            relSvc.getReferencedMBeans("A-DependsOn-B");
        check("Map<ObjectName,List<String>> RelationService.getReferencedMBeans",
              refdMBeans.get(moduleA).equals(singletonList("dependent")) &&
              refdMBeans.get(moduleB).equals(singletonList("dependedOn")));

        List<ObjectName> roleContents =
            checked(relSvc.getRole("A-DependsOn-B", "dependent"),
                    ObjectName.class);
        check("List<ObjectName> RelationService.getRole",
              roleContents.equals(singletonList(moduleA)));

        RoleInfo roleInfoDependent =
            relSvc.getRoleInfo("DependsOn", "dependent");
        RoleInfo roleInfoDependedOn =
            relSvc.getRoleInfo("DependsOn", "dependedOn");
        List<RoleInfo> expectedRoleInfos =
            Arrays.asList(new RoleInfo[] {roleInfoDependent, roleInfoDependedOn});
        List<RoleInfo> roleInfos =
            checked(relSvc.getRoleInfos("DependsOn"), RoleInfo.class);
        check("List<RoleInfo> RelationService.getRoleInfos",
              equalListContents(expectedRoleInfos, roleInfos));

        RelationType relType =
            new RelationTypeSupport("DependsOn", dependsOnRoles);
        List<RoleInfo> relTypeRoleInfos =
            checked(relType.getRoleInfos(), RoleInfo.class);
        // Since there's no RoleInfo.equals and since the RelationTypeSupport
        // constructor clones the RoleInfos passed to it, it's tricky to
        // test equality here so we check type and size and have done with it
        check("List<RoleInfo> RelationType.getRoleInfos",
              relTypeRoleInfos.size() == 2);

        MBeanServerNotificationFilter mbsnf =
            new MBeanServerNotificationFilter();
        mbsnf.enableObjectName(moduleA);
        check("Vector<ObjectName> MBeanServerNotificationFilter." +
              "getEnabledObjectNames",
              mbsnf.getEnabledObjectNames().equals(Arrays.asList(moduleA)));
        mbsnf.enableAllObjectNames();
        mbsnf.disableObjectName(moduleB);
        check("Vector<ObjectName> MBeanServerNotificationFilter." +
              "getDisabledObjectNames",
              mbsnf.getDisabledObjectNames().equals(Arrays.asList(moduleB)));

        RelationService unusedRelSvc = new RelationService(false);
        RelationNotification rn1 =
            new RelationNotification(RelationNotification.RELATION_MBEAN_REMOVAL,
                                     unusedRelSvc, 0L, 0L, "yo!",
                                     "A-DependsOn-B", "DependsOn", null,
                                     singletonList(moduleA));
        List<ObjectName> toUnreg =
            checked(rn1.getMBeansToUnregister(), ObjectName.class);
        check("List<ObjectName> RelationNotification.getMBeansToUnregister",
              toUnreg.equals(singletonList(moduleA)));

        RelationNotification rn2 =
            new RelationNotification(RelationNotification.RELATION_MBEAN_UPDATE,
                                     unusedRelSvc, 0L, 0L, "yo!",
                                     "A-DependsOn-B", "DependsOn", null,
                                     "dependent", singletonList(moduleA),
                                     singletonList(moduleB));
        check("List<ObjectName> RelationNotification.getOldRoleValue",
              checked(rn2.getOldRoleValue(), ObjectName.class)
              .equals(singletonList(moduleB)));
        check("List<ObjectName> RelationNotification.getNewRoleValue",
              checked(rn2.getNewRoleValue(), ObjectName.class)
              .equals(singletonList(moduleA)));

        ObjectName timerName = new ObjectName(":type=timer");
        mbs.registerMBean(new Timer(), timerName);
        TimerMBean timer =
            MBeanServerInvocationHandler.newProxyInstance(mbs,
                                                          timerName,
                                                          TimerMBean.class,
                                                          false);
        Date doomsday = new Date(Long.MAX_VALUE);
        int timer1 = timer.addNotification("one", "one", null, doomsday);
        int timer2 = timer.addNotification("two", "two", null, doomsday);
        Vector<Integer> idsOne = timer.getNotificationIDs("one");
        check("Vector<Integer> TimerMBean.getNotificationIDs",
              idsOne.equals(singletonList(timer1)));
        Vector<Integer> allIds = timer.getAllNotificationIDs();
        check("Vector<Integer> TimerMBean.getAllNotificationIDs",
              equalListContents(allIds,
                                Arrays.asList(new Integer[]{timer1, timer2})));

        // ADD NEW TEST CASES ABOVE THIS COMMENT

        if (failures == 0)
            System.out.println("All tests passed");
        else {
            System.out.println("TEST FAILURES: " + failures);
            System.exit(1);
        }

        // DO NOT ADD NEW TEST CASES HERE, ADD THEM ABOVE THE PREVIOUS COMMENT
    }

    public static interface StupidMBean {
        public int getFive();
    }

    public static class Stupid implements StupidMBean {
        public int getFive() {
            return 5;
        }
    }

    public static class Module extends StandardMBean implements StupidMBean {
        public Module() throws NotCompliantMBeanException {
            super(StupidMBean.class);
        }

        public int getFive() {
            return 5;
        }
    }

    private static <E> List<E> singletonList(E value) {
        return Collections.singletonList(value);
    }

    private static <E> Set<E> singleton(E value) {
        return Collections.singleton(value);
    }

    private static <K,V> Map<K,V> singletonMap(K key, V value) {
        return Collections.singletonMap(key, value);
    }

    private static <E> List<E> checked(List<E> c, Class<E> type) {
        List<E> unchecked = new ArrayList<E>();
        List<E> checked = Collections.checkedList(unchecked, type);
        checked.addAll(c);
        return Collections.checkedList(c, type);
    }

    private static <E> Set<E> checked(Set<E> c, Class<E> type) {
        Set<E> unchecked = new HashSet<E>();
        Set<E> checked = Collections.checkedSet(unchecked, type);
        checked.addAll(c);
        return Collections.checkedSet(c, type);
    }

    private static <K,V> Map<K,V> checked(Map<K,V> m,
                                          Class<K> keyType,
                                          Class<V> valueType) {
        Map<K,V> unchecked = new HashMap<K,V>();
        Map<K,V> checked = Collections.checkedMap(unchecked, keyType, valueType);
        checked.putAll(m);
        return Collections.checkedMap(m, keyType, valueType);
    }

    /* The fact that we have to call this method is a clear signal that
     * the API says List where it means Set.
     */
    private static <E> boolean equalListContents(List<E> l1, List<E> l2) {
        return new HashSet<E>(l1).equals(new HashSet<E>(l2));
    }

    private static void check(String what, boolean cond) {
        if (cond)
            System.out.println("OK: " + what);
        else {
            System.out.println("FAILED: " + what);
            failures++;
        }
    }
}
