/** * Copyright (c) 2011-2014 Exxeleron GmbH * * 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.exxeleron.qjava; import java.util.Iterator; import java.util.NoSuchElementException; /** * Represents a q keyed table type. */ public class QKeyedTable implements Iterable<QKeyedTable.KeyValuePair>, Table { private final QTable keys; private final QTable values; private final int length; /** * Creates new {@link QKeyedTable} instance with given keys and values arrays. * * @param keys * keys {@link QTable} * @param values * values {@link QTable} * * @throws IllegalArgumentException */ public QKeyedTable(final QTable keys, final QTable values) { length = keys.getRowsCount(); if ( length != values.getRowsCount() ) { throw new IllegalArgumentException("Keys and value arrays cannot have different length"); } this.keys = keys; this.values = values; } /** * Returns {@link QTable} containing table keys. * * @return table of keys */ public QTable getKeys() { return keys; } /** * Returns {@link QTable} containing table values. * * @return table of values */ public QTable getValues() { return values; } /* * (non-Javadoc) * * @see com.exxeleron.qjava.Table#size() */ public int getRowsCount() { return keys.getRowsCount(); } /* * (non-Javadoc) * * @see com.exxeleron.qjava.Table#getColumnsCount() */ public int getColumnsCount() { return keys.getColumnsCount() + values.getColumnsCount(); } /* * (non-Javadoc) * * @see com.exxeleron.qjava.Table#hasColumn(java.lang.String) */ public boolean hasColumn( final String column ) { return keys.hasColumn(column) || values.hasColumn(column); } /* * (non-Javadoc) * * @see com.exxeleron.qjava.Table#getColumnIndex(java.lang.String) */ public int getColumnIndex( final String column ) { if ( keys.hasColumn(column) ) { return keys.getColumnIndex(column); } else { return keys.getColumnsCount() + values.getColumnIndex(column); } } /** * <p> * Returns an iterator over a key/value pairs stored in the keyed table. * </p> * * <p> * Note that the iterator returned by this method will throw an {@link UnsupportedOperationException} in response to * its <code>remove</code> method. * </p> * * @see java.lang.Iterable#iterator() */ public Iterator<KeyValuePair> iterator() { return new Iterator<QKeyedTable.KeyValuePair>() { private int index = 0; private KeyValuePair row = new KeyValuePair(0); public boolean hasNext() { return index < length; } public KeyValuePair next() { if ( hasNext() ) { row.setRowIndex(index++); return row; } else { throw new NoSuchElementException(); } } public void remove() { throw new UnsupportedOperationException(); } }; } /** * Defines a key/value pair that can be retrieved. */ public class KeyValuePair { private int index; KeyValuePair(final int index) { this.index = index; } /** * Returns index of the row. * * @return {@link int} */ public int getRowIndex() { return index; } /** * Moves the row view to new index. * * @param index * the index to set */ public void setRowIndex( final int index ) { if ( index < 0 || index > getRowsCount() ) { throw new IndexOutOfBoundsException(); } this.index = index; } /** * Returns key from given pair. * * @return key */ public QTable.Row getKey() { return keys.get(index); } /** * Returns value from given pair. * * @return value */ public QTable.Row getValue() { return values.get(index); } } /** * Returns a String that represents the current {@link QKeyedTable}. * * @return a String representation of the {@link QKeyedTable} * @see java.lang.Object#toString() */ @Override public String toString() { return "QKeyedTable: " + keys + "|" + values; } /** * Indicates whether some other object is "equal to" this keyed table. {@link QKeyedTable} objects are considered * equal if the keys and values lists are equal for both instances. * * @return <code>true</code> if this object is the same as the obj argument, <code>false</code> otherwise. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals( final Object obj ) { if ( this == obj ) { return true; } if ( !(obj instanceof QKeyedTable) ) { return false; } final QKeyedTable kt = (QKeyedTable) obj; return keys.equals(kt.getKeys()) && values.equals(kt.getValues()); } /** * Returns a hash code value for this {@link QKeyedTable}. * * @return a hash code value for this object * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 31 * keys.hashCode() + values.hashCode(); } }