/*****************************************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ****************************************************************************************/
package gov.va.med.esr.common.model.security;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.ToStringBuilder;

import gov.va.med.esr.common.model.lookup.Capability;

public class CapabilitySet extends AbstractPermission implements Comparable {

   /**
    * An instance of serialVersionUID
    */
   private static final long serialVersionUID = 4731870603981647496L;

   private Set internalCapabilities;

   public CapabilitySet() {
      super();
   }

   /**
    * Returns all the capabilities assigned
    * 
    * @return
    */
   public Set getCapabilities() {
      Set capabilities = new HashSet();
      // get the capabilitySetcapabilities and return the set
      for( Iterator i = getInternalCapabilities().iterator(); i.hasNext(); ) {
         capabilities.add(( (CapabilitySetCapability)i.next() ).getCapability());
      }
      return capabilities;
   }

   /**
    * Return active capabilities
    * 
    * @return
    */
   public List getActiveCapabilities() {
      // check whether the set is active or not
      List capabilities = new ArrayList();
      if( isActive() ) {
         capabilities.addAll(getCapabilities());
      }
      return capabilities;
   }

   /**
    * Helper method to add the Capability to the CapabilitySet
    * 
    * @param capability
    */
   public void addCapability(Capability capability) {
      Validate.notNull(capability, "Can not add null capability");
      if( findCapability(capability) == null ) {
         CapabilitySetCapability capabilitySetCapability = new CapabilitySetCapability(
               this, capability);
         getInternalCapabilities().add(capabilitySetCapability);
      }
   }

   /**
    * Helper method to remove Capability.
    * 
    * @param capability
    */
   public void removeCapability(Capability capability) {
      Validate.notNull(capability, "Can not remove null Capability");
      CapabilitySetCapability capabilitySetCapability = findCapability(capability);
      if( capabilitySetCapability != null ) {
         getInternalCapabilities().remove(capabilitySetCapability);
      }
   }

   /**
    * Helper method to remove all Capabilities.
    * 
    * @param none
    */
   public void removeAllCapabilities() {
      getInternalCapabilities().clear();
   }

   public int compareTo(Object o) {
      if( o != null && o instanceof CapabilitySet )
         return getName().compareTo(( (CapabilitySet)o ).getName());
      else
         return 1;
   }

   /**
    * Find a Capability from in the internale collection of CapabilitySetCapabilities
    * 
    * @param capability
    * @return CapabilitySetCapability
    */
   private CapabilitySetCapability findCapability(Capability capability) {
      for( Iterator iter = getInternalCapabilities().iterator(); iter.hasNext(); ) {
         CapabilitySetCapability capabilitySetCapability = (CapabilitySetCapability)iter
               .next();
         if( capability.equals(capabilitySetCapability.getCapability())
               || capability.getCode().equals(
                     capabilitySetCapability.getCapability().getCode()) ) {
            return capabilitySetCapability;
         }
      }
      return null;
   }

   protected void buildToString(ToStringBuilder builder) {
      super.buildToString(builder);
      builder.append("internalCapabilities", this.internalCapabilities);
   }

   public Set getInternalCapabilities() {
      if( internalCapabilities == null )
         internalCapabilities = new HashSet();
      return internalCapabilities;
   }

   private void setInternalCapabilities(Set internalCapabilities) {
      this.internalCapabilities = internalCapabilities;
   }
   
   protected void finalize() throws Throwable {
      super.finalize();
      setInternalCapabilities( null );
   }
}
