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

org.numenta.nupic.util.Tuple Maven / Gradle / Ivy

/* ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2014-2016, Numenta, Inc.  Unless you have an agreement
 * with Numenta, Inc., for a separate license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero Public License for more details.
 *
 * You should have received a copy of the GNU Affero Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

package org.numenta.nupic.util;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.numenta.nupic.model.Persistable;

/**
 * An immutable fixed data structure whose values are retrieved
 * via a given index. This data structure emulates multiple method
 * return values possible in Python.
 * 
 * @author David Ray
 */
public class Tuple implements Persistable, Comparable {
    
    private static final long serialVersionUID = 1L;

    /** The internal container array */
	protected Object[] container;
	
	private int hashcode;
	
	private Comparator comparator;
	
	public Tuple() {}
	
	/**
	 * Instantiates a new {@code Tuple}
	 * @param objects
	 */
	public Tuple(Object... objects) {
		remake(objects);
	}
	
	/**
	 * Constructs a {@code Tuple} that will use the supplied
	 * {@link Comparator} to implement the {@link Comparable}
	 * interface.
	 * @param c            the Comparator function to use to compare the
	 *                     contents of the is {@code Tuple}
	 * @param objects      the objects contained within
	 */
	public Tuple(Comparator c, Object...objects) {
	    this.comparator = c;
	    remake(objects);
	}
	
	/**
	 * Remakes the internals for this Tuple.
	 * @param objects
	 */
	protected void remake(Object...objects) {
	    container = new Object[objects.length];
        for(int i = 0;i < objects.length;i++) container[i] = objects[i];
        this.hashcode = hashCode();
	}
	
	/**
	 * Returns the object previously inserted into the
	 * specified index.
	 * 
	 * @param index    the index representing the insertion order.
	 * @return
	 */
	public Object get(int index) {
		return container[index];
	}
	
	/**
	 * Returns the number of items in this {@code Tuple}
	 * 
	 * @return
	 */
	public int size() {
	    return container.length;
	}
	
	/**
	 * Returns an unmodifiable view of the underlying data.
	 * @return
	 */
	public  List all() {
	    return Collections.unmodifiableList(Arrays.asList(container));
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for(int i = 0;i < container.length;i++) {
			try {
				new Double((double) container[i]);
				sb.append(container[i]);
			}catch(Exception e) { sb.append("'").append(container[i]).append("'");}
			sb.append(":");
		}
		sb.setLength(sb.length() - 1);
		
		return sb.toString();
	}
	
	/**
     * {@inheritDoc}
     */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + Arrays.hashCode(container);
		return result;
	}

	/**
     * {@inheritDoc}
     */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Tuple other = (Tuple) obj;
		if (this.hashcode != other.hashcode)
			return false;
		return true;
	}

	/**
	 * Uses the supplied {@link Comparator} to compare this {@code Tuple}
	 * with the specified {@link Tuple}
	 */
    @Override
    public int compareTo(Tuple t) {
        if(comparator == null) {
            throw new IllegalStateException("Tuples used for comparison should be " +
                "instantiated using the constructor taking a Comparator");
        }
        
        return comparator.compare(this, t);
    }
}