/*
 * 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.ambari.server.state.kerberos;

import org.apache.ambari.server.AmbariException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * AbstractKerberosDescriptorContainer is an abstract class implementing AbstractKerberosDescriptor
 * and providing facility to handle common descriptor container functionality.
 * <p/>
 * Each AbstractKerberosDescriptorContainer contains identities and configurations as well as a
 * name and a parent (which is inherited from AbstractKerberosDescriptor).
 * <p/>
 * An AbstractKerberosDescriptorContainer has the following properties:
 * <ul>
 * <li>identities</li>
 * <li>configurations</li>
 * </ul>
 * <p/>
 * The following (pseudo) JSON Schema will yield a valid AbstractKerberosDescriptorContainer
 * <pre>
 *   {
 *      "$schema": "http://json-schema.org/draft-04/schema#",
 *      "title": "AbstractKerberosDescriptorContainer",
 *      "description": "Describes an AbstractKerberosDescriptorContainer",
 *      "type": "object",
 *      "properties": {
 *        "identities": {
 *          "description": "A list of Kerberos identity descriptors",
 *          "type": "array",
 *          "items": {
 *            "title": "KerberosIdentityDescriptor"
 *            "type": "{@link org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor}"
 *          }
 *        },
 *        "configurations": {
 *          "description": "A list of relevant configuration blocks",
 *          "type": "array",
 *          "items": {
 *            "title": "KerberosConfigurationDescriptor"
 *            "type": "{@link org.apache.ambari.server.state.kerberos.KerberosConfigurationDescriptor}"
 *          }
 *        },
 *        "auth_to_local": {
 *          "description": "A list of configuration properties declaring which properties are auth-to-local values
 *          "type": "array",
 *          "items": {
 *            "title": "String"
 *            "type": "{@link java.lang.String}"
 *          }
 *        }
 *      }
 *   }
 * </pre>
 * <p/>
 * This implementation does not set the
 * {@link org.apache.ambari.server.state.kerberos.AbstractKerberosDescriptor#name} value, it is
 * left up to the implementing class to do so.
 */
public abstract class AbstractKerberosDescriptorContainer extends AbstractKerberosDescriptor {

  /**
   * Regular expression pattern used to parse auth_to_local property specifications into the following
   * parts:
   * <ul>
   * <li>configuration type (optional, if _global_)</li>
   * <li>property name</li>
   * <li>concatenation type (optional, if using the default behavior)</li>
   * </ul>
   */
  public static final Pattern AUTH_TO_LOCAL_PROPERTY_SPECIFICATION_PATTERN = Pattern.compile("^(?:(.+?)/)?(.+?)(?:\\|(.+?))?$");

  /**
   * A List of KerberosIdentityDescriptors contained in this AbstractKerberosDescriptorContainer
   */
  private List<KerberosIdentityDescriptor> identities = null;

  /**
   * A Map of KerberosConfigurationDescriptors contained in this AbstractKerberosDescriptorContainer
   */
  private Map<String, KerberosConfigurationDescriptor> configurations = null;

  /**
   * A Set of configuration identifiers (config-type/property_name) that indicate which properties
   * contain auth_to_local values.
   */
  private Set<String> authToLocalProperties = null;

  /**
   * Constructs a new AbstractKerberosDescriptorContainer
   * <p/>
   * This constructor must be called from the constructor(s) of the implementing classes
   *
   * @param data a Map of data used for collecting groups of common descriptors
   */
  protected AbstractKerberosDescriptorContainer(Map<?, ?> data) {
    if (data != null) {
      Object list;

      // (Safely) Get the set of KerberosIdentityDescriptors
      list = data.get(Type.IDENTITY.getDescriptorPluralName());
      if (list instanceof Collection) {
        for (Object item : (Collection) list) {
          if (item instanceof Map) {
            putIdentity(new KerberosIdentityDescriptor((Map<?, ?>) item));
          }
        }
      }

      // (Safely) Get the set of KerberosConfigurationDescriptors
      list = data.get(Type.CONFIGURATION.getDescriptorPluralName());
      if (list instanceof Collection) {
        for (Object item : (Collection) list) {
          if (item instanceof Map) {
            putConfiguration(new KerberosConfigurationDescriptor((Map<?, ?>) item));
          }
        }
      }

      // (Safely) Get the set of KerberosConfigurationDescriptors
      list = data.get(Type.AUTH_TO_LOCAL_PROPERTY.getDescriptorPluralName());
      if (list instanceof Collection) {
        for (Object item : (Collection) list) {
          if (item instanceof String) {
            putAuthToLocalProperty((String) item);
          }
        }
      }
    }
  }

  /**
   * Returns the child containers associated with this container.
   *
   * @return an immutable collection of {@link AbstractKerberosDescriptorContainer}s
   */
  public abstract Collection<? extends AbstractKerberosDescriptorContainer> getChildContainers();

  /**
   * Returns a specific named child container
   * @param name the name of the child container to retrieve
   *
   * @return an {@link AbstractKerberosDescriptorContainer}
   */
  public abstract AbstractKerberosDescriptorContainer getChildContainer(String name);

  /**
   * Returns the raw List of KerberosIdentityDescriptors contained within this
   * AbstractKerberosDescriptorContainer.
   * <p/>
   * The returned KerberosIdentityDescriptors are not merged with data from referenced
   * KerberosConfigurationDescriptors. This is the same calling
   * {@link AbstractKerberosDescriptorContainer#getIdentities(boolean, Map)} and setting the
   * argument to 'false'
   *
   * @return the relevant List of KerberosIdentityDescriptors
   */
  public List<KerberosIdentityDescriptor> getIdentities() {
    try {
      return getIdentities(false, null);
    } catch (AmbariException e) {
      // AmbariException will not be thrown unless an error occurs while trying to dereference
      // identities.  This method does not attempt to dereference identities.
      return null;
    }
  }

  /**
   * Returns a List of KerberosIdentityDescriptors contained within this
   * AbstractKerberosDescriptorContainer.
   * <p/>
   * If resolveReferences is true, a "detached" set of KerberosIdentityDescriptors are returned.
   * Any KerberosIdentityDescriptor that implies it references some other KerberosIdentityDescriptor
   * in the hierarchy will be resolved. Meaning, if the name of the KerberosIdentityDescriptor
   * indicates a path to some other KerberosIdentityDescriptor (i.e, /spnego, /HDFS/NAMENODE/nn, etc...)
   * the referenced KerberosIdentityDescriptor is found, detached (or copied), and updated with
   * the information from the initial KerberosIdentityDescriptor.  Because of this, all of the
   * KerberosIdentityDescriptors to be included are copied into the resulting list, and dissociating
   * them with the rest of the hierarchy such that changes to them will not be reflected within the
   * entire KerberosDescriptor tree.
   * <p/>
   * If resolveReferences is false, the raw List of KerberosIdentityDescriptors are returned. This
   * data is not manipulated by resolving references and therefore it may be missing data, however
   * this List is of "attached" descriptors, so changes will be reflected within the KerberosDescriptor
   * hierarchy.
   *
   * @param resolveReferences a Boolean value indicating whether to resolve references (true) or not
   *                          (false)
   * @return a List of the requested KerberosIdentityDescriptors
   */
  public List<KerberosIdentityDescriptor> getIdentities(boolean resolveReferences, Map<String,Object> contextForFilter) throws AmbariException {
    if (identities == null) {
      return Collections.emptyList();
    } else {
      List<KerberosIdentityDescriptor> list = new ArrayList<KerberosIdentityDescriptor>();

      for (KerberosIdentityDescriptor identity : identities) {
        KerberosIdentityDescriptor identityToAdd;

        if (resolveReferences) {
          // Dereference this KerberosIdentityDescriptor, if necessary
          identityToAdd = dereferenceIdentity(identity);
        } else {
          identityToAdd = identity;
        }

        // Make sure this Kerberos Identity is not to be filtered out based on its "when" clause
        if ((identityToAdd != null) && ((contextForFilter == null) || identityToAdd.shouldInclude(contextForFilter))) {
          list.add(identityToAdd);
        }
      }

      return list;
    }
  }

  /**
   * Return a KerberosIdentityDescriptor with the specified name.
   *
   * @param name a String declaring the name of the descriptor to retrieve
   * @return the requested KerberosIdentityDescriptor
   */
  public KerberosIdentityDescriptor getIdentity(String name) {
    KerberosIdentityDescriptor identity = null;

    if ((name != null) && (identities != null)) {
      // Iterate over the List of KerberosIdentityDescriptors to find one with the requested name
      // If one is found, break out of the loop.
      for (KerberosIdentityDescriptor descriptor : identities) {
        if (name.equals(descriptor.getName())) {
          identity = descriptor;
          break;
        }
      }
    }

    return identity;
  }

  /**
   * Adds the specified KerberosIdentityDescriptor to the list of KerberosIdentityDescriptor.
   * <p/>
   * This method attempts to ensure that the names or KerberosIdentityDescriptors are unique within
   * the List.
   *
   * @param identity the KerberosIdentityDescriptor to add
   */
  public void putIdentity(KerberosIdentityDescriptor identity) {
    if (identity != null) {
      String name = identity.getName();

      if (identities == null) {
        identities = new ArrayList<KerberosIdentityDescriptor>();
      }

      // If the identity has a name, ensure that one one with that name is in the List
      // Note: this cannot be enforced since any AbstractKerberosDescriptor+'s name property can be
      // changed
      if ((name != null) && !name.isEmpty()) {
        removeIdentity(identity.getName());
      }

      identities.add(identity);

      // Set the identity's parent to this AbstractKerberosDescriptorContainer
      identity.setParent(this);
    }
  }

  /**
   * Remove all KerberosIdentityDescriptors have have the specified name
   * <p/>
   * One or more KerberosIdentityDescriptors may be removed if multiple KerberosIdentityDescriptors
   * have the same name.
   *
   * @param name a String declaring the name of the descriptors to remove
   */
  public void removeIdentity(String name) {
    if ((name != null) && (identities != null)) {
      Iterator<KerberosIdentityDescriptor> iterator = identities.iterator();

      while (iterator.hasNext()) {
        KerberosIdentityDescriptor identity = iterator.next();
        if (name.equals(identity.getName())) {
          identity.setParent(null);
          iterator.remove();
        }
      }
    }
  }

  /**
   * Returns a Map of raw KerberosConfigurationDescriptors contained within this
   * AbstractKerberosDescriptorContainer.
   * <p/>
   * The returned KerberosConfigurationDescriptors are not merged with data from KerberosDescriptor
   * hierarchy. This is the same calling
   * {@link AbstractKerberosDescriptorContainer#getConfigurations(boolean)} and setting the argument
   * to 'false'
   *
   * @return a List of KerberosConfigurationDescriptors
   */
  public Map<String, KerberosConfigurationDescriptor> getConfigurations() {
    return getConfigurations(false);
  }

  /**
   * Returns a Map of KerberosConfigurationDescriptors contained within this
   * AbstractKerberosDescriptorContainer.
   * <p/>
   * If includeInherited is true, the Map will contain "detached" KerberosConfigurationDescriptor
   * instances, but the data will be merged with all relevant KerberosConfigurationDescriptors within
   * the hierarchy.  Data higher in the hierarchy (the service level is higher in the hierarchy than
   * the component level) will be overwritten by data lower in the hierarchy.
   * <p/>
   * If includeInherited is false, the Map will consist of attached (non-merged)
   * KerberosConfigurationDescriptors. This data is not manipulated by merging with data within the
   * KerberosDescriptor hierarchy and therefore it may be missing data, however this Map is of
   * "attached" descriptors, so changes will be reflected within the KerberosDescriptor
   * hierarchy.
   *
   * @param includeInherited a Boolean value indicating whether to include configuration within the
   *                         KerberosDescriptor hierarchy (true) or not (false)
   * @return a Map of Strings to KerberosConfigurationDescriptors, where the key is the type
   * (core-site, etc...)
   */
  public Map<String, KerberosConfigurationDescriptor> getConfigurations(boolean includeInherited) {
    if (includeInherited) {
      Map<String, KerberosConfigurationDescriptor> mergedConfigurations = new HashMap<String, KerberosConfigurationDescriptor>();
      List<Map<String, KerberosConfigurationDescriptor>> configurationSets = new ArrayList<Map<String, KerberosConfigurationDescriptor>>();
      AbstractKerberosDescriptor currentDescriptor = this;

      // Walk up the hierarchy and collect the configuration sets.
      while (currentDescriptor != null) {
        if (currentDescriptor.isContainer()) {
          Map<String, KerberosConfigurationDescriptor> configurations = ((AbstractKerberosDescriptorContainer) currentDescriptor).getConfigurations();

          if (configurations != null) {
            configurationSets.add(configurations);
          }
        }

        currentDescriptor = currentDescriptor.getParent();
      }

      // Reverse the collection so that we can merge from top to bottom
      Collections.reverse(configurationSets);

      for (Map<String, KerberosConfigurationDescriptor> map : configurationSets) {
        for (Map.Entry<String, KerberosConfigurationDescriptor> entry : map.entrySet()) {
          // For each configuration type, copy it and determine if an entry exists or not.
          // ** If one exists, merge the current data into the existing data (potentially
          //    overwriting values).
          // ** If one does not exist, simply add a copy of the current one to the Map
          String currentType = entry.getKey();
          KerberosConfigurationDescriptor currentConfiguration = entry.getValue();

          if (currentConfiguration != null) {
            KerberosConfigurationDescriptor detachedConfiguration = new KerberosConfigurationDescriptor(currentConfiguration.toMap());
            KerberosConfigurationDescriptor mergedConfiguration = mergedConfigurations.get(entry.getKey());

            if (mergedConfiguration == null) {
              mergedConfigurations.put(currentType, detachedConfiguration);
            } else {
              mergedConfiguration.update(detachedConfiguration);
            }
          }
        }
      }

      return mergedConfigurations;
    } else {
      return configurations;
    }
  }

  /**
   * Adds the specified KerberosConfigurationDescriptor to the list of KerberosConfigurationDescriptors.
   * <p/>
   * If an entry exists of the same configuration type, it will be overwritten.
   *
   * @param configuration the KerberosConfigurationDescriptor to add
   */
  public void putConfiguration(KerberosConfigurationDescriptor configuration) {
    if (configuration != null) {
      String type = configuration.getType();

      if (type == null) {
        throw new IllegalArgumentException("The configuration type must not be null");
      }

      if (configurations == null) {
        configurations = new HashMap<String, KerberosConfigurationDescriptor>();
      }

      configurations.put(type, configuration);

      // Set the configuration's parent to this AbstractKerberosDescriptorContainer
      configuration.setParent(this);
    }
  }

  /**
   * Returns the requested KerberosConfigurationDescriptor
   *
   * @param name a String declaring the name of the descriptor to retrieve
   * @return the requested KerberosConfigurationDescriptor or null if not found
   */
  public KerberosConfigurationDescriptor getConfiguration(String name) {
    return ((name == null) || (configurations == null)) ? null : configurations.get(name);
  }

  /**
   * Adds the specified property name to the set of <code>auth_to_local</code> property names.
   * <p/>
   * Each <code>auth_to_local</code> property name is expected to be in the following format:
   * <code>config-type/property_name</code>`
   *
   * @param authToLocalProperty the auth_to_local property to add
   */
  public void putAuthToLocalProperty(String authToLocalProperty) {
    if (authToLocalProperty != null) {
      if (authToLocalProperties == null) {
        authToLocalProperties = new HashSet<String>();
      }

      authToLocalProperties.add(authToLocalProperty);
    }
  }

  /**
   * Gets the set of <code>auth_to_local</code> property names.
   *
   * @return a Set of String values; or null if not set
   */
  public Set<String> getAuthToLocalProperties() {
    return authToLocalProperties;
  }

  /**
   * Test this AbstractKerberosDescriptor to see if it is a container.
   * <p/>
   * This implementation always returns true since it implements a descriptor container.
   *
   * @return true if this AbstractKerberosDescriptor is a container, false otherwise
   */
  public boolean isContainer() {
    return true;
  }

  /**
   * Updates this AbstractKerberosDescriptorContainer using information from the supplied
   * AbstractKerberosDescriptorContainer.
   * <p/>
   * Information from updates will overwrite information in this AbstractKerberosDescriptorContainer.
   * More specifically, the name of this AbstractKerberosDescriptorContainer may be updated as well
   * as each individual KerberosIdentityDescriptor and KerberosConfigurationDescriptor contained
   * within it.  Any new KerberosIdentityDescriptors and KerberosConfigurationDescriptors will be
   * appended to there appropriate lists.
   *
   * @param updates an AbstractKerberosDescriptorContainer containing the updates to this
   *                AbstractKerberosDescriptorContainer
   */
  public void update(AbstractKerberosDescriptorContainer updates) {
    if (updates != null) {
      String updatedName = updates.getName();
      if (updatedName != null) {
        setName(updatedName);
      }

      Map<String, KerberosConfigurationDescriptor> updatedConfigurations = updates.getConfigurations();
      if (updatedConfigurations != null) {
        for (Map.Entry<String, KerberosConfigurationDescriptor> entry : updatedConfigurations.entrySet()) {
          KerberosConfigurationDescriptor existingConfiguration = getConfiguration(entry.getKey());

          // Copy this descriptor so we don't alter the hierarchy of existing data we don't intend to change
          KerberosConfigurationDescriptor clone = new KerberosConfigurationDescriptor(entry.getValue().toMap());

          if (existingConfiguration == null) {
            putConfiguration(clone);
          } else {
            existingConfiguration.update(clone);
          }
        }
      }

      List<KerberosIdentityDescriptor> updatedIdentities = updates.getIdentities();
      if (updatedIdentities != null) {
        for (KerberosIdentityDescriptor updatedIdentity : updatedIdentities) {
          KerberosIdentityDescriptor existing = getIdentity(updatedIdentity.getName());

          // Copy this descriptor so we don't alter the hierarchy of existing data we don't intend to change
          KerberosIdentityDescriptor clone = new KerberosIdentityDescriptor(updatedIdentity.toMap());

          if (existing == null) {
            putIdentity(clone);
          } else {
            existing.update(clone);
          }
        }
      }

      Set<String> updatedAuthToLocalProperties = updates.getAuthToLocalProperties();
      if (updatedAuthToLocalProperties != null) {
        for (String updatedAuthToLocalProperty : updatedAuthToLocalProperties) {
          putAuthToLocalProperty(updatedAuthToLocalProperty);
        }
      }
    }
  }

  /**
   * Attempts to find the KerberosIdentityDescriptor at the specified path.
   * <p/>
   * The path value is expected to be an "absolute" path through the Kerberos Descriptor hierarchy
   * to some specific KerberosIdentityDescriptor.  The path must be in one of the following forms:
   * <ul>
   * <li>/identity</li>
   * <li>/service/identity</li>
   * <li>/service/component/identity</li>
   * </ul>
   * <p/>
   * If the path starts with "../", the ".." will be translated to the path of the parent item.
   * In the following example, <code>../service_identity</code> will resolve to
   * <code>/SERVICE/service_identity</code>:
   * <pre>
   * {
   *  "name": "SERVICE",
   *  "identities": [
   *    {
   *      "name": "service_identity",
   *      ...
   *    }
   *  ],
   *  "components" : [
   *    {
   *      "name": "COMPONENT",
   *      "identities": [
   *        {
   *          "name": "./service_identity",
   *          ...
   *        },
   *        ...
   *      ]
   *    }
   *  ]
   * }
   * </pre>
   *
   * @param path a String declaring the path to a KerberosIdentityDescriptor
   * @return a KerberosIdentityDescriptor identified by the path or null if not found
   */
  protected KerberosIdentityDescriptor getReferencedIdentityDescriptor(String path)
      throws AmbariException {
    KerberosIdentityDescriptor identityDescriptor = null;

    if (path != null) {
      if(path.startsWith("../")) {
        // Resolve parent path
        AbstractKerberosDescriptor parent = getParent();

        path = path.substring(2);

        while(parent != null) {
          String name = parent.getName();

          if (name != null) {
            path = String.format("/%s", name) + path;
          }

          parent = parent.getParent();
        }
      }

      if (path.startsWith("/")) {
        // The name indicates it is referencing an identity somewhere in the hierarchy... try to find it.
        // /[<service name>/[<component name>/]]<identity name>
        String[] pathParts = path.split("/");

        String serviceName = null;
        String componentName = null;
        String identityName;

        switch (pathParts.length) {
          case 4:
            serviceName = pathParts[1];
            componentName = pathParts[2];
            identityName = pathParts[3];
            break;
          case 3:
            serviceName = pathParts[1];
            identityName = pathParts[2];
            break;
          case 2:
            identityName = pathParts[1];
            break;
          case 1:
            identityName = pathParts[0];
            break;
          default:
            throw new AmbariException(String.format("Unexpected path length in %s", path));
        }

        if (identityName != null) {
          // Start at the top of the hierarchy
          AbstractKerberosDescriptor descriptor = getRoot();

          if (descriptor != null) {
            if ((serviceName != null) && !serviceName.isEmpty()) {
              descriptor = descriptor.getDescriptor(Type.SERVICE, serviceName);

              if ((descriptor != null) && (componentName != null) && !componentName.isEmpty()) {
                descriptor = descriptor.getDescriptor(Type.COMPONENT, componentName);
              }
            }

            if (descriptor != null) {
              descriptor = descriptor.getDescriptor(Type.IDENTITY, identityName);

              if (descriptor instanceof KerberosIdentityDescriptor) {
                identityDescriptor = (KerberosIdentityDescriptor) descriptor;
              }
            }
          }
        }
      }
    }

    return identityDescriptor;
  }

  /**
   * Gets the requested AbstractKerberosDescriptor implementation using a type name and a relevant
   * descriptor name.
   * <p/>
   * This implementation handles identity and configuration descriptors within this
   * AbstractKerberosDescriptorContainer.
   * <p/>
   * Implementing classes should override this to handle other types, but call this method to
   * ensure no data is missed.
   *
   * @param type a String indicating the type of the requested descriptor
   * @param name a String indicating the name of the requested descriptor
   * @return a AbstractKerberosDescriptor representing the requested descriptor or null if not found
   */
  @Override
  protected AbstractKerberosDescriptor getDescriptor(Type type, String name) {
    if (Type.IDENTITY == type) {
      return getIdentity(name);
    } else if (Type.CONFIGURATION == type) {
      return getConfiguration(name);
    } else {
      return null;
    }
  }

  /**
   * Creates a Map of values that can be used to create a copy of this AbstractKerberosDescriptorContainer
   * or generate the JSON structure described in
   * {@link org.apache.ambari.server.state.kerberos.AbstractKerberosDescriptorContainer}
   *
   * @return a Map of values for this AbstractKerberosDescriptorContainer
   * @see org.apache.ambari.server.state.kerberos.AbstractKerberosDescriptorContainer
   */
  @Override
  public Map<String, Object> toMap() {
    Map<String, Object> map = super.toMap();

    if (identities != null) {
      List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
      for (KerberosIdentityDescriptor identity : identities) {
        list.add(identity.toMap());
      }
      map.put(Type.IDENTITY.getDescriptorPluralName(), list);
    }

    if (configurations != null) {
      List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
      for (KerberosConfigurationDescriptor configuration : configurations.values()) {
        list.add(configuration.toMap());
      }
      map.put(Type.CONFIGURATION.getDescriptorPluralName(), list);
    }

    if (authToLocalProperties != null) {
      List<String> list = new ArrayList<String>(authToLocalProperties);
      map.put(Type.AUTH_TO_LOCAL_PROPERTY.getDescriptorPluralName(), list);
    }

    return map;
  }

  @Override
  public int hashCode() {
    return super.hashCode() +
        ((getIdentities() == null)
            ? 0
            : getIdentities().hashCode()) +
        ((getConfigurations() == null)
            ? 0
            : getConfigurations().hashCode());
  }

  @Override
  public boolean equals(Object object) {
    if (object == null) {
      return false;
    } else if (object == this) {
      return true;
    } else if (object instanceof AbstractKerberosDescriptorContainer) {
      AbstractKerberosDescriptorContainer descriptor = (AbstractKerberosDescriptorContainer) object;
      return super.equals(object) &&
          (
              (getIdentities() == null)
                  ? (descriptor.getIdentities() == null)
                  : getIdentities().equals(descriptor.getIdentities())
          ) &&
          (
              (getConfigurations() == null)
                  ? (descriptor.getConfigurations() == null)
                  : getConfigurations().equals(descriptor.getConfigurations())
          );
    } else {
      return false;
    }
  }

  /**
   * Recursively dereference a referenced identity.
   * <p>
   * Follows the path of references such that the top-most identity definition (one with no pointer
   * to a referenced identity) contains the base  information which is copied and updated with the
   * referencing identity's data. The composite identity is then update with the next referencing
   * identity's data, and so on until the initial identity is encountered.
   *
   * @param identity the initial identity to dereference
   * @return a (disconnected) {@link KerberosIdentityDescriptor} built by traversing the identity
   * references; or the input identity if it does not reference any other identities.
   * @throws AmbariException
   */
  private KerberosIdentityDescriptor dereferenceIdentity(KerberosIdentityDescriptor identity) throws AmbariException {
    KerberosIdentityDescriptor dereferencedIdentity = null;

    if(identity != null) {
      KerberosIdentityDescriptor referencedIdentity;
      try {
        if (identity.getReference() != null) {
          referencedIdentity = getReferencedIdentityDescriptor(identity.getReference());
        } else {
          // For backwards compatibility, see if the identity's name indicates a reference...
          referencedIdentity = getReferencedIdentityDescriptor(identity.getName());
        }
      } catch (AmbariException e) {
        throw new AmbariException(String.format("Invalid Kerberos identity reference: %s", identity.getReference()), e);
      }

      if (referencedIdentity != null) {
        dereferencedIdentity = dereferenceIdentity(referencedIdentity);  // Dereference the "parent"...

        if (dereferencedIdentity != null) {
          dereferencedIdentity.update(identity);
        } else {
          dereferencedIdentity = new KerberosIdentityDescriptor(referencedIdentity.toMap());
          dereferencedIdentity.update(identity);
        }
      }
      else {
        dereferencedIdentity = new KerberosIdentityDescriptor(identity.toMap());
      }
    }

    return dereferencedIdentity;
  }
}
