--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.utils.datastructures.persistent;\r
+\r
+public abstract class ImmutableStack<T> {\r
+ \r
+ private ImmutableStack() { \r
+ }\r
+ \r
+ private static class SingleStackNode<T> extends ImmutableStack<T> {\r
+ ImmutableStack<T> parent;\r
+ T value;\r
+ \r
+ public SingleStackNode(ImmutableStack<T> parent, T value) { \r
+ this.parent = parent;\r
+ this.value = value;\r
+ }\r
+\r
+ @Override\r
+ public T get(int i) {\r
+ return i==0 ? value : parent.get(i-1);\r
+ } \r
+ }\r
+ \r
+ private static class MultiStackNode<T> extends ImmutableStack<T> {\r
+ ImmutableStack<T> parent;\r
+ T[] values;\r
+ \r
+ public MultiStackNode(ImmutableStack<T> parent, T[] values) { \r
+ this.parent = parent;\r
+ this.values = values;\r
+ }\r
+\r
+ @Override\r
+ public T get(int i) {\r
+ return i<values.length ? values[i] : parent.get(i-values.length);\r
+ } \r
+ }\r
+ \r
+ private static class EmptyStack<T> extends ImmutableStack<T> {\r
+\r
+ @Override\r
+ public T get(int i) {\r
+ throw new IllegalArgumentException("No such element in stack.");\r
+ }\r
+ \r
+ }\r
+ \r
+ @SuppressWarnings({ "rawtypes" })\r
+ static final EmptyStack EMPTY = new EmptyStack();\r
+ \r
+ public ImmutableStack<T> push(T value) {\r
+ return new SingleStackNode<T>(this, value);\r
+ }\r
+ \r
+ public ImmutableStack<T> push(T[] values) {\r
+ if(values.length > 1)\r
+ return new MultiStackNode<T>(this, values);\r
+ else if(values.length == 1)\r
+ return new SingleStackNode<T>(this, values[0]);\r
+ else\r
+ return this;\r
+ }\r
+ \r
+ public abstract T get(int i); \r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public static <T> ImmutableStack<T> empty() {\r
+ return (ImmutableStack<T>)EMPTY;\r
+ }\r
+ \r
+ public static <T> ImmutableStack<T> of(T value) {\r
+ return new SingleStackNode<T>(null, value);\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public static <T> ImmutableStack<T> of(T[] values) {\r
+ if(values.length > 1)\r
+ return new MultiStackNode<T>((ImmutableStack<T>)empty(), values);\r
+ else if(values.length == 1)\r
+ return new SingleStackNode<T>((ImmutableStack<T>)empty(), values[0]);\r
+ else\r
+ return empty();\r
+ }\r
+}\r