package users;

import sale.*;

/**
  * A special capability guarding an action object.
  *
  * <p>The ActionCapability is itself an Action again, so that you can write code like
  * this:</p>
  *
  * <pre>
  *   public class S extends SalesPoint {
  *
  *   ...
  *
  *     public MenuSheet getDefaultMenuSheet() {
  *
  *       MenuSheet ms = new MenuSheet();
  *
  * <b>      ms.addItem ("Capability Test",
  *         (Action) {@link SalesPoint#getUser getUser}().{@link User#getCapability getCapability}("CapTest"));
  * </b>
  *       return ms;
  *     }
  *
  *   ...
  *
  *   }
  *
  * </pre>
  *
  * <p>Assuming that the CapTest capability is represented by an ActionCapability wrapping
  * some other Action.</p>
  *
  * @see SalesPoint
  * @see MenuSheet
  * @see UserManager
  * @see User
  *
  * @author Steffen Zschaler
  * @version 2.0 05/05/1999
  * @since v2.0
  */
public class ActionCapability extends AbstractCapability implements Action {

  /**
    * Is this capability granted?
    *
    * @serial
    */
  private boolean m_fGranted;

  /**
    * The action guarded.
    *
    * @serial
    */
  private Action  m_aToDo;

  /**
    * A message to be presented on denial.
    *
    * @serial
    */
  private String  m_sOnDeny;

  /**
    * Create a granted capability.
    *
    * @param sName the name of the capability.
    * @param aToDo the Action to be guarded.
    */
  public ActionCapability (String sName,
                           Action aToDo) {
    this (sName, null, aToDo, true);
  }

  /**
    * Create a new ActionCapability.
    *
    * @param sName the name of the capability.
    * @param sOnDeny a message to be popped up on denial.
    * @param aToDo the Action to be guarded.
    * @param fGranted true if this capability is to grant rights.
    */
  public ActionCapability (String sName,
                           String sOnDeny,
                           Action aToDo,
                           boolean fGranted) {
    super (sName);

    m_sOnDeny = sOnDeny;
    m_aToDo = aToDo;
    m_fGranted = fGranted;
  }

  // Capability interface methods

  /**
    * Get the ActionCapability that is the inverse to this one. I.e. if this capability grants the right to
    * execute a given action, the returned capability will deny this right and vice versa.
    *
    * @return the ActionCapability that is the inverse to this one.
    *
    * @override Never
    */
  public Capability getToggled() {
    return new ActionCapability (getName(), m_sOnDeny, m_aToDo, !m_fGranted);
  }

  /**
    * Return true if this capability is granting rights.
    *
    * @return true if this capability is granting rights.
    *
    * @override Never
    */
  public boolean isGranted() {
    return m_fGranted;
  }

  // Action interface method

  /**
    * If the capability is granting rights, perform the guarded action; otherwise,
    * print a message to the user that he/she is not granted the right to
    * perform this action.
    *
    * @param p the process in which to perform the action
    * @param sp the SalesPoint on which to perform the action.
    *
    * @override Never
    */
  public void doAction (SaleProcess p, SalesPoint sp) throws Throwable {
    // This is not the proper way, normally the two cases should be different subclasses
    // of Capability, but for the sake of useability I put it like this.
    if (m_fGranted) {
      if (m_aToDo != null)
        m_aToDo.doAction (p, sp);
    }
    else {
      if (m_sOnDeny != null)
        // use the JOptionPane to make it easy to pop up a message box.
        // Should actually be using a p.popupFormSheet (new MsgForm (...)) instead
        javax.swing.JOptionPane.showMessageDialog (null, m_sOnDeny, "Error", javax.swing.JOptionPane.ERROR_MESSAGE);
    }
  }
}