/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.value;
import java.lang.reflect.Array;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import org.h2.engine.Constants;
import org.h2.util.MathUtils;
import org.h2.util.New;
import org.h2.util.StatementBuilder;
/**
* Implementation of the ARRAY data type.
*/
public class ValueArray extends Value {
private final Class<?> componentType;
private final Value[] values;
private int hash;
private ValueArray(Class<?> componentType, Value[] list) {
this.componentType = componentType;
this.values = list;
}
private ValueArray(Value[] list) {
this(Object.class, list);
}
/**
* Get or create a array value for the given value array.
* Do not clone the data.
*
* @param list the value array
* @return the value
*/
public static ValueArray get(Value[] list) {
return new ValueArray(list);
}
/**
* Get or create a array value for the given value array.
* Do not clone the data.
*
* @param componentType the array class (null for Object[])
* @param list the value array
* @return the value
*/
public static ValueArray get(Class<?> componentType, Value[] list) {
return new ValueArray(componentType, list);
}
public int hashCode() {
if (hash != 0) {
return hash;
}
int h = 1;
for (Value v : values) {
h = h * 31 + v.hashCode();
}
hash = h;
return h;
}
public Value[] getList() {
return values;
}
public int getType() {
return Value.ARRAY;
}
public Class<?> getComponentType() {
return componentType;
}
public long getPrecision() {
long p = 0;
for (Value v : values) {
p += v.getPrecision();
}
return p;
}
public String getString() {
StatementBuilder buff = new StatementBuilder("(");
for (Value v : values) {
buff.appendExceptFirst(", ");
buff.append(v.getString());
}
return buff.append(')').toString();
}
protected int compareSecure(Value o, CompareMode mode) {
ValueArray v = (ValueArray) o;
if (values == v.values) {
return 0;
}
int l = values.length;
int ol = v.values.length;
int len = Math.min(l, ol);
for (int i = 0; i < len; i++) {
Value v1 = values[i];
Value v2 = v.values[i];
int comp = v1.compareTo(v2, mode);
if (comp != 0) {
return comp;
}
}
return l > ol ? 1 : l == ol ? 0 : -1;
}
public Object getObject() {
int len = values.length;
Object[] list = (Object[]) Array.newInstance(componentType, len);
for (int i = 0; i < len; i++) {
list[i] = values[i].getObject();
}
return list;
}
public void set(PreparedStatement prep, int parameterIndex) {
throw throwUnsupportedExceptionForType("PreparedStatement.set");
}
public String getSQL() {
StatementBuilder buff = new StatementBuilder("(");
for (Value v : values) {
buff.appendExceptFirst(", ");
buff.append(v.getSQL());
}
if (values.length == 1) {
buff.append(',');
}
return buff.append(')').toString();
}
public String getTraceSQL() {
StatementBuilder buff = new StatementBuilder("(");
for (Value v : values) {
buff.appendExceptFirst(", ");
buff.append(v.getTraceSQL());
}
return buff.append(')').toString();
}
public int getDisplaySize() {
long size = 0;
for (Value v : values) {
size += v.getDisplaySize();
}
return MathUtils.convertLongToInt(size);
}
public boolean equals(Object other) {
if (!(other instanceof ValueArray)) {
return false;
}
ValueArray v = (ValueArray) other;
if (values == v.values) {
return true;
}
int len = values.length;
if (len != v.values.length) {
return false;
}
for (int i = 0; i < len; i++) {
if (!values[i].equals(v.values[i])) {
return false;
}
}
return true;
}
public int getMemory() {
int memory = 32;
for (Value v : values) {
memory += v.getMemory() + Constants.MEMORY_POINTER;
}
return memory;
}
public Value convertPrecision(long precision, boolean force) {
if (!force) {
return this;
}
ArrayList<Value> list = New.arrayList();
for (Value v : values) {
v = v.convertPrecision(precision, true);
// empty byte arrays or strings have precision 0
// they count as precision 1 here
precision -= Math.max(1, v.getPrecision());
if (precision < 0) {
break;
}
list.add(v);
}
Value[] array = new Value[list.size()];
list.toArray(array);
return get(array);
}
}