/** * * Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved. * * 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.speedment.common.codegen.internal; import com.speedment.common.codegen.RenderStack; import java.util.ArrayDeque; import java.util.Deque; import java.util.Iterator; import java.util.stream.Stream; import java.util.stream.StreamSupport; import static java.util.Objects.requireNonNull; /** * The default {@link RenderStack} implementation. * * @author Emil Forslund */ public class DefaultRenderStack implements RenderStack { private final Deque<Object> stack; /** * Constructs the stack. */ public DefaultRenderStack() { stack = new ArrayDeque<>(); } /** * Constructs the stack using an existing stack as a prototype. This creates * a shallow copy of that stack. * * @param prototype the prototype */ public DefaultRenderStack(DefaultRenderStack prototype) { stack = new ArrayDeque<>(requireNonNull(prototype).stack); } /** * Put the specified object on the stack. * * @param obj the object to push */ public void push(Object obj) { stack.push(requireNonNull(obj)); } /** * Returns the latest element from the stack, removes it. * * @return the latest added element */ public Object pop() { return stack.pop(); } @Override public <T> Stream<T> fromBottom(Class<T> type) { return all(requireNonNull(type), stack.descendingIterator()); } @Override public <T> Stream<T> fromTop(Class<T> type) { return all(requireNonNull(type), stack.iterator()); } @Override public boolean isEmpty() { return stack.isEmpty(); } /** * Creates a <code>Stream</code> over all the elements of the stack using an * <code>Iterator</code>. Only elements of the specified type is included. * * @param <T> the type to look for * @param type the type to look for * @param i the iterator * @return a stream of all the models in the stack of that type */ @SuppressWarnings("unchecked") private static <T> Stream<T> all(Class<T> type, Iterator<Object> i) { requireNonNull(type); requireNonNull(i); return all(i).filter(o -> type.isAssignableFrom(o.getClass())) .map(o -> (T) o); } /** * Creates a <code>Stream</code> over all the elements of the stack using an * <code>Iterator</code>. * * @param i the iterator * @return a stream of all the models in the stack */ private static Stream<?> all(Iterator<Object> i) { requireNonNull(i); final Iterable<Object> it = () -> i; return StreamSupport.stream(it.spliterator(), false); } }