/** * 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 dictionary type. */ public final class QDictionary implements Iterable<QDictionary.KeyValuePair> { private final Object keys; private final Object values; private final int length; private final boolean areValuesArray; /** * Creates new {@link QDictionary} instance with given keys and values arrays. * * @param keys * keys array * @param values * values array * * @throws IllegalArgumentException */ public QDictionary(final Object keys, final Object values) { if ( keys == null || !keys.getClass().isArray() ) { throw new IllegalArgumentException("Parameter: keys is not an array"); } if ( values == null || !(values.getClass().isArray() || values instanceof QTable) ) { throw new IllegalArgumentException("Parameter: values is not an array nor table"); } length = Array.getLength(keys); if ( (values.getClass().isArray() && length != Array.getLength(values)) || (values instanceof QTable && length != ((QTable) values).getRowsCount()) ) { throw new IllegalArgumentException("Keys and values cannot have different length"); } this.keys = keys; this.values = values; this.areValuesArray = values.getClass().isArray(); } /** * Returns array containing list of keys stored in the dictionary. * * @return an array of keys */ public Object getKeys() { return keys; } /** * Returns array containing list of values stored in the dictionary. * * @return an array of values */ public Object getValues() { return values; } /** * Gets a number of entries in {@link QDictionary}. * * @return a number of entries */ public int size() { return length; } /** * <p> * Returns an iterator over a key/value pairs stored in the dictionary. * </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<QDictionary.KeyValuePair>() { private int index = 0; private KeyValuePair view = new KeyValuePair(index); public boolean hasNext() { return index < length; } public KeyValuePair next() { if ( hasNext() ) { view.setIndex(index++); return view; } 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) { setIndex(index); } /** * Returns index of the view. * * @return {@link int} */ public int getIndex() { return index; } /** * Moves the view to new index. * * @param index * the index to set */ public void setIndex( final int index ) { if ( index < 0 || index > length ) { throw new IndexOutOfBoundsException(); } this.index = index; } /** * Returns key from given pair. * * @return key */ public Object getKey() { return Array.get(keys, index); } /** * Returns value from given pair. * * @return value */ public Object getValue() { if ( areValuesArray ) { return Array.get(values, index); } else { return ((QTable) values).get(index); } } } /** * Returns a String that represents the current {@link QDictionary}. * * @return a String representation of the {@link QDictionary} * @see java.lang.Object#toString() */ @Override public String toString() { if ( areValuesArray ) { return "QDictionary: " + Utils.arrayToString(keys) + "!" + Utils.arrayToString(values); } else { return "QDictionary: " + Utils.arrayToString(keys) + "!" + values.toString(); } } /** * Indicates whether some other object is "equal to" this dictionary. {@link QDictionary} 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 QDictionary) ) { return false; } final QDictionary d = (QDictionary) obj; if ( areValuesArray ) { return Utils.deepArraysEquals(keys, d.keys) && Utils.deepArraysEquals(values, d.values); } else { return Utils.deepArraysEquals(keys, d.keys) && values.equals(d.values); } } /** * Returns a hash code value for this {@link QDictionary}. * * @return a hash code value for this object * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 31 * Utils.arrayHashCode(keys) + Utils.arrayHashCode(values); } }