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

com.simplaex.bedrock.Mapping Maven / Gradle / Ivy

package com.simplaex.bedrock;

import lombok.val;

import javax.annotation.Nonnull;
import java.lang.ref.SoftReference;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public interface Mapping extends Function, Iterable> {

  @Nonnull
  Optional get(From key);

  default To getOrElse(final From key, final To fallback) {
    return get(key).orElse(fallback);
  }

  @Override
  default To apply(final From key) {
    val result = get(key);
    if (result.isPresent()) {
      return result.get();
    } else {
      throw new NoSuchElementException(Objects.toString(key));
    }
  }

  Seq keys();

  default int size() {
    return keys().length();
  }

  default boolean isEmpty() {
    return keys().isEmpty();
  }

  default Seq values() {
    val builder = Seq.builder();
    for (val key : keys()) {
      builder.add(apply(key));
    }
    return builder.result();
  }

  @Override
  @Nonnull
  default Iterator> iterator() {
    return new Iterator>() {
      private final Iterator underlying = keys().iterator();

      @Override
      public boolean hasNext() {
        return underlying.hasNext();
      }

      @Override
      public Pair next() {
        val nextKey = underlying.next();
        return Pair.of(nextKey, apply(nextKey));
      }
    };
  }

  default Stream> stream() {
    return StreamSupport.stream(spliterator(), false);
  }

  default Map toMap() {
    return new AbstractMap() {

      private SoftReference>> entrySet = new SoftReference<>(null);

      @Override
      @Nonnull
      public Set> entrySet() {
        val entrySet = this.entrySet.get();
        if (entrySet == null) {
          val set = new HashSet>();
          for (val key : keys()) {
            set.add(Pair.of(key, apply(key)));
          }
          this.entrySet = new SoftReference<>(set);
          return set;
        }
        return entrySet;
      }
    };
  }

  static  Mapping wrap(final Map map) {
    return new Mapping() {

      @Override
      @Nonnull
      public Map toMap() {
        return map;
      }

      @Override
      @Nonnull
      public Iterator> iterator() {
        return new Iterator>() {

          private final Iterator> underlying = map.entrySet().iterator();

          @Override
          public boolean hasNext() {
            return underlying.hasNext();
          }

          @Override
          public Pair next() {
            return Pair.of(underlying.next());
          }
        };
      }

      private SoftReference> keys = new SoftReference<>(null);
      private SoftReference> values = new SoftReference<>(null);

      @Nonnull
      @Override
      public Optional get(final From key) {
        if (map.containsKey(key)) {
          return Optional.ofNullable(map.get(key));
        }
        return Optional.empty();
      }

      @Override
      public Seq keys() {
        val keys = this.keys.get();
        if (keys == null) {
          val newKeys = Seq.ofCollection(map.keySet());
          this.keys = new SoftReference<>(newKeys);
          return newKeys;
        }
        return keys;
      }

      @Override
      public Seq values() {
        val values = this.values.get();
        if (values == null) {
          val newValues = Seq.ofCollection(map.values());
          this.values = new SoftReference<>(newValues);
          return newValues;
        }
        return values;
      }
    };
  }

  @SuppressWarnings("unchecked")
  static  Mapping empty() {
    return (Mapping) EmptyMapping.EMPTY;
  }

  class EmptyMapping implements Mapping {

    private static EmptyMapping EMPTY = new EmptyMapping();

    @Nonnull
    @Override
    public Optional get(final K key) {
      return Optional.empty();
    }

    @Override
    public Seq keys() {
      return Seq.empty();
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy