AbstractRecord.java
package autumn.lang.internals;
import autumn.lang.Record;
import autumn.util.F;
import com.mackenziehigh.autumn.util.T;
import com.google.common.collect.Lists;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* This class provides a partial implementation of the Record type.
*
* <p>
* A subclass must provide a single constructor.
* The constructor takes one parameter for each element in the record.
* The constructor simply places its parameters into the appropriate elements.
* The new record must be immutable.
* </p>
*
* <p>
* A subclass needs to implement the following methods:
* <ul>
* <li>static method instance() - Returns an immutable empty instance.</li>
* <li>isStruct()</li>
* <li>isTuple()</li>
* <li>keys()</li>
* <li>types()</li>
* <li>values()</li>
* <li>set(int, Object)</li>
* <li>get(int)</li>
* </ul>
* </p>
*
* <p>
* A subclass must provide bridge methods for every method herein that returns a Record.
* The return-type of the bridge method must be the subclass itself.
* For example in a subclass T, method copy() : Record should have a bridge method copy() : T.
* <br>
* <ul>
* <li>set(int, Object)</li>
* <li>copy()</li>
* </ul>
* </p>
*
* @author Mackenzie High
*/
public abstract class AbstractRecord
implements Record
{
/**
* {@inheritDoc}
*/
@Override
public abstract List<String> keys();
/**
* {@inheritDoc}
*/
@Override
public abstract List<Class> types();
/**
* {@inheritDoc}
*/
@Override
public abstract boolean isStruct();
/**
* {@inheritDoc}
*/
@Override
public abstract boolean isTuple();
/**
* {@inheritDoc}
*/
@Override
public abstract Record set(int index,
Object value);
/**
* {@inheritDoc}
*/
@Override
public abstract Object get(int index);
/**
* {@inheritDoc}
*/
@Override
public final List<Object> values()
{
final int size = size();
final List<Object> values = Lists.newLinkedList();
for (int i = 0; i < size; i++)
{
values.add(get(i));
}
final List<Object> result = Collections.unmodifiableList(values);
return result;
}
/**
* {@inheritDoc}
*/
@Override
public final int size()
{
return keys().size();
}
/**
* {@inheritDoc}
*/
@Override
public final boolean isEmpty()
{
return size() == 0;
}
/**
* {@inheritDoc}
*/
@Override
public final int compareTo(final Record other)
{
if (other == null)
{
return 1; // Null is always less than an object.
}
else if (keys().equals(other.keys()) == false)
{
throw new UnsupportedOperationException();
}
else
{
for (int i = 0; i < size(); i++)
{
try
{
final Comparable operand1 = (Comparable) this.get(i);
final Comparable operand2 = (Comparable) other.get(i);
final int relationship = T.compare(operand1, operand2);
if (relationship < 0)
{
return -1;
}
else if (relationship > 0)
{
return 1;
}
}
catch (ClassCastException ex)
{
throw new UnsupportedOperationException(ex);
}
}
}
return 0;
}
/**
* {@inheritDoc}
*/
@Override
public final boolean equals(final Object other)
{
if (other == null)
{
return false;
}
if (this == other)
{
return true;
}
if (other instanceof Record == false)
{
return false;
}
final Record record = (Record) other;
final boolean answer = keys().equals(record.keys()) && values().equals(record.values());
return answer;
}
/**
* {@inheritDoc}
*/
@Override
public final int hashCode()
{
return keys().hashCode() ^ values().hashCode();
}
/**
* {@inheritDoc}
*/
@Override
public final Iterator<Object> iterator()
{
return values().iterator();
}
/**
* {@inheritDoc}
*/
@Override
public final String toString()
{
final String result = F.str(values(), "(", ", ", ")");
return result;
}
}