/*
 * 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 org.apache.uima.cas.impl;

import org.apache.uima.cas.Type;
import org.apache.uima.cas.impl.SlotKinds.SlotKind;

public class TypeImpl_array extends TypeImpl implements TypeSystemConstants {
  
  private final TypeImpl componentType;
  
  private final boolean isHeapStoredArray;
  
  /** Component slot kind */
  private final SlotKind  componentSlotKind;
  
  public TypeImpl_array(String name, TypeImpl componentType, TypeSystemImpl tsi, TypeImpl supertype, 
      SlotKind componentSlotKind, boolean isHeapStoredArray, Class<?> javaClass) {
    super(name, tsi, supertype, javaClass);
    this.isInheritanceFinal = true;
    this.isFeatureFinal = true;
    this.componentType = componentType;
    this.isHeapStoredArray = isHeapStoredArray;
    this.componentSlotKind = componentSlotKind;
  }
  
  @Override
  public TypeImpl getComponentType() {
    return componentType;
  }
  
  @Override
  TypeImpl consolidateType(TypeImpl topType, TypeImpl fsArrayType) {
    if (!(componentType.isPrimitive())) {
        return fsArrayType;  // booleanArrayType, stringArrayType etc.
    }
    // is a primitive array
    return this;
  }
  
  @Override
  public boolean isArray() {
    return true;
  }
  
  @Override
  boolean isHeapStoredArray() {
    return isHeapStoredArray;
  }
  
  @Override
  boolean isAuxStoredArray() {
    return !isHeapStoredArray;
  }
  
  /** Component Slot Kind */
  @Override
  public SlotKind getComponentSlotKind() {
    return componentSlotKind;
  }
  
  @Override
  public boolean subsumes(TypeImpl subType) {
    if (this == subType) {
      return true;
    }
    
    // Need special handling for arrays
    
    if (!subType.isArray()) {
      return false;  // arrays never subsume non-arrays
    }
    
    // Yes, the code below is intentional. Until we actually support real arrays of some particular fs,
    
    // We have FSArray is the supertype of xxxx[] ( xxxx is non-primitive) AND
    //           xxx[] is the supertype of FSArray
    // (this second relation because all we can generate are instances of FSArray
    // and we must be able to assign them to xxx[] )
    
    
    final TypeImpl superType = this;
    final int superTypeCode = getCode();
    
    if (superTypeCode == fsArrayTypeCode) {
      return !subType.isPrimitiveArrayType();
    }
    
    if (subType.getCode() == fsArrayTypeCode) {
      return superTypeCode == arrayBaseTypeCode ||
             !isPrimitiveArrayType();
    }

    // at this point, we could have arrays of other primitive types, or
    // arrays of specific types: xxx[]

    // If both types are arrays, simply compare the components.
    return getComponentType().subsumes(subType.getComponentType());
 
//    } else if (isSubArray) {
//      // If the subtype is an array, and the supertype is not, then the
//      // supertype must be top, or the abstract array base.
//      return superTypeCode == topTypeCode || superTypeCode == arrayBaseTypeCode;
//    }
        
  }
}

@@ -864,42 +864,8 @@
 %0D%0A%0D%0A
-import org.apache.uima.cas.Type;%0D%0A
 impo
@@ -2989,16 +2989,141 @@
 xx%5B%5D )%0D%0A
+    //   *** Correction: there is a way to generate instances of xxx%5B%5D - via ll_createArray and CASImpl.createTempArray ***%0D%0A
     %0D%0A  
@@ -3294,32 +3294,49 @@
 tiveArrayType();
+    // primitive 
 %0D%0A    %7D%0D%0A    %0D%0A 
@@ -3437,581 +3437,1202 @@
 e %7C%7C
-%0D%0A             !isPrimitiveArrayType();%0D%0A    %7D%0D%0A%0D%0A    // at this point, we could have arrays of other primitive types, or%0D%0A    // arrays of specific types: xxx%5B%5D%0D%0A%0D%0A    // If both types are arrays, simply compare the components.%0D%0A    return getComponentType().subsumes(subType.getComponentType());%0D%0A %0D%0A//    %7D else if (isSubArray) %7B%0D%0A//      // If the subtype is an array, and the supertype is not, then the%0D%0A//      // supertype must be top, or the abstract array base.%0D%0A//      return superTypeCode == topTypeCode %7C%7C superTypeCode == arrayBaseTypeCode;%0D%0A//    %7D%0D%0A        
+  // this subsumes FSArray only if this is arrayBaseTypeCode, or %0D%0A                                                    //       this is some Array of specific FSs (seems wrong)%0D%0A             !isPrimitiveArrayType();%0D%0A    %7D%0D%0A%0D%0A    // at this point, the super type and the subtype are %0D%0A    //  both arrays, %0D%0A    //  not fsArrays%0D%0A    //  not equal%0D%0A    %0D%0A    if (superType.isPrimitiveArrayType() %7C%7C subType.isPrimitiveArrayType()) %7B%0D%0A      return false; %0D%0A    %7D%0D%0A    %0D%0A    return getComponentType().subsumes(subType.getComponentType());%0D%0A %0D%0A//    %7D else if (isSubArray) %7B%0D%0A//      // If the subtype is an array, and the supertype is not, then the%0D%0A//      // supertype must be top, or the abstract array base.%0D%0A//      return superTypeCode == topTypeCode %7C%7C superTypeCode == arrayBaseTypeCode;%0D%0A//    %7D%0D%0A        %0D%0A  %7D%0D%0A %0D%0A  /**%0D%0A   * @return true if this array type is a subtype of FSArray over a specific feature structure (other than TOP, or %0D%0A   *              one of the primitives)%0D%0A   */%0D%0A  @Override%0D%0A  public boolean isTypedFsArray() %7B%0D%0A    return componentType.isRefType && %0D%0A           componentType.getCode() != fsArrayTypeCode && %0D%0A           componentType.getCode() != topTypeCode;
 %0D%0A  

support arrays of typed FSs