
package uk.co.wingpath.modbus;


/**
* This class is used to represent Modbus error response messages.
* <p>The header fields (slave ID, function code and transaction identifier) and
* the error code are specified when an instance is constructed.
* A string describing the error may also be supplied - this is used to
* provide more informative message tracing.
*/
public class ModbusErrorResponse
    extends ModbusResponse
{
    private final String helpId;
    private final String errorString;
    private final int errorCode;

    /**
    * Constructs a ModbusResponse with the specified slave id,
    * function code, transaction identifier, error code and error string.
    * @param slaveId slave identifier.
    * @param function function code.
    * @param transId transaction identifier, or -1 if the transaction
    * identifier is not defined (i.e. for RTU and ASCII packets).
    * @param errorCode error code.
    * @param helpId the help identifier. May be {@code null} if specific
    * help is not available.
    * @param errorString error string.
    */
    private ModbusErrorResponse (int slaveId, int function, int transId,
        int errorCode, String helpId, String errorString)
    {
        super (slaveId, function | 0x80, transId,
            new byte [] { (byte) errorCode });
        this.errorCode = errorCode;
        this.helpId = helpId;
        this.errorString = errorString;
    }

    /**
    * Constructs a ModbusResponse with the specified slave id,
    * function code, transaction identifier, and error code.
    * @param slaveId slave identifier.
    * @param function function code.
    * @param transId transaction identifier.
    * @param errorCode error code.
    */
    public ModbusErrorResponse (int slaveId, int function, int transId,
        int errorCode)
    {
        this (slaveId, function, transId, errorCode,
            Modbus.getHelpId (errorCode), null);
    }

    /**
    * Constructs a ModbusResponse with the specified slave id,
    * function code, and transaction identifier. The error code, help ID,
    *  and error string are taken from the supplied Modbus exception.
    * @param slaveId slave identifier.
    * @param function function code.
    * @param transId transaction identifier.
    * @param e Modbus exception.
    */
    public ModbusErrorResponse (int slaveId, int function, int transId,
        ModbusException e)
    {
        this (slaveId, function, transId, e.getErrorCode (), e.getHelpId (),
            e.getExplanation ());
    }

    /**
    * Returns the error code.
    * @return the error code.
    */
    public int getErrorCode ()
    {
        return errorCode;
    }

    /**
    * Returns the error string.
    * @return the error string.
    */
    public String getErrorString ()
    {
        return errorString;
    }

    @Override
    public void checkSize (boolean allowLongMessages)
        throws ModbusException
    {
        checkSize (1);
    }

    @Override
    void traceExplanation (Tracer tracer)
    {
        if (tracer == null || !tracer.isTraceEnabled ())
            return;
        StringBuilder msg = new StringBuilder ();
        msg.append ("Error response: ");
        msg.append (Modbus.getErrorMessage (errorCode));
        if (errorString != null)
        {
            msg.append (" - ");
            msg.append (errorString);
        }
        traceExplanation (tracer, helpId, msg.toString ());
    }

    @Override
    void traceSend (Tracer tracer)
    {
        trace (tracer, ">", helpId);
    }

    @Override
    void traceReceive (Tracer tracer)
    {
        trace (tracer, "<", helpId);
    }

}

