/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/urm/org/apache/slide/urm/utils/resourceutilities/message/ResourceMessage.java,v 1.4 2005/03/02 10:53:36 eckehard Exp $
 * $Revision: 1.4 $
 * $Date: 2005/03/02 10:53:36 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed 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.slide.urm.utils.resourceutilities.message;

import java.text.MessageFormat;

import java.util.Arrays;
import java.util.ResourceBundle;
import java.util.MissingResourceException;

/**
 ** This {@link DetailedMessage DetailedMessage} retrieves its content
 ** from a given ResourceBundle where the ResourceBundle should contain
 ** the resources defined in {@link XMLMessageResourceBundle XMLMessageResourceBundle}.
 ** At least it must contain a valid resource for the given constructor parameter
 ** {@link #ResourceMessage id}.
 **
 ** @version $Revision: 1.4 $
 **
 ** @author rsk@softwareag.com
 **/
public class ResourceMessage extends AbstractDetailedMessage implements MessageConstants {
    
    /**
     ** The name of this class to use in log Statements.
     **/
    //zsa//private static final String LOG_NAME = LoggerUtil.getThisClassName();
    
    /**
     ** The Logger instance.
     **/
    //zsa//private static Logger logger = LoggerFactory.getLogger(LOG_NAME);
    
    /**
     ** The message of the MessageRetrieveException that is thrown if
     ** constructor parameter <code>resourceBundle</code> is <code>null</code>.
     **/
    public static final String RESOURCE_BUNDLE_IS_NULL = "Parameter 'resourceBundle' is null";
    
    /**
     ** The message of the MessageRetrieveException that is thrown if
     ** constructor parameter <code>id</code> is <code>null</code>.
     **/
    public static final String ID_IS_NULL = "Parameter 'id' is null";
    
    
    
    /**
     ** The ResourceBundle containing the resource defined by <code>id</code>.
     **/
    protected ResourceBundle resourceBundle = null;
    
    /**
     ** The message resource id.
     **/
    protected String id = null;
    
    /**
     ** An array containing additional parameters that will be applied
     ** to the message text with java.text.MessageFormat.format().
     **/
    protected Object[] parameters = null;
    
    /**
     ** The MessageCode of this Message.
     **/
    protected MessageCode messageCode = null;
    
    /**
     ** The title of the message.
     **/
    protected String messageTitle = null;
    
    /**
     ** The content of the message.
     **/
    protected String messageContent = null;
    
    /**
     ** The title of the explanations.
     **/
    protected String explanationTitle = null;
    
    /**
     ** The content of the explanations.
     **/
    protected String explanationContent = null;
    
    /**
     ** The title of the action.
     **/
    protected String actionTitle = null;
    
    /**
     ** The content of the action.
     **/
    protected String actionContent = null;
    
    /**
     ** The helpID of this message.
     **/
    protected String helpID = null;
    
    
    
    
    
    /**
     ** Creates a ResourceMessage from the given <code>resourceBundle</code> and
     ** <code>id</code>.
     ** A {@link MessageRetrieveException MessageRetrieveException} is thrown for
     ** one of the following reasons.
     ** <ul>
     ** <li>
     ** Either the parameter <code>resourceBundle</code> or <code>id</code>
     ** is <code>null</code>.
     ** </li>
     ** <li>
     ** The resource for <code>id</code> is not found in <code>resourceBundle</code>.
     ** </li>
     ** <li>
     ** Parsing the {@link #getMessageCode <code>MessageCode</code>} failed for any reason.
     ** </li>
     ** </ul>
     **
     ** @pre   true
     ** @post  true
     **
     ** @param resourceBundle   The ResourceBundle containing the resource defined by
     **                         <code>id</code>.
     ** @param id               The message resource id.
     **
     ** @throws     MessageRetrieveException if retrieving the Message content from the
     **                                      given ResourceBundle fails for any reason.
     **/
    public ResourceMessage(ResourceBundle resourceBundle, String id)  throws MessageRetrieveException {
        
        this(resourceBundle, id, (Object[])null);
    }
    
    /**
     ** Creates a ResourceMessage from the given <code>resourceBundle</code>,
     ** <code>id</code> and <code>parameterString</code>.
     ** A {@link MessageRetrieveException MessageRetrieveException} is thrown for
     ** one of the following reasons.
     ** <ul>
     ** <li>
     ** Either the parameter <code>resourceBundle</code> or <code>id</code>
     ** is <code>null</code>.
     ** </li>
     ** <li>
     ** The resource for <code>id</code> is not found in <code>resourceBundle</code>.
     ** </li>
     ** <li>
     ** Parsing the {@link #getMessageCode <code>MessageCode</code>} failed for any reason.
     ** </li>
     ** </ul>
     **
     ** @pre   true
     ** @post  true
     **
     ** @param resourceBundle   The ResourceBundle containing the resource defined by
     **                         <code>id</code>.
     ** @param id               The message resource id.
     ** @param parameterString  An array containing additional parameters that will be applied
     **                         to the message text with MessageFormat.format().
     **
     ** @throws     MessageRetrieveException if retrieving the Message content from the
     **                                      given ResourceBundle fails for any reason.
     **/
    public ResourceMessage(ResourceBundle resourceBundle, String id, String parameterString)  throws MessageRetrieveException {
        
        this(resourceBundle, id, (parameterString != null ? new Object[] {parameterString} : null));
    }
    
    
    /**
     ** Creates a ResourceMessage from the given <code>resourceBundle</code>,
     ** <code>id</code> and <code>parameters</code>.
     ** A {@link MessageRetrieveException MessageRetrieveException} is thrown for
     ** one of the following reasons.
     ** <ul>
     ** <li>
     ** Either the parameter <code>resourceBundle</code> or <code>id</code>
     ** is <code>null</code>.
     ** </li>
     ** <li>
     ** The resource for <code>id</code> is not found in <code>resourceBundle</code>.
     ** </li>
     ** <li>
     ** Parsing the {@link #getMessageCode <code>MessageCode</code>} failed for any reason.
     ** </li>
     ** </ul>
     **
     ** @pre   true
     ** @post  true
     **
     ** @param resourceBundle   The ResourceBundle containing the resource defined by
     **                         <code>id</code>.
     **                         If <code>null</code>, a MessageRetrieveException is thrown.
     ** @param id               The message resource id.
     **                         If <code>null</code>, or if a value for <code>id</code>
     **                         is not found in the ResourceBunlde, a MessageRetrieveException
     **                         is thrown.
     ** @param parameters       An additional parameters that will be applied
     **                         to the message text with MessageFormat.format().
     **
     ** @throws     MessageRetrieveException if retrieving the Message content from the
     **                                      given ResourceBundle fails for any reason.
     **/
    public ResourceMessage(ResourceBundle resourceBundle, String id, Object[] parameters) throws MessageRetrieveException {
        
        if (resourceBundle == null) {
            throw new MessageRetrieveException(resourceBundle,
                                               id,
                                               RESOURCE_BUNDLE_IS_NULL);
        }
        if (id == null) {
            throw new MessageRetrieveException(resourceBundle,
                                               id,
                                               ID_IS_NULL);
        }
        
        this.resourceBundle = resourceBundle;
        this.id = id;
        this.parameters = parameters;
        
        messageContent = getResourceString(resourceBundle, id, null);
        messageTitle = getResourceString(resourceBundle, id, TITLE_SUFFIX);
        explanationContent = getResourceString(resourceBundle, id, EXPLANATION_SUFFIX);
        explanationTitle = getResourceString(resourceBundle, id, EXPLANATION_TITLE_SUFFIX);
        actionContent = getResourceString(resourceBundle, id, ACTION_SUFFIX);
        actionTitle = getResourceString(resourceBundle, id, ACTION_TITLE_SUFFIX);
        helpID = getResourceString(resourceBundle, id, HELP_ID_SUFFIX);
        
        // extract MessageCode from message content
        if (messageContent != null) {
            
            int index = messageContent.indexOf(" ");
            if (index > 1) {
                
                String codeString = messageContent.substring(0, index);
                try {
                    messageCode = new MessageCode(codeString);
                }
                catch (IllegalArgumentException e) {
                    //zsa//if(logger.isLoggable(Level.FINE)) { logger.throwing(LOG_NAME,"Failure parsing message code", e); }
                    throw new MessageRetrieveException(resourceBundle,
                                                       id,
                                                       "Parsing the MessageCode failed",
                                                       e);
                }
                
                // now truncate the code part from the message
                if (messageContent.length() > index) {
                    messageContent = messageContent.substring(index+1);
                }
                else {
                    messageContent = "";
                }
            }
            
            // now parameterize message
            if ( (parameters != null) && (parameters.length > 0) ) {
                messageContent = MessageFormat.format(messageContent, parameters);
            }
        }
        
    }
    
    /**
     ** Returns the ResourceBundle containing the resource defined by <code>id</code>.
     **
     ** @return the ResourceBundle containing the resource defined by <code>id</code>.
     **/
    public ResourceBundle getResourceBundle() {
        return resourceBundle;
    }
    
    /**
     ** Returns the message resource id.
     **
     ** @return the message resource id.
     **/
    public String getID() {
        return id;
    }
    
    /**
     ** Returns an array containing additional parameters that will be applied
     ** to the message text with java.text.MessageFormat.format().
     **
     ** @return an array containing additional parameters that will be applied
     **         to the message text with java.text.MessageFormat.format().
     **
     **/
    public Object[] getParameters() {
        return parameters;
    }
    
    
    /**
     ** Returns the MessageCode of the message.
     **
     ** @pre        true
     ** @post       true
     **
     ** @return     the MessageCode of the message.
     **/
    public MessageCode getMessageCode() {
        return messageCode;
    }
    
    
    /**
     ** Returns the title of the message.
     **
     ** @pre        true
     ** @post       true
     **
     ** @return     the title of the message.
     **/
    public String getMessageTitle() {
        return messageTitle;
    }
    
    /**
     ** Returns the message to display to the user.
     **
     ** @pre        true
     ** @post       true
     **
     ** @return     the message to display to the user.
     **/
    public String getMessageContent() {
        return messageContent;
    }
    
    
    /**
     ** Returns the title of the explanation section.
     **
     ** @pre        true
     ** @post       true
     **
     ** @return     the title of the explanation section.
     **/
    public String getExplanationTitle() {
        return explanationTitle;
    }
    
    /**
     ** Returns the explanation to display to the user.
     **
     ** @pre        true
     ** @post       true
     **
     ** @return     the explanation to display to the user.
     **/
    public String getExplanationContent() {
        return explanationContent;
    }
    
    
    /**
     ** Returns the title of the action section.
     **
     ** @pre        true
     ** @post       true
     **
     ** @return     the title of the action section.
     **/
    public String getActionTitle() {
        return actionTitle;
    }
    
    /**
     ** Returns the action to display to the user.
     **
     ** @pre        true
     ** @post       true
     **
     ** @return     the action to display to the user.
     **/
    public String getActionContent() {
        return actionContent;
    }
    
    
    /**
     ** Returns the helpID of this message.
     **
     ** @pre        true
     ** @post       true
     **
     ** @return     the helpID of this message.
     **/
    public String getHelpID() {
        return helpID;
    }
    
    
    /**
     ** Sets the details of the message.
     **
     ** @pre        true
     ** @post       true
     **
     ** @param      details  the details of the message.
     **/
    public void setDetails(String details) {
        super.setDetails(details);
    }
    
    /**
     ** Returns a String representation of the Message.
     **
     ** @pre        true
     ** @post       true
     **
     ** @return     a String representation of the Message.
     **/
    public String toString() {
        
        StringBuffer buffer = new StringBuffer("ResourceMessage[");
        buffer.append("resourceBundle=");
        buffer.append(getResourceBundle());
        buffer.append(", id=");
        buffer.append(getID());
        buffer.append(", parameters=");
        buffer.append((getParameters() != null ? Arrays.asList(getParameters()) : null));
        buffer.append(", messageCode=");
        buffer.append(getMessageCode());
        buffer.append(", messageTitle=");
        buffer.append(getMessageTitle());
        buffer.append(", messageContent=");
        buffer.append(getMessageContent());
        buffer.append(", explanationTitle=");
        buffer.append(getExplanationTitle());
        buffer.append(", explanationContent=");
        buffer.append(getExplanationContent());
        buffer.append(", actionTitle=");
        buffer.append(getActionTitle());
        buffer.append(", actionContent=");
        buffer.append(getActionContent());
        buffer.append(", helpID=");
        buffer.append(getHelpID());
        buffer.append("]");
        
        return buffer.toString();
    }
    
    /**
     ** Returns the appropriate value for the given <code>id</code> and
     ** <code>suffix</code>. If a value is not found, <code>null</code> is
     ** returned. If the value for the <code>id</code> is not found (means
     ** the <code>suffix</code> is <code>null</code>), a MessageRetrieveException
     ** is thrown.
     **
     ** @pre        true
     ** @post       true
     **
     ** @param      resourceBundle   The ResourceBundle containing the resource
     **                              defined by <code>id</code>.
     ** @param      id               The message resource id.
     ** @param      suffix           The suffix of the resource key.
     **
     ** @return     the value for the given <code>id</code> and <code>suffix</code>.
     **
     ** @throws     MessageRetrieveException if retrieving the Message content from the
     **                                      given ResourceBundle fails for any reason.
     **/
    protected static String getResourceString(ResourceBundle resourceBundle, String id, String suffix) throws MessageRetrieveException {
        
        String value = null;
        if (suffix == null) {
            try {
                value = resourceBundle.getString(id);
            }
            catch (MissingResourceException e) {
                // id is mandatory
                //zsa//if(logger.isLoggable(Level.FINE)) { logger.throwing(LOG_NAME,"Resource not found", e); }
                throw new MessageRetrieveException(resourceBundle,
                                                   id,
                                                   "Resource for id '" + id + "' not found in ResourceBundle",
                                                   e);
            }
        }
        else {
            try {
                value = resourceBundle.getString(id + suffix);
            }
            catch (MissingResourceException e) {
                // is OK since these entries are optional
            }
        }
        return value;
    }
    
}
