1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.bcel.internal.generic;
  23 
  24 import com.sun.org.apache.bcel.internal.Constants;
  25 
  26 /**
  27  * Denotes array type, such as int[][]
  28  *
  29  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  30  */
  31 public final class ArrayType extends ReferenceType {
  32   private int  dimensions;
  33   private Type basic_type;
  34 
  35   /**
  36    * Convenience constructor for array type, e.g. int[]
  37    *
  38    * @param type array type, e.g. T_INT
  39    */
  40   public ArrayType(byte type, int dimensions) {
  41     this(BasicType.getType(type), dimensions);
  42   }
  43 
  44   /**
  45    * Convenience constructor for reference array type, e.g. Object[]
  46    *
  47    * @param class_name complete name of class (java.lang.String, e.g.)
  48    */
  49   public ArrayType(String class_name, int dimensions) {
  50     this(new ObjectType(class_name), dimensions);
  51   }
  52 
  53   /**
  54    * Constructor for array of given type
  55    *
  56    * @param type type of array (may be an array itself)
  57    */
  58   public ArrayType(Type type, int dimensions) {
  59     super(Constants.T_ARRAY, "<dummy>");
  60 
  61     if((dimensions < 1) || (dimensions > Constants.MAX_BYTE))
  62       throw new ClassGenException("Invalid number of dimensions: " + dimensions);
  63 
  64     switch(type.getType()) {
  65     case Constants.T_ARRAY:
  66       ArrayType array = (ArrayType)type;
  67       this.dimensions = dimensions + array.dimensions;
  68       basic_type      = array.basic_type;
  69       break;
  70 
  71     case Constants.T_VOID:
  72       throw new ClassGenException("Invalid type: void[]");
  73 
  74     default: // Basic type or reference
  75       this.dimensions = dimensions;
  76       basic_type = type;
  77       break;
  78     }
  79 
  80     StringBuffer buf = new StringBuffer();
  81     for(int i=0; i < this.dimensions; i++)
  82       buf.append('[');
  83 
  84     buf.append(basic_type.getSignature());
  85 
  86     signature = buf.toString();
  87   }
  88 
  89   /**
  90    * @return basic type of array, i.e., for int[][][] the basic type is int
  91    */
  92   public Type getBasicType() {
  93     return basic_type;
  94   }
  95 
  96   /**
  97    * @return element type of array, i.e., for int[][][] the element type is int[][]
  98    */
  99   public Type getElementType() {
 100     if(dimensions == 1)
 101       return basic_type;
 102     else
 103       return new ArrayType(basic_type, dimensions - 1);
 104   }
 105 
 106   /** @return number of dimensions of array
 107    */
 108   public int getDimensions() { return dimensions; }
 109 
 110   /** @return a hash code value for the object.
 111    */
 112   public int hashCode() { return basic_type.hashCode() ^ dimensions; }
 113 
 114   /** @return true if both type objects refer to the same array type.
 115    */
 116   public boolean equals(Object type) {
 117     if(type instanceof ArrayType) {
 118       ArrayType array = (ArrayType)type;
 119       return (array.dimensions == dimensions) && array.basic_type.equals(basic_type);
 120     } else
 121       return false;
 122   }
 123 }