All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.tinymediamanager.scraper.DynaEnum Maven / Gradle / Ivy

/*
 * Copyright 2012 - 2019 Manuel Laggner
 *
 * Licensed 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.tinymediamanager.scraper;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * The class DynaEnum is used to create a "dynamic" enum - an enum which is extensible at runtime
 * 
 * @param 
 *          the element type
 * @author Manuel Laggner
 * @since 1.0
 */
public abstract class DynaEnum> {
  private static Map>, Map>>   elements  = new LinkedHashMap<>();
  private static Map>, Set> listeners = new LinkedHashMap<>();
  private final String                                                         name;
  protected final int                                                          ordinal;

  public final String name() {
    return name;
  }

  /**
   * Ordinal.
   * 
   * @return the int
   */
  public final int ordinal() {
    return ordinal;
  }

  /**
   * Instantiates a new dyna enum. do not forget to add this value to the list of values after the constructor has been finished
   * 
   * @param name
   *          the name
   * @param ordinal
   *          the ordinal
   */
  protected DynaEnum(String name, int ordinal) {
    this.name = name;
    this.ordinal = ordinal;
  }

  /**
   * add this element to the list of elements
   */
  protected void addElement() {
    Map> typeElements = elements.get(getClass());
    if (typeElements == null) {
      typeElements = new LinkedHashMap<>();
      elements.put(getDynaEnumClass(), typeElements);
    }
    typeElements.put(name, this);

    valueAdded(getClass(), this);
  }

  /**
   * Gets the dyna enum class.
   * 
   * @return the dyna enum class
   */
  @SuppressWarnings("unchecked")
  private Class> getDynaEnumClass() {
    return (Class>) getClass();
  }

  @Override
  public String toString() {
    return name;
  }

  @Override
  public final boolean equals(Object other) {
    return this == other;
  }

  @Override
  public final int hashCode() {
    return super.hashCode();
  }

  @Override
  protected final Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException();
  }

  public final int compareTo(E other) {
    DynaEnum self = this;
    if (self.getClass() != other.getClass() && // optimization
        self.getDeclaringClass() != other.getDeclaringClass()) {
      throw new ClassCastException();
    }
    return self.ordinal - other.ordinal;
  }

  @SuppressWarnings({ "unchecked", "rawtypes" })
  public final Class getDeclaringClass() {
    Class clazz = getClass();
    Class zuper = clazz.getSuperclass();
    return (zuper == DynaEnum.class) ? clazz : zuper;
  }

  /**
   * Value of.
   * 
   * @param 
   *          the generic type
   * @param enumType
   *          the enum type
   * @param name
   *          the name
   * @return the t
   */
  @SuppressWarnings("unchecked")
  public static > T valueOf(Class enumType, String name) {
    return (T) elements.get(enumType).get(name);
  }

  /**
   * Read object.
   * 
   * @param in
   *          the in
   * @throws IOException
   *           Signals that an I/O exception has occurred.
   * @throws ClassNotFoundException
   *           the class not found exception
   */
  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    throw new InvalidObjectException("can't deserialize enum");
  }

  /**
   * Read object no data.
   * 
   * @throws ObjectStreamException
   *           the object stream exception
   */
  @SuppressWarnings("unused")
  private void readObjectNoData() throws ObjectStreamException {
    throw new InvalidObjectException("can't deserialize enum");
  }

  /**
   * Values.
   * 
   * @param 
   *          the element type
   * @return the dyna enum>[]
   */
  public static  DynaEnum>[] values() {
    throw new IllegalStateException("Sub class of DynaEnum must implement method values()");
  }

  /**
   * Values.
   * 
   * @param 
   *          the element type
   * @param enumType
   *          the enum type
   * @return the e[]
   */
  @SuppressWarnings("unchecked")
  public static  E[] values(Class enumType) {
    Collection> values = elements.get(enumType).values();
    int n = values.size();
    E[] typedValues = (E[]) Array.newInstance(enumType, n);
    int i = 0;
    for (DynaEnum value : values) {
      Array.set(typedValues, i, value);
      i++;
    }

    return typedValues;
  }

  /**
   * add a new DynaEnumEventListener. This listener will be informed if any new value has been added
   *
   * @param clazz
   *          the class to register the listener for
   * @param listener
   *          the new listener to be added
   */
  protected static void addListener(Class> clazz, DynaEnumEventListener listener) {
    Set listenerSet = listeners.get(clazz);
    if (listenerSet == null) {
      listenerSet = new HashSet<>();
      listeners.put(clazz, listenerSet);
    }
    listenerSet.add(listener);
  }

  /**
   * remove the given DynaEnumEventListener
   *
   * @param clazz
   *          the class to de-register the listener for
   * @param listener
   *          the listener to be removed
   */
  protected static void removeListener(Class> clazz, DynaEnumEventListener listener) {
    Set listenerSet = listeners.get(clazz);
    if (listenerSet != null) {
      listenerSet.remove(listener);
    }
  }

  protected static void valueAdded(Class clazz, DynaEnum value) {
    Set listenerSet = listeners.get(clazz);
    if (listenerSet != null) {
      try {
        for (DynaEnumEventListener listener : listenerSet) {
          listener.valueAdded(value);
        }
      }
      catch (Exception ignored) {
      }
    }
  }

  /**
   * DynaEnumEventListener is the interface for getting informed if any new items are added
   * 
   * @param 
   *          the type of the enum
   */
  public interface DynaEnumEventListener {
    void valueAdded(E value);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy