/*
 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.management;

import java.lang.management.MonitorInfo;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.OpenDataException;
import java.util.Set;

/**
 * A CompositeData for MonitorInfo for the local management support.
 * This class avoids the performance penalty paid to the
 * construction of a CompositeData use in the local case.
 */
public class MonitorInfoCompositeData extends LazyCompositeData {
    private final MonitorInfo lock;

    private MonitorInfoCompositeData(MonitorInfo mi) {
        this.lock = mi;
    }

    public MonitorInfo getMonitorInfo() {
        return lock;
    }

    public static CompositeData toCompositeData(MonitorInfo mi) {
        MonitorInfoCompositeData micd = new MonitorInfoCompositeData(mi);
        return micd.getCompositeData();
    }

    protected CompositeData getCompositeData() {
        // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH
        // monitorInfoItemNames!

        int len = monitorInfoItemNames.length;
        Object[] values = new Object[len];
        CompositeData li = LockDataConverter.toLockInfoCompositeData(lock);

        for (int i = 0; i < len; i++) {
            String item = monitorInfoItemNames[i];
            if (item.equals(LOCKED_STACK_FRAME)) {
                StackTraceElement ste = lock.getLockedStackFrame();
                values[i] = (ste != null ? StackTraceElementCompositeData.
                                               toCompositeData(ste)
                                         : null);
            } else if (item.equals(LOCKED_STACK_DEPTH)) {
                values[i] = new Integer(lock.getLockedStackDepth());
            } else {
                values[i] = li.get(item);
            }
        }

        try {
            return new CompositeDataSupport(monitorInfoCompositeType,
                                            monitorInfoItemNames,
                                            values);
        } catch (OpenDataException e) {
            // Should never reach here
            throw new AssertionError(e);
        }
    }

    private static final CompositeType monitorInfoCompositeType;
    private static final String[] monitorInfoItemNames;
    static {
        try {
            monitorInfoCompositeType = (CompositeType)
                MappedMXBeanType.toOpenType(MonitorInfo.class);
            Set<String> s = monitorInfoCompositeType.keySet();
            monitorInfoItemNames = (String[]) s.toArray(new String[0]);
        } catch (OpenDataException e) {
            // Should never reach here
            throw new AssertionError(e);
        }
    }

    static CompositeType getMonitorInfoCompositeType() {
        return monitorInfoCompositeType;
    }

    private static final String CLASS_NAME         = "className";
    private static final String IDENTITY_HASH_CODE = "identityHashCode";
    private static final String LOCKED_STACK_FRAME = "lockedStackFrame";
    private static final String LOCKED_STACK_DEPTH = "lockedStackDepth";

    public static String getClassName(CompositeData cd) {
        return getString(cd, CLASS_NAME);
    }

    public static int getIdentityHashCode(CompositeData cd) {
        return getInt(cd, IDENTITY_HASH_CODE);
    }

    public static StackTraceElement getLockedStackFrame(CompositeData cd) {
        CompositeData ste = (CompositeData) cd.get(LOCKED_STACK_FRAME);
        if (ste != null) {
            return StackTraceElementCompositeData.from(ste);
        } else {
            return null;
        }
    }

    public static int getLockedStackDepth(CompositeData cd) {
        return getInt(cd, LOCKED_STACK_DEPTH);
    }

    /** Validate if the input CompositeData has the expected
     * CompositeType (i.e. contain all attributes with expected
     * names and types).
     */
    public static void validateCompositeData(CompositeData cd) {
        if (cd == null) {
            throw new NullPointerException("Null CompositeData");
        }

        if (!isTypeMatched(monitorInfoCompositeType, cd.getCompositeType())) {
            throw new IllegalArgumentException(
                "Unexpected composite type for MonitorInfo");
        }
    }

    private static final long serialVersionUID = -5825215591822908529L;
}
