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

com.igormaznitsa.mistack.impl.AbstractMiStackDeque Maven / Gradle / Ivy

/*
 * Copyright 2022 Igor Maznitsa
 *
 * 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 com.igormaznitsa.mistack.impl;

import static java.util.Objects.requireNonNull;

import com.igormaznitsa.mistack.MiStack;
import com.igormaznitsa.mistack.MiStackItem;
import java.util.Deque;
import java.util.Iterator;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;

/**
 * Class allows to build MiStacks based on java.util.Deque collections.
 *
 * @param  type of values placed on stack
 * @since 1.0.0
 */
public abstract class AbstractMiStackDeque implements MiStack {

  protected final Deque> deque;
  private final String name;
  private final AtomicBoolean closed = new AtomicBoolean();

  /**
   * Constructor requires name and base deque.
   *
   * @param name  name for the stack instance, must not be null
   * @param deque base deque, must not be null
   * @throws NullPointerException if any parameter is null
   * @since 1.0.0
   */
  public AbstractMiStackDeque(final String name, final Deque> deque) {
    this.name = requireNonNull(name);
    this.deque = requireNonNull(deque);
  }

  /**
   * Get the base deque for the stack.
   *
   * @return the base deque, can't be null
   * @since 1.0.0
   */
  protected Deque> getDeque() {
    return this.deque;
  }

  @Override
  public MiStack push(final MiStackItem item) {
    this.assertNotClosed();
    this.deque.addFirst(requireNonNull(item));
    return this;
  }

  @Override
  public Optional> pop(final Predicate> predicate) {
    this.assertNotClosed();

    MiStackItem result = null;
    var iterator = this.deque.iterator();
    while (iterator.hasNext() && result == null) {
      var item = iterator.next();
      if (predicate.test(item)) {
        iterator.remove();
        result = item;
      }
    }

    return Optional.ofNullable(result);
  }

  @Override
  public Iterator> iterator(final Predicate> filter,
                                           final Predicate> takeWhile) {
    return new FilterableIterator<>(this.deque.iterator(), filter, takeWhile, this.closed::get,
        x -> {
        });
  }

  @Override
  public boolean isClosed() {
    return this.closed.get();
  }

  @Override
  public String getName() {
    return this.name;
  }

  @Override
  public void clear() {
    this.assertNotClosed();
    this.deque.clear();
  }

  @Override
  public boolean isEmpty() {
    this.assertNotClosed();
    return this.deque.isEmpty();
  }

  @Override
  public long size() {
    this.assertNotClosed();
    int result = this.deque.size();
    if (result < Integer.MAX_VALUE) {
      return result;
    } else {
      return this.deque.stream().count();
    }
  }

  @Override
  public void close() {
    if (this.closed.compareAndSet(false, true)) {
      this.deque.clear();
    } else {
      this.assertNotClosed();
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy