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

org.eclipse.xtext.util.AbstractLinkedStack Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *******************************************************************************/
package org.eclipse.xtext.util;

import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import com.google.common.collect.Lists;

public abstract class AbstractLinkedStack, ELEMENT> implements
		Iterable {

	protected static class Element {
		protected Element parent;
		protected T value;

		public Element(Element parent, T value) {
			super();
			this.parent = parent;
			this.value = value;
		}
	}

	private final class ElementIterator implements Iterator {
		private Element ele;

		public ElementIterator(Element ele) {
			super();
			this.ele = ele;
		}

		@Override
		public boolean hasNext() {
			return ele != null;
		}

		@Override
		public ELEMENT next() {
			if (!hasNext())
				throw new NoSuchElementException();
			Element prev = ele;
			ele = ele.parent;
			return prev.value;
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

	protected Element top = null;

	@Override
	public THIS clone() {
		THIS result = createStack();
		init(result);
		return result;
	}

	public THIS cloneAndPop() {
		THIS stack = clone();
		stack.pop();
		return stack;
	}

	public THIS cloneAndPush(ELEMENT element) {
		THIS stack = clone();
		stack.push(element);
		return stack;
	}

	public boolean contains(ELEMENT value) {
		Element t = top;
		while (t != null) {
			if (t.value == value)
				return true;
			t = t.parent;
		}
		return false;
	}

	protected Element createElement(Element parent, ELEMENT value) {
		return new Element(parent, value);
	}

	protected abstract THIS createStack();

	public String elementToStr(ELEMENT value) {
		return value == null ? "null" : value.toString();
	}

	@Override
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public boolean equals(Object obj) {
		if (!(obj instanceof AbstractLinkedStack))
			return false;
		Element t1 = top;
		Element t2 = ((AbstractLinkedStack) obj).top;
		while (true) {
			if (t1 == null && t2 == null)
				return true;
			if (t1 == null || t2 == null || t1.value != t2.value)
				return false;
			t1 = t1.parent;
			t2 = t2.parent;
		}
	}

	@Override
	public int hashCode() {
		// same algorithm as in java.util.AbstractList.hashCode()
		int hashCode = 1;
		Element t = top;
		while (t != null) {
			hashCode = 31 * hashCode + (t.value == null ? 0 : t.value.hashCode());
			t = t.parent;
		}
		return hashCode;
	}

	protected void init(THIS result) {
		result.top = top;
	}

	public boolean isEmpty() {
		return top == null;
	}

	/**
	 * @since 2.0
	 */
	@Override
	public Iterator iterator() {
		return new ElementIterator(top);
	}

	public ELEMENT peek() {
		return top != null ? top.value : null;
	}

	public ELEMENT pop() {
		if (top != null) {
			ELEMENT result = top.value;
			top = top.parent;
			return result;
		}
		return null;
	}

	public void push(ELEMENT value) {
		top = createElement(top, value);
	}

	@Override
	public String toString() {
		List values = Lists.newArrayList();
		Element t = top;
		while (t != null) {
			values.add(elementToStr(t.value));
			t = t.parent;
		}
		return values.toString();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy