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

com.aggrepoint.utils.linkedtable.LinkedTable Maven / Gradle / Ivy

The newest version!
package com.aggrepoint.utils.linkedtable;

import java.util.Hashtable;
import java.util.Vector;

import com.aggrepoint.utils.TypeCast;

/**
 * @param 
 *            Type of column key
 * @param 
 *            Type of row key
 * @param 
 *            Table content type
 */
public class LinkedTable extends PropObject {
	ColumnHead m_colHead;
	ColumnHead m_colTail;
	RowHead m_rowHead;
	RowHead m_rowTail;

	public TValue[][] toArray(TValue[][] arr) {
		if (m_rowHead == null || m_colHead == null)
			return null;

		int rc = getRowCount();
		int cc = getColumnCount();

		boolean bCreate = true;
		if (arr.length != rc)
			bCreate = true;
		else
			for (int i = 0; i < arr.length; i++)
				if (arr[i].length != cc) {
					bCreate = true;
					break;
				}

		if (bCreate)
			arr = TypeCast.cast(java.lang.reflect.Array.newInstance(arr
					.getClass().getComponentType().getComponentType(), rc, cc));

		RowHead row = m_rowHead;
		for (int r = 0; r < rc; r++) {
			Node node = row.m_firstNode;
			int c = 0;
			while (node != null) {
				arr[r][c++] = node.m_value;
				node = node.m_nextInRow;
			}
			row = row.m_nextHead;
		}

		return arr;
	}

	RowHead getRow(TRow row, boolean createIfNotExists) {
		if (m_rowHead == null) {
			if (!createIfNotExists)
				return null;

			// This is the first row
			// Create the row
			m_rowHead = m_rowTail = new RowHead(row);

			// { create nodes in the row
			ColumnHead col = m_colHead;
			Node nodePrev = null;
			while (col != null) {
				Node node = new Node(
						col, m_rowHead, null);
				col.m_firstNode = col.m_lastNode = node;
				if (nodePrev == null)
					m_rowHead.m_firstNode = node;
				else
					nodePrev.m_nextInRow = node;
				nodePrev = node;
				col = col.m_nextHead;
			}
			m_rowHead.m_lastNode = nodePrev;
			// }

			return m_rowHead;
		}

		RowHead r = m_rowHead.find(row);
		if (r != null)
			return r;

		if (!createIfNotExists)
			return null;

		// append a row
		r = new RowHead(row);
		m_rowTail.m_nextHead = r;
		m_rowTail = r;

		// { create nodes in the row
		ColumnHead col = m_colHead;
		Node nodePrev = null;
		while (col != null) {
			Node node = new Node(
					col, r, null);
			col.m_lastNode.m_nextInColumn = node;
			col.m_lastNode = node;
			if (nodePrev == null)
				r.m_firstNode = node;
			else
				nodePrev.m_nextInRow = node;
			nodePrev = node;
			col = col.m_nextHead;
		}
		r.m_lastNode = nodePrev;
		// }

		return r;
	}

	ColumnHead getColumn(TColumn column,
			boolean createIfNotExists) {
		if (m_colHead == null) {
			if (!createIfNotExists)
				return null;

			// This is the first column
			// Create the column
			m_colHead = m_colTail = new ColumnHead(
					column);

			// { create nodes in the column
			RowHead row = m_rowHead;
			Node nodePrev = null;
			while (row != null) {
				Node node = new Node(
						m_colHead, row, null);
				row.m_firstNode = row.m_lastNode = node;
				if (nodePrev == null)
					m_colHead.m_firstNode = node;
				else
					nodePrev.m_nextInColumn = node;
				nodePrev = node;
				row = row.m_nextHead;
			}
			m_colHead.m_lastNode = nodePrev;
			// }

			return m_colHead;
		}

		ColumnHead col = m_colHead.find(column);
		if (col != null)
			return col;

		if (!createIfNotExists)
			return null;

		// append a column
		col = new ColumnHead(column);
		m_colTail.m_nextHead = col;
		m_colTail = col;

		// { create nodes in the column
		RowHead row = m_rowHead;
		Node nodePrev = null;
		while (row != null) {
			Node node = new Node(
					col, row, null);
			row.m_lastNode.m_nextInRow = node;
			row.m_lastNode = node;
			if (nodePrev == null)
				col.m_firstNode = node;
			else
				nodePrev.m_nextInColumn = node;
			nodePrev = node;
			row = row.m_nextHead;
		}
		col.m_lastNode = nodePrev;
		// }

		return col;
	}

	public ColumnHead addColumn(TColumn col) {
		return getColumn(col, true);
	}

	public RowHead addRow(TRow row) {
		return getRow(row, true);
	}

	public void insertColumn(TColumn col, int posi) {
		ColumnHead newCol = new ColumnHead(
				col);

		if (posi == 0) {
			newCol.m_nextHead = m_colHead;
			m_colHead = newCol;
			if (m_colTail == null)
				m_colTail = newCol;

			// create nodes in the column
			RowHead row = m_rowHead;
			Node nodePrev = null;
			while (row != null) {
				Node node = new Node(
						newCol, row, null);
				node.m_nextInRow = row.m_firstNode;
				row.m_firstNode = node;
				if (row.m_lastNode == null)
					row.m_lastNode = node;
				if (nodePrev == null)
					newCol.m_firstNode = node;
				else
					nodePrev.m_nextInColumn = node;
				nodePrev = node;
				row = row.m_nextHead;
			}
			newCol.m_lastNode = nodePrev;

			return;
		}

		ColumnHead prev = m_colHead;
		for (int i = 0; i < posi - 1 && prev != null; i++)
			prev = prev.m_nextHead;
		if (prev == null)
			return;

		newCol.m_nextHead = prev.m_nextHead;
		prev.m_nextHead = newCol;
		if (newCol.m_nextHead == null)
			m_colTail = newCol;

		// create nodes in the column
		RowHead row = m_rowHead;
		Node nodePrev = null;
		while (row != null) {
			Node pn = row.m_firstNode;
			for (int i = 0; i < posi - 1 && pn != null; i++)
				pn = pn.m_nextInRow;

			Node node = new Node(
					newCol, row, null);
			node.m_nextInRow = pn.m_nextInRow;
			pn.m_nextInRow = node;
			if (node.m_nextInRow == null)
				row.m_lastNode = node;
			if (nodePrev == null)
				newCol.m_firstNode = node;
			else
				nodePrev.m_nextInColumn = node;
			nodePrev = node;
			row = row.m_nextHead;
		}
		newCol.m_lastNode = nodePrev;
	}

	public void set(TColumn column, TRow row, TValue value) {
		ColumnHead col = getColumn(column, true);
		RowHead r = getRow(row, true);

		Node node = col.m_firstNode;
		while (node != null) {
			if (node.m_row == r) {
				node.m_value = value;
				return;
			}
			node = node.m_nextInColumn;
		}
	}

	Object add(TValue a, TValue b) {
		if (a instanceof Double)
			return ((Double) a).doubleValue() + ((Double) b).doubleValue();
		else if (a instanceof Float)
			return ((Float) a).doubleValue() + ((Float) b).doubleValue();
		else if (a instanceof Long)
			return ((Long) a).doubleValue() + ((Long) b).doubleValue();
		else if (a instanceof Integer)
			return ((Integer) a).doubleValue() + ((Integer) b).doubleValue();
		else if (a instanceof Short)
			return ((Short) a).doubleValue() + ((Short) b).doubleValue();
		return b;
	}

	@SuppressWarnings("unchecked")
	public void add(TColumn column, TRow row, TValue value) {
		ColumnHead col = getColumn(column, true);
		RowHead r = getRow(row, true);

		Node node = col.m_firstNode;
		while (node != null) {
			if (node.m_row == r) {
				node.m_value = (TValue) add(node.m_value, value);
				return;
			}
			node = node.m_nextInColumn;
		}
	}

	public TValue get(TColumn column, TRow row) {
		if (m_colHead == null || m_rowHead == null)
			return null;

		ColumnHead col = m_colHead.find(column);
		RowHead r = m_rowHead.find(row);
		if (col == null || r == null)
			return null;

		Node node = col.m_firstNode;
		while (node != null) {
			if (node.m_row == r) {
				return node.m_value;
			}
			node = node.m_nextInColumn;
		}

		return null;
	}

	public TColumn getFirstColumn() {
		if (m_colHead == null)
			return null;
		return m_colHead.m_value;
	}

	public TRow getFirstRow() {
		if (m_rowHead == null)
			return null;
		return m_rowHead.m_value;
	}

	public Vector getColumns() {
		if (m_colHead == null)
			return null;

		ColumnHead col = m_colHead;
		while (col != null) {
			col = col.m_nextHead;
		}

		Vector cols = new Vector();

		col = m_colHead;
		while (col != null) {
			cols.add(col.m_value);
			col = col.m_nextHead;
		}

		return cols;
	}

	public Vector> getColumnProps() {
		if (m_colHead == null)
			return null;

		ColumnHead col = m_colHead;
		while (col != null) {
			col = col.m_nextHead;
		}

		Vector> cols = new Vector>();

		col = m_colHead;
		while (col != null) {
			cols.add(col.getProps());
			col = col.m_nextHead;
		}

		return cols;
	}

	public Vector getRows() {
		if (m_rowHead == null)
			return null;

		RowHead row = m_rowHead;
		while (row != null) {
			row = row.m_nextHead;
		}

		Vector rows = new Vector();

		row = m_rowHead;
		while (row != null) {
			rows.add(row.m_value);
			row = row.m_nextHead;
		}

		return rows;
	}

	public Vector> getRowProps() {
		if (m_rowHead == null)
			return null;

		RowHead row = m_rowHead;
		while (row != null) {
			row = row.m_nextHead;
		}

		Vector> rows = new Vector>();

		row = m_rowHead;
		while (row != null) {
			rows.add(row.getProps());
			row = row.m_nextHead;
		}

		return rows;
	}

	public int getColumnCount() {
		if (m_colHead == null)
			return 0;
		int c = 0;
		ColumnHead col = m_colHead;
		while (col != null) {
			c++;
			col = col.m_nextHead;
		}
		return c;
	}

	public int getRowCount() {
		if (m_rowHead == null)
			return 0;
		int c = 0;
		RowHead row = m_rowHead;
		while (row != null) {
			c++;
			row = row.m_nextHead;
		}
		return c;
	}

	int findRowPosi(TRow row) {
		if (row == null)
			return -1;

		RowHead r = m_rowHead;
		int posi = 0;
		while (r != null) {
			if (r.m_value.equals(row))
				return posi;
			posi++;
			r = r.m_nextHead;
		}
		return -1;
	}

	RowHead getRowHead(int posi) {
		if (posi < 0)
			return null;

		RowHead r = m_rowHead;
		while (r != null) {
			if (posi == 0)
				return r;
			posi--;
			r = r.m_nextHead;
		}
		return null;
	}

	public TRow getRow(int posi) {
		RowHead head = getRowHead(posi);
		if (head == null)
			return null;
		return head.m_value;
	}

	int findColumnPosi(TColumn column) {
		if (column == null)
			return -1;

		ColumnHead col = m_colHead;
		int posi = 0;
		while (col != null) {
			if (col.m_value.equals(column))
				return posi;
			posi++;
			col = col.m_nextHead;
		}
		return -1;
	}

	ColumnHead getColumnHead(int posi) {
		if (posi < 0)
			return null;

		ColumnHead col = m_colHead;
		while (col != null) {
			if (posi == 0)
				return col;
			posi--;
			col = col.m_nextHead;
		}
		return null;
	}

	public TColumn getColumn(int posi) {
		ColumnHead head = getColumnHead(posi);
		if (head == null)
			return null;
		return head.m_value;
	}

	public void deleteColumn(TColumn column) {
		int posi = findColumnPosi(column);
		if (posi == -1)
			return;
		if (posi == 0) {
			if (m_colTail == m_colHead)
				m_colHead = m_colTail = null;
			else
				m_colHead = m_colHead.m_nextHead;

			RowHead row = m_rowHead;
			while (row != null) {
				if (m_colHead == null)
					row.m_firstNode = row.m_lastNode = null;
				else
					row.m_firstNode = row.m_firstNode.m_nextInRow;

				row = row.m_nextHead;
			}
		} else {
			ColumnHead col = m_colHead;
			posi--;
			for (int i = 0; i < posi; i++)
				col = col.m_nextHead;
			if (m_colTail == col.m_nextHead)
				m_colTail = col;
			col.m_nextHead = col.m_nextHead.m_nextHead;

			RowHead row = m_rowHead;
			while (row != null) {
				Node node = row.m_firstNode;
				for (int i = 0; i < posi; i++)
					node = node.m_nextInRow;
				if (row.m_lastNode == node.m_nextInRow)
					row.m_lastNode = node;
				node.m_nextInRow = node.m_nextInRow.m_nextInRow;

				row = row.m_nextHead;
			}
		}
	}

	public void deleteRow(TRow row) {
		int posi = findRowPosi(row);
		if (posi == -1)
			return;
		if (posi == 0) {
			if (m_rowTail == m_rowHead)
				m_rowHead = m_rowTail = null;
			else
				m_rowHead = m_rowHead.m_nextHead;

			ColumnHead col = m_colHead;
			while (col != null) {
				if (m_rowHead == null)
					col.m_firstNode = col.m_lastNode = null;
				else
					col.m_firstNode = col.m_firstNode.m_nextInColumn;

				col = col.m_nextHead;
			}
		} else {
			RowHead r = m_rowHead;
			posi--;
			for (int i = 0; i < posi; i++)
				r = r.m_nextHead;
			if (m_rowTail == r.m_nextHead)
				m_rowTail = r;
			r.m_nextHead = r.m_nextHead.m_nextHead;

			ColumnHead col = m_colHead;
			while (col != null) {
				Node node = col.m_firstNode;
				for (int i = 0; i < posi; i++)
					node = node.m_nextInColumn;
				if (col.m_lastNode == node.m_nextInColumn)
					col.m_lastNode = node;
				node.m_nextInColumn = node.m_nextInColumn.m_nextInColumn;

				col = col.m_nextHead;
			}
		}
	}

	TValue[] getValuesInColumn(ColumnHead col,
			TValue[] vals) {
		if (col == null)
			return null;

		int count = getRowCount();
		if (vals.length != count)
			vals = TypeCast.cast(java.lang.reflect.Array.newInstance(vals
					.getClass().getComponentType(), count));

		Node node = col.m_firstNode;
		int c = 0;
		while (node != null) {
			vals[c++] = node.m_value;
			node = node.m_nextInColumn;
		}

		return vals;
	}

	public TValue[] getValuesInColumn(TColumn column, TValue[] vals) {
		return getValuesInColumn(getColumn(column, false), vals);
	}

	public TValue[] getValuesInColumn(int posi, TValue[] vals) {
		return getValuesInColumn(getColumnHead(posi), vals);
	}

	TValue[] getValuesInRow(RowHead r, TValue[] vals) {
		if (r == null)
			return null;

		int count = getColumnCount();
		if (vals.length != count)
			vals = TypeCast.cast(java.lang.reflect.Array.newInstance(vals
					.getClass().getComponentType(), count));

		Node node = r.m_firstNode;
		int c = 0;
		while (node != null) {
			vals[c++] = node.m_value;
			node = node.m_nextInRow;
		}

		return vals;
	}

	public TValue[] getValuesInRow(TRow row, TValue[] vals) {
		return getValuesInRow(getRow(row, false), vals);
	}

	public TValue[] getValuesInRow(int posi, TValue[] vals) {
		return getValuesInRow(getRowHead(posi), vals);
	}

	@SuppressWarnings("unchecked")
	public void sortColumns(TColumn[] order) {
		if (order == null || m_colHead == null)
			return;

		// { calculate the order by position id
		int[] orders = new int[getColumnCount()];
		TColumn[] cols = TypeCast.cast(new Object[orders.length]);

		int i = 0;
		ColumnHead col = m_colHead;
		while (col != null) {
			cols[i++] = col.m_value;
			col = col.m_nextHead;
		}

		i = 0;
		for (TColumn c : order) {
			for (int j = 0; j < cols.length; j++) {
				if (cols[j] == null)
					continue;
				if (cols[j].equals(c)) {
					orders[i++] = j;
					cols[j] = null;
					continue;
				}
			}
		}
		for (int j = 0; j < cols.length; j++)
			if (cols[j] != null)
				orders[i++] = j;
		// }

		// {sort header
		Object[] heads = new Object[orders.length];
		Object[] newHeads = new Object[orders.length];

		i = 0;
		col = m_colHead;
		while (col != null) {
			heads[i++] = col;
			col = col.m_nextHead;
		}

		for (int j = 0; j < orders.length; j++)
			newHeads[j] = heads[orders[j]];

		m_colHead = (ColumnHead) newHeads[0];
		m_colTail = (ColumnHead) newHeads[orders.length - 1];
		m_colTail.m_nextHead = null;

		for (int j = 0; j < orders.length - 1; j++)
			((ColumnHead) newHeads[j]).m_nextHead = TypeCast
					.cast(newHeads[j + 1]);
		// }

		// { sort data
		Object[] nodes = new Object[orders.length];
		Object[] newNodes = new Object[orders.length];

		RowHead row = m_rowHead;
		while (row != null) {
			Node node = row.m_firstNode;
			i = 0;
			while (node != null) {
				nodes[i++] = node;
				node = node.m_nextInRow;
			}

			for (int j = 0; j < orders.length; j++)
				newNodes[j] = nodes[orders[j]];

			row.m_firstNode = (Node) newNodes[0];
			row.m_lastNode = (Node) newNodes[orders.length - 1];
			row.m_lastNode.m_nextInRow = null;

			for (int j = 0; j < orders.length - 1; j++)
				((Node) newNodes[j]).m_nextInRow = (Node) newNodes[j + 1];

			row = row.m_nextHead;
		}
		// }
	}

	@SuppressWarnings("unchecked")
	public void sortRows(TRow[] order) {
		if (order == null || m_rowHead == null)
			return;

		// { calculate the order by position id
		int[] orders = new int[getRowCount()];
		TRow[] rows = TypeCast.cast(new Object[orders.length]);

		int i = 0;
		RowHead row = m_rowHead;
		while (row != null) {
			rows[i++] = row.m_value;
			row = row.m_nextHead;
		}

		i = 0;
		for (TRow r : order) {
			for (int j = 0; j < rows.length; j++) {
				if (rows[j] == null)
					continue;
				if (rows[j].equals(r)) {
					orders[i++] = j;
					rows[j] = null;
					continue;
				}
			}
		}
		for (int j = 0; j < rows.length; j++)
			if (rows[j] != null)
				orders[i++] = j;
		// }

		// {sort header
		Object[] heads = new Object[orders.length];
		Object[] newHeads = new Object[orders.length];

		i = 0;
		row = m_rowHead;
		while (row != null) {
			heads[i++] = row;
			row = row.m_nextHead;
		}

		for (int j = 0; j < orders.length; j++)
			newHeads[j] = heads[orders[j]];

		m_rowHead = (RowHead) newHeads[0];
		m_rowTail = (RowHead) newHeads[orders.length - 1];
		m_rowTail.m_nextHead = null;

		for (int j = 0; j < orders.length - 1; j++)
			((RowHead) newHeads[j]).m_nextHead = TypeCast
					.cast(newHeads[j + 1]);
		// }

		// { sort data
		Object[] nodes = new Object[orders.length];
		Object[] newNodes = new Object[orders.length];

		ColumnHead col = m_colHead;
		while (col != null) {
			Node node = col.m_firstNode;
			i = 0;
			while (node != null) {
				nodes[i++] = node;
				node = node.m_nextInColumn;
			}

			for (int j = 0; j < orders.length; j++)
				newNodes[j] = nodes[orders[j]];

			col.m_firstNode = (Node) newNodes[0];
			col.m_lastNode = (Node) newNodes[orders.length - 1];
			col.m_lastNode.m_nextInColumn = null;

			for (int j = 0; j < orders.length - 1; j++)
				((Node) newNodes[j]).m_nextInColumn = (Node) newNodes[j + 1];

			col = col.m_nextHead;
		}
		// }
	}

	public void mergeColumn(TColumn from, TColumn to, INodeMerger merger) {
		if (m_colHead == null)
			return;

		ColumnHead colFrom = m_colHead.find(from);
		ColumnHead colTo = m_colHead.find(to);

		if (colFrom == null)
			return;

		if (colTo == null) {
			colFrom.m_value = to;
			return;
		}

		Node ndFrom = colFrom.m_firstNode;
		Node ndTo = colTo.m_firstNode;
		while (ndFrom != null && ndTo != null) {
			ndTo.m_value = merger.merge(ndFrom.m_value, ndTo.m_value);
			ndFrom = ndFrom.m_nextInColumn;
			ndTo = ndTo.m_nextInColumn;
		}

		deleteColumn(from);
	}

	public void mergeColumn(TColumn[] froms, TColumn to, INodeMerger merger) {
		if (m_colHead == null)
			return;
		for (int i = 0; i < froms.length; i++)
			mergeColumn(froms[i], to, merger);
	}

	public void mergeRow(TRow from, TRow to, INodeMerger merger) {
		if (m_rowHead == null)
			return;

		RowHead rowFrom = m_rowHead.find(from);
		RowHead rowTo = m_rowHead.find(to);

		if (rowFrom == rowTo)
			return;

		if (rowFrom == null)
			return;

		if (rowTo == null) {
			rowFrom.m_value = to;
			return;
		}

		Node ndFrom = rowFrom.m_firstNode;
		Node ndTo = rowTo.m_firstNode;
		while (ndFrom != null && ndTo != null) {
			ndTo.m_value = merger.merge(ndFrom.m_value, ndTo.m_value);
			ndFrom = ndFrom.m_nextInRow;
			ndTo = ndTo.m_nextInRow;
		}

		deleteRow(from);
	}

	public void mergeRow(TRow[] froms, TRow to, INodeMerger merger) {
		if (m_rowHead == null)
			return;
		for (int i = 0; i < froms.length; i++)
			mergeRow(froms[i], to, merger);
	}

	public void updateColumns(Hashtable map) {
		if (m_colHead == null)
			return;

		ColumnHead col = m_colHead;
		while (col != null) {
			TColumn c = map.get(col.m_value);
			if (c != null)
				col.m_value = c;
			col = col.m_nextHead;
		}
	}

	public void updateRows(Hashtable map) {
		if (m_rowHead == null)
			return;

		RowHead row = m_rowHead;
		while (row != null) {
			TRow r = map.get(row.m_value);
			if (r != null)
				row.m_value = r;
			row = row.m_nextHead;
		}
	}

	public boolean setColumnProp(TColumn col, String name, Object value) {
		ColumnHead head = getColumn(col, false);
		if (head == null)
			return false;
		head.setProp(name, value);
		return true;
	}

	public boolean setColumnProp(int col, String name, Object value) {
		ColumnHead head = getColumnHead(col);
		if (head == null)
			return false;
		head.setProp(name, value);
		return true;
	}

	public void copyColumnToProp(String name) {
		ColumnHead col = m_colHead;
		while (col != null) {
			col.setProp(name, col.m_value);
			col = col.m_nextHead;
		}
	}

	public Object getColumnProp(TColumn col, String name) {
		ColumnHead c = getColumn(col, false);
		if (c == null)
			return null;
		if (name == null)
			return c.getProps();
		else
			return c.getProp(name);
	}

	public Object getColumnProp(int posi, String name) {
		ColumnHead c = getColumnHead(posi);
		if (c == null)
			return null;
		if (name == null)
			return c.getProps();
		else
			return c.getProp(name);
	}

	public boolean setRowProp(TRow row, String name, Object value) {
		RowHead head = getRow(row, false);
		if (head == null)
			return false;
		head.setProp(name, value);
		return true;
	}

	public boolean setRowProp(int row, String name, Object value) {
		RowHead head = getRowHead(row);
		if (head == null)
			return false;
		head.setProp(name, value);
		return true;
	}

	public void copyRowToProp(String name) {
		RowHead r = m_rowHead;
		while (r != null) {
			r.setProp(name, r.m_value);
			r = r.m_nextHead;
		}
	}

	public Object getRowProp(TRow row, String name) {
		RowHead head = getRow(row, false);
		if (head == null)
			return false;
		if (name == null)
			return head.getProps();
		else
			return head.getProp(name);
	}

	public Object getRowProp(int posi, String name) {
		RowHead head = getRowHead(posi);
		if (head == null)
			return false;
		if (name == null)
			return head.getProps();
		else
			return head.getProp(name);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy