/*
 * 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.tomcat.util.modeler;

import javax.management.MBeanAttributeInfo;

/**
 * Internal configuration information for an <code>Attribute</code> descriptor.
 */
public class AttributeInfo extends FeatureInfo {

    private static final long serialVersionUID = -2511626862303972143L;

    /**
     * Constructs a new AttributeInfo instance.
     */
    public AttributeInfo() {
    }

    // ----------------------------------------------------- Instance Variables
    /**
     * Human-readable display name for this attribute.
     */
    protected String displayName = null;

    // Information about the method to use
    /**
     * Name of the getter method for this attribute.
     */
    protected String getMethod = null;

    /**
     * Name of the setter method for this attribute.
     */
    protected String setMethod = null;

    /**
     * Whether this attribute can be read by management applications.
     */
    protected boolean readable = true;

    /**
     * Whether this attribute can be written by management applications.
     */
    protected boolean writeable = true;

    /**
     * Whether this is a boolean attribute with an "is" getter.
     */
    protected boolean is = false;

    // ------------------------------------------------------------- Properties

    /**
     * Returns the display name of this attribute.
     *
     * @return the display name of this attribute
     */
    public String getDisplayName() {
        return this.displayName;
    }

    /**
     * Sets the display name of this attribute.
     *
     * @param displayName the display name
     */
    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    /**
     * Returns the name of the property getter method, generating a default if not explicitly set.
     *
     * @return the name of the property getter method
     */
    public String getGetMethod() {
        if (getMethod == null) {
            getMethod = getMethodName(getName(), true, isIs());
        }
        return this.getMethod;
    }

    /**
     * Sets the name of the property getter method.
     *
     * @param getMethod the getter method name
     */
    public void setGetMethod(String getMethod) {
        this.getMethod = getMethod;
    }

    /**
     * Is this a boolean attribute with an "is" getter?
     *
     * @return <code>true</code> if this is a boolean attribute with an "is" getter
     */
    public boolean isIs() {
        return this.is;
    }

    /**
     * Sets whether this is a boolean attribute with an "is" getter.
     *
     * @param is {@code true} if this is a boolean attribute with an "is" getter
     */
    public void setIs(boolean is) {
        this.is = is;
    }


    /**
     * Is this attribute readable by management applications?
     *
     * @return <code>true</code> if readable
     */
    public boolean isReadable() {
        return this.readable;
    }

    /**
     * Sets whether this attribute is readable by management applications.
     *
     * @param readable {@code true} if readable
     */
    public void setReadable(boolean readable) {
        this.readable = readable;
    }


    /**
     * Returns the name of the property setter method, generating a default if not explicitly set.
     *
     * @return the name of the property setter method
     */
    public String getSetMethod() {
        if (setMethod == null) {
            setMethod = getMethodName(getName(), false, false);
        }
        return this.setMethod;
    }

    /**
     * Sets the name of the property setter method.
     *
     * @param setMethod the setter method name
     */
    public void setSetMethod(String setMethod) {
        this.setMethod = setMethod;
    }

    /**
     * Is this attribute writable by management applications?
     *
     * @return <code>true</code> if writable
     */
    public boolean isWriteable() {
        return this.writeable;
    }

    /**
     * Sets whether this attribute is writable by management applications.
     *
     * @param writeable {@code true} if writable
     */
    public void setWriteable(boolean writeable) {
        this.writeable = writeable;
    }

    // --------------------------------------------------------- Public Methods


    /**
     * Create and return a <code>ModelMBeanAttributeInfo</code> object that corresponds to the attribute described by
     * this instance.
     *
     * @return the attribute info
     */
    MBeanAttributeInfo createAttributeInfo() {
        // Return our cached information (if any)
        if (info == null) {
            info = new MBeanAttributeInfo(getName(), getType(), getDescription(), isReadable(), isWriteable(), false);
        }
        return (MBeanAttributeInfo) info;
    }

    // -------------------------------------------------------- Private Methods


    /**
     * Create and return the name of a default property getter or setter method, according to the specified values.
     *
     * @param name   Name of the property itself
     * @param getter Do we want a get method (versus a set method)?
     * @param is     If returning a getter, do we want the "is" form?
     *
     * @return the method name
     */
    private String getMethodName(String name, boolean getter, boolean is) {
        StringBuilder sb = new StringBuilder();
        if (getter) {
            if (is) {
                sb.append("is");
            } else {
                sb.append("get");
            }
        } else {
            sb.append("set");
        }
        sb.append(Character.toUpperCase(name.charAt(0)));
        sb.append(name.substring(1));
        return sb.toString();
    }


}
