content: /**
   * Copyright 2010 The Apache Software Foundation
   *
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you 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.alibaba.wasp.jdbc.value;
  
  import com.alibaba.wasp.util.New;
  import com.alibaba.wasp.util.StatementBuilder;
  
  import java.lang.reflect.Array;
  import java.sql.PreparedStatement;
  import java.util.ArrayList;
  
  /**
   * 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 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 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);
      }
  
  }
  