// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package com.google.protobuf;

import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * A table of known extensions, searchable by name or field number.  When
 * parsing a protocol message that might have extensions, you must provide
 * an {@code ExtensionRegistry} in which you have registered any extensions
 * that you want to be able to parse.  Otherwise, those extensions will just
 * be treated like unknown fields.
 *
 * <p>For example, if you had the {@code .proto} file:
 *
 * <pre>
 * option java_class = "MyProto";
 *
 * message Foo {
 *   extensions 1000 to max;
 * }
 *
 * extend Foo {
 *   optional int32 bar;
 * }
 * </pre>
 *
 * Then you might write code like:
 *
 * <pre>
 * ExtensionRegistry registry = ExtensionRegistry.newInstance();
 * registry.add(MyProto.bar);
 * MyProto.Foo message = MyProto.Foo.parseFrom(input, registry);
 * </pre>
 *
 * <p>Background:
 *
 * <p>You might wonder why this is necessary.  Two alternatives might come to
 * mind.  First, you might imagine a system where generated extensions are
 * automatically registered when their containing classes are loaded.  This
 * is a popular technique, but is bad design; among other things, it creates a
 * situation where behavior can change depending on what classes happen to be
 * loaded.  It also introduces a security vulnerability, because an
 * unprivileged class could cause its code to be called unexpectedly from a
 * privileged class by registering itself as an extension of the right type.
 *
 * <p>Another option you might consider is lazy parsing: do not parse an
 * extension until it is first requested, at which point the caller must
 * provide a type to use.  This introduces a different set of problems.  First,
 * it would require a mutex lock any time an extension was accessed, which
 * would be slow.  Second, corrupt data would not be detected until first
 * access, at which point it would be much harder to deal with it.  Third, it
 * could violate the expectation that message objects are immutable, since the
 * type provided could be any arbitrary message class.  An unprivileged user
 * could take advantage of this to inject a mutable object into a message
 * belonging to privileged code and create mischief.
 *
 * @author kenton@google.com Kenton Varda
 */
public class ExtensionRegistry extends ExtensionRegistryLite {
  /** Construct a new, empty instance. */
  public static ExtensionRegistry newInstance() {
    return new ExtensionRegistry();
  }

  /** Get the unmodifiable singleton empty instance. */
  public static ExtensionRegistry getEmptyRegistry() {
    return EMPTY;
  }


  /** Returns an unmodifiable view of the registry. */
  @Override
  public ExtensionRegistry getUnmodifiable() {
    return new ExtensionRegistry(this);
  }

  /** A (Descriptor, Message) pair, returned by lookup methods. */
  public static final class ExtensionInfo {
    /** The extension's descriptor. */
    public final FieldDescriptor descriptor;

    /**
     * A default instance of the extension's type, if it has a message type.
     * Otherwise, {@code null}.
     */
    public final Message defaultInstance;

    private ExtensionInfo(final FieldDescriptor descriptor) {
      this.descriptor = descriptor;
      defaultInstance = null;
    }
    private ExtensionInfo(final FieldDescriptor descriptor,
                          final Message defaultInstance) {
      this.descriptor = descriptor;
      this.defaultInstance = defaultInstance;
    }
  }

  /**
   * Deprecated. Use {@link #findImmutableExtensionByName(String)} instead.
   */
  public ExtensionInfo findExtensionByName(final String fullName) {
    return findImmutableExtensionByName(fullName);
  }

  /**
   * Find an extension for immutable APIs by fully-qualified field name,
   * in the proto namespace. i.e. {@code result.descriptor.fullName()} will
   * match {@code fullName} if a match is found.
   *
   * @return Information about the extension if found, or {@code null}
   *         otherwise.
   */
  public ExtensionInfo findImmutableExtensionByName(final String fullName) {
    return immutableExtensionsByName.get(fullName);
  }

  /**
   * Find an extension for mutable APIs by fully-qualified field name,
   * in the proto namespace. i.e. {@code result.descriptor.fullName()} will
   * match {@code fullName} if a match is found.
   *
   * @return Information about the extension if found, or {@code null}
   *         otherwise.
   */
  public ExtensionInfo findMutableExtensionByName(final String fullName) {
    return mutableExtensionsByName.get(fullName);
  }

  /**
   * Deprecated. Use {@link #findImmutableExtensionByNumber(
   * Descriptors.Descriptor, int)}
   */
  public ExtensionInfo findExtensionByNumber(
      final Descriptor containingType, final int fieldNumber) {
    return findImmutableExtensionByNumber(containingType, fieldNumber);
  }

  /**
   * Find an extension by containing type and field number for immutable APIs.
   *
   * @return Information about the extension if found, or {@code null}
   *         otherwise.
   */
  public ExtensionInfo findImmutableExtensionByNumber(
      final Descriptor containingType, final int fieldNumber) {
    return immutableExtensionsByNumber.get(
      new DescriptorIntPair(containingType, fieldNumber));
  }

  /**
   * Find an extension by containing type and field number for mutable APIs.
   *
   * @return Information about the extension if found, or {@code null}
   *         otherwise.
   */
  public ExtensionInfo findMutableExtensionByNumber(
      final Descriptor containingType, final int fieldNumber) {
    return mutableExtensionsByNumber.get(
        new DescriptorIntPair(containingType, fieldNumber));
  }

  /**
   * Find all extensions for mutable APIs by fully-qualified name of
   * extended class. Note that this method is more computationally expensive
   * than getting a single extension by name or number.
   *
   * @return Information about the extensions found, or {@code null} if there
   *     are none.
   */
  public Set<ExtensionInfo> getAllMutableExtensionsByExtendedType(final String fullName) {
    HashSet<ExtensionInfo> extensions = new HashSet<ExtensionInfo>();
    for (DescriptorIntPair pair : mutableExtensionsByNumber.keySet()) {
      if (pair.descriptor.getFullName().equals(fullName)) {
        extensions.add(mutableExtensionsByNumber.get(pair));
      }
    }
    return extensions;
  }

  /**
   * Find all extensions for immutable APIs by fully-qualified name of
   * extended class. Note that this method is more computationally expensive
   * than getting a single extension by name or number.
   *
   * @return Information about the extensions found, or {@code null} if there
   *     are none.
   */
  public Set<ExtensionInfo> getAllImmutableExtensionsByExtendedType(final String fullName) {
    HashSet<ExtensionInfo> extensions = new HashSet<ExtensionInfo>();
    for (DescriptorIntPair pair : immutableExtensionsByNumber.keySet()) {
      if (pair.descriptor.getFullName().equals(fullName)) {
        extensions.add(immutableExtensionsByNumber.get(pair));
      }
    }
    return extensions;
  }

  /** Add an extension from a generated file to the registry. */
  public void add(final Extension<?, ?> extension) {
    if (extension.getExtensionType() != Extension.ExtensionType.IMMUTABLE &&
        extension.getExtensionType() != Extension.ExtensionType.MUTABLE) {
      // do not support other extension types. ignore
      return;
    }
    add(newExtensionInfo(extension), extension.getExtensionType());
  }

  static ExtensionInfo newExtensionInfo(final Extension<?, ?> extension) {
    if (extension.getDescriptor().getJavaType() ==
        FieldDescriptor.JavaType.MESSAGE) {
      if (extension.getMessageDefaultInstance() == null) {
        throw new IllegalStateException(
            "Registered message-type extension had null default instance: " +
                extension.getDescriptor().getFullName());
      }
      return new ExtensionInfo(extension.getDescriptor(),
          (Message) extension.getMessageDefaultInstance());
    } else {
      return new ExtensionInfo(extension.getDescriptor(), null);
    }
  }

  /** Add a non-message-type extension to the registry by descriptor. */
  public void add(final FieldDescriptor type) {
    if (type.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
      throw new IllegalArgumentException(
        "ExtensionRegistry.add() must be provided a default instance when " +
        "adding an embedded message extension.");
    }
    ExtensionInfo info = new ExtensionInfo(type, null);
    add(info, Extension.ExtensionType.IMMUTABLE);
    add(info, Extension.ExtensionType.MUTABLE);
  }

  /** Add a message-type extension to the registry by descriptor. */
  public void add(final FieldDescriptor type, final Message defaultInstance) {
    if (type.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
      throw new IllegalArgumentException(
        "ExtensionRegistry.add() provided a default instance for a " +
        "non-message extension.");
    }
      add(new ExtensionInfo(type, defaultInstance),
          Extension.ExtensionType.IMMUTABLE);
  }

  // =================================================================
  // Private stuff.

  private ExtensionRegistry() {
    this.immutableExtensionsByName = new HashMap<String, ExtensionInfo>();
    this.mutableExtensionsByName = new HashMap<String, ExtensionInfo>();
    this.immutableExtensionsByNumber =
        new HashMap<DescriptorIntPair, ExtensionInfo>();
    this.mutableExtensionsByNumber =
        new HashMap<DescriptorIntPair, ExtensionInfo>();
  }

  private ExtensionRegistry(ExtensionRegistry other) {
    super(other);
    this.immutableExtensionsByName =
        Collections.unmodifiableMap(other.immutableExtensionsByName);
    this.mutableExtensionsByName =
        Collections.unmodifiableMap(other.mutableExtensionsByName);
    this.immutableExtensionsByNumber =
        Collections.unmodifiableMap(other.immutableExtensionsByNumber);
    this.mutableExtensionsByNumber =
            Collections.unmodifiableMap(other.mutableExtensionsByNumber);
  }

  private final Map<String, ExtensionInfo> immutableExtensionsByName;
  private final Map<String, ExtensionInfo> mutableExtensionsByName;
  private final Map<DescriptorIntPair, ExtensionInfo> immutableExtensionsByNumber;
  private final Map<DescriptorIntPair, ExtensionInfo> mutableExtensionsByNumber;

  ExtensionRegistry(boolean empty) {
    super(ExtensionRegistryLite.getEmptyRegistry());
    this.immutableExtensionsByName =
        Collections.<String, ExtensionInfo>emptyMap();
    this.mutableExtensionsByName =
        Collections.<String, ExtensionInfo>emptyMap();
    this.immutableExtensionsByNumber =
        Collections.<DescriptorIntPair, ExtensionInfo>emptyMap();
    this.mutableExtensionsByNumber =
            Collections.<DescriptorIntPair, ExtensionInfo>emptyMap();
  }
  private static final ExtensionRegistry EMPTY = new ExtensionRegistry(true);

  private void add(
      final ExtensionInfo extension,
      final Extension.ExtensionType extensionType) {
    if (!extension.descriptor.isExtension()) {
      throw new IllegalArgumentException(
          "ExtensionRegistry.add() was given a FieldDescriptor for a regular " +
              "(non-extension) field.");
    }

    Map<String, ExtensionInfo> extensionsByName;
    Map<DescriptorIntPair, ExtensionInfo> extensionsByNumber;
    switch (extensionType) {
      case IMMUTABLE:
        extensionsByName = immutableExtensionsByName;
        extensionsByNumber = immutableExtensionsByNumber;
        break;
      case MUTABLE:
        extensionsByName = mutableExtensionsByName;
        extensionsByNumber = mutableExtensionsByNumber;
        break;
      default:
        // Ignore the unknown supported type.
        return;
    }

    extensionsByName.put(extension.descriptor.getFullName(), extension);
    extensionsByNumber.put(
      new DescriptorIntPair(extension.descriptor.getContainingType(),
                            extension.descriptor.getNumber()),
      extension);

    final FieldDescriptor field = extension.descriptor;
    if (field.getContainingType().getOptions().getMessageSetWireFormat() &&
        field.getType() == FieldDescriptor.Type.MESSAGE &&
        field.isOptional() &&
        field.getExtensionScope() == field.getMessageType()) {
      // This is an extension of a MessageSet type defined within the extension
      // type's own scope.  For backwards-compatibility, allow it to be looked
      // up by type name.
      extensionsByName.put(field.getMessageType().getFullName(), extension);
    }
  }

  /** A (GenericDescriptor, int) pair, used as a map key. */
  private static final class DescriptorIntPair {
    private final Descriptor descriptor;
    private final int number;

    DescriptorIntPair(final Descriptor descriptor, final int number) {
      this.descriptor = descriptor;
      this.number = number;
    }

    @Override
    public int hashCode() {
      return descriptor.hashCode() * ((1 << 16) - 1) + number;
    }
    @Override
    public boolean equals(final Object obj) {
      if (!(obj instanceof DescriptorIntPair)) {
        return false;
      }
      final DescriptorIntPair other = (DescriptorIntPair)obj;
      return descriptor == other.descriptor && number == other.number;
    }
  }
}
