/*
 * Copyright (c) 2002,2006 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 */
package com.ibm.wala.shrike.shrikeBT;

import java.util.Objects;

/**
 * An ExceptionHandler represents a single handler covering a single instruction. It simply tells us
 * what kind of exception to catch and where to dispatch the exception to.
 *
 * <p>ExceptionHandlers are immutable. It is quite legal to save a reference to an exception handler
 * and use it in any other context. We also treat arrays of ExceptionHandlers as immutable.
 * Therefore the following code can be used to build an exception handler table that specifies two
 * handlers covering an entire block of code:
 *
 * <pre>
 *
 *   ExceptionHandler[] hs = {
 *     new ExceptionHandler(110, &quot;Ljava.lang.NullPointerException;&quot;),
 *     new ExceptionHandler(220, &quot;Ljava.io.IOException;&quot;);
 *   };
 *   for (int i = 0; i &lt; 100; i++) {
 *     handlers[i] = hs;
 *   }
 * </pre>
 */
public final class ExceptionHandler {

  int handler;

  final String catchClass;

  final Object catchClassLoader;

  /**
   * @param handler the label for the handler code
   * @param catchClass the type of exception that should be caught (in JVM format), or null if all
   *     exceptions should be caught (as with 'finally')
   */
  public ExceptionHandler(int handler, String catchClass, Object catchClassLoader) {
    this.handler = handler;
    this.catchClass = catchClass;
    this.catchClassLoader = catchClassLoader;
  }

  public ExceptionHandler(int handler, String catchClass) {
    this(handler, catchClass, null);
  }

  /** @return the label of the handler code */
  public int getHandler() {
    return handler;
  }

  public Object getCatchClassLoader() {
    return catchClassLoader;
  }

  /** @return the type of exceptions to be caught, or null if all exceptions should be caught */
  public String getCatchClass() {
    return catchClass;
  }

  public boolean equals(ExceptionHandler h) {
    if (h == null) {
      throw new IllegalArgumentException("h is null");
    }
    return h.handler == handler && Objects.equals(catchClass, h.catchClass);
  }

  @Override
  public int hashCode() {
    return 1069 * handler + ((catchClass == null) ? 0 : catchClass.hashCode());
  }

  @Override
  public boolean equals(Object o) {
    if (o instanceof ExceptionHandler) {
      return equals((ExceptionHandler) o);
    } else {
      return false;
    }
  }
}
