Code Search for Developers
 
 
  

ArrayData.java from DrJava at Krugle


Show ArrayData.java syntax highlighted

/*BEGIN_COPYRIGHT_BLOCK
 *
 * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software is Open Source Initiative approved Open Source Software.
 * Open Source Initative Approved is a trademark of the Open Source Initiative.
 * 
 * This file is part of DrJava.  Download the current version of this project
 * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 * 
 * END_COPYRIGHT_BLOCK*/

package edu.rice.cs.javalanglevels;

import edu.rice.cs.javalanglevels.tree.*;
import edu.rice.cs.javalanglevels.parser.*;
import java.util.*;
import junit.framework.*;
import java.io.File;
import edu.rice.cs.plt.reflect.JavaVersion;

/**
 * Represents the data for an array class.  There are two states of SymbolData.  One is a continuation which
 * is created when a type is referenced, but the corresponding class has not been read for its members.  The
 * other is a complete SymbolData containing all of the member data.
 * This ArrayData stores the SymbolData of its element type inside of it.
 */

public class ArrayData extends SymbolData {
  /**The type of the elements of this array.  For example, int[] has an _elementType of int.*/
  private SymbolData _elementType;
  
  /**
   * Creates a new ArrayData corresponding to the elementType sd.
   * @param sd  The SymbolData element type.
   * @param llv  The LanguageLevelVisitor who created this ArrayData.
   * @param si  The SourceInfo corresponding to this ArrayData.
   */
  public ArrayData(SymbolData sd, LanguageLevelVisitor llv, SourceInfo si) {
    super(sd.getName() + "[]");
    
    _elementType = sd;
    
    // Arrays only have one field called length, and it is automatically given a value
    addVar(new VariableData("length", 
                            new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, 
                                                       new String[] {"public", "final"}),
                            SymbolData.INT_TYPE, true, this));
    
    
    //All arrays are a subclass of Object
    SymbolData object = llv.getSymbolData("java.lang.Object", si);
    setSuperClass(object);
    
    //All arrays implement java.lang.Cloneable and java.io.Serializable
    SymbolData result = llv.getSymbolData("java.lang.Cloneable", si);
    if (result != null) {
      addInterface(result);
    }
    
    result = llv.getSymbolData("java.io.Serializable", si);
    if (result != null) {
      addInterface(result);
    }
    
    //And, since they implement Cloneable, all arrays overwrite the clone method so that it does not throw exceptions
    addMethod(new MethodData("clone", 
                             new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"public"}), 
                             new TypeParameter[0],
                             object,
                             new VariableData[0],
                             new String[0], //Doesn't throw any exceptions!
                             this,
                             null));
                             
    setIsContinuation(false);

  }

  /*@return the package of the element type*/
  public String getPackage() {
    return _elementType.getPackage();
  }
  
  /*Set the package of the element type to be the specified package:
   * @param s  The package to use*/
  public void setPackage(String s) {
    _elementType.setPackage(s);
  }
  
  
  /* @return the ModifiersAndVisibility of the element type*/
  public ModifiersAndVisibility getMav() {
    if (_elementType.hasModifier("final")) { return _elementType.getMav(); }
    else {
      String[] elementMavs = _elementType.getMav().getModifiers();
      String[] newMavs = new String[elementMavs.length + 1];
      for (int i = 0; i < elementMavs.length; i++) { newMavs[i] = elementMavs[i]; }
      newMavs[elementMavs.length] = "final";
      
      return new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, newMavs);
    }
  }
  
  /*Set the ModifiersAndVisibility of the element type to the specified value.
   * @param mv  The ModifiersAndVisibility to use.*/
  public void setMav(ModifiersAndVisibility mv) {
    _elementType.setMav(mv);
  }
  
  /*@return the SymbolData element type corresponding to the elements of this array.*/
  public SymbolData getElementType() {
    return _elementType;
  }
  
  /**Delegate to the outer data of your element type*/
  public Data getOuterData() {
    return _elementType.getOuterData();
  }
  
  /**
   * A Noop, because arrays shouldn't have outer data
   */
  public void setOuterData(Data outerData) {
//    _elementType.setOuterData(outerData);
  }
  
  
  public boolean equals(Object obj) {
    if (this == obj) {return true;}
    if (obj == null) return false;
    if ((obj.getClass() != this.getClass())) { //|| (obj.hashCode() != this.hashCode())) {
      return false;
    }
    ArrayData ad = (ArrayData) obj;    
    
    //For 2 array datas to be equal, all their symbolData fields must be equal, and their element types must be equal
    return super.equals(obj) && getElementType().equals(ad.getElementType());
    
    
  }
  
  /**
   * Provide a hashcode method that distinguishes between array datas based on name
   */
  public int hashCode() {
    return getName().hashCode();
  }
  
  /**
   *      Returns true only under the following conditions: 
   *      -if assignTo is a class, assignTo must be java.lang.Object.
   *      -if assignTo is an interferface, then it must be Serializable or Clonable.
   *      -if assignTo is an array, then if this's element type is a primitive assignTo must have the same primitive element type and
   *          if this's element type is a reference type, this's reference type must be assignable to assignTo's element type.
   */
  public boolean isAssignableTo(SymbolData assignTo, JavaVersion version) {
    if (assignTo instanceof ArrayData) {
      if (this.getElementType().isPrimitiveType()) {
        return this.getElementType() == ((ArrayData)assignTo).getElementType();
      }
      else if (((ArrayData)assignTo).getElementType().isPrimitiveType()) {
        return false;
      }
      else {
        return this.getElementType().isAssignableTo(((ArrayData)assignTo).getElementType(), version);
      }
    }
    else {
      return this.isSubClassOf(assignTo);
    }
  }
  
  /**
   * Return true iff
   *      - castTo is a class type and is Object
   *      - castTo is an interface type that is Serializable or Clonable
   *      - castTo is an array type then this and castTo must have element types that are either the same primitive type or (both reference types and this's element type must be castable to castTo's element type)
   */
  public boolean isCastableTo(SymbolData castTo, JavaVersion version) {
    if (castTo instanceof ArrayData) {
      if (this.getElementType().isPrimitiveType()) {
        return this.getElementType() == ((ArrayData)castTo).getElementType();
      }
      else if (((ArrayData)castTo).getElementType().isPrimitiveType()) {
        return false;
      }
      else {
        return this.getElementType().isCastableTo(((ArrayData)castTo).getElementType(), version);
      }
    }
    else if (this.isSubClassOf(castTo)) {
      return true;
    }
    else {
      return this.isSubClassOf(castTo);
    }
  }
  
  /**
   * Return the dimensions of this array (the level of nesting until a non-array element type is found).
   */
  public int getDimensions() {
    int dim = 1;
    SymbolData curData = this.getElementType();
    while(curData instanceof ArrayData) {
      dim ++;
      curData = ((ArrayData) curData).getElementType();
    }
    return dim;
  }
  

   /**
    * Test the methods in the enclosing class.  There is a test method corresponding to almost every method defined above.
    */
  public static class ArrayDataTest extends TestCase {
    
    private ArrayData _ad;
    
    private ModifiersAndVisibility _publicMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"public"});
    private ModifiersAndVisibility _protectedMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"protected"});
    private ModifiersAndVisibility _privateMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"private"});
    private ModifiersAndVisibility _packageMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[0]);
    private ModifiersAndVisibility _abstractMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"abstract"});
    private ModifiersAndVisibility _finalMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"final"});
    private ModifiersAndVisibility _publicFinalMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[]{"public", "final"});
    private ModifiersAndVisibility _privateFinalMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"private", "final"});
    
    private LanguageLevelVisitor llv;
    private SourceInfo si;
    
    public ArrayDataTest() {
      this("");
    }
    public ArrayDataTest(String name) {
      super(name);
    }
    
    public void setUp() {
      llv = new LanguageLevelVisitor(new File(""), "", new LinkedList<String>(), new LinkedList<String>(),
                                                          new LinkedList<String>(), new Hashtable<String, Pair<TypeDefBase, LanguageLevelVisitor>>(), 
                                                          new Hashtable<String, Pair<SourceInfo, LanguageLevelVisitor>>());
      
      llv.symbolTable = new Symboltable();
      si = JExprParser.NO_SOURCE_INFO;
      SymbolData e = new SymbolData("elementType");
      e.setIsContinuation(false);
      _ad = new ArrayData(e, llv, si);
      LanguageLevelVisitor.errors = new LinkedList<Pair<String, JExpressionIF>>();
    }
    
    public void testGetDimensions() {
      ArrayData intArray = new ArrayData(SymbolData.INT_TYPE, llv, si);
      intArray.setIsContinuation(false);
      llv.symbolTable.remove("int[]");
      llv.symbolTable.put("int[]", intArray);
      
      ArrayData intArrayArray = new ArrayData(intArray, llv, si);
      intArrayArray.setIsContinuation(false);
      llv.symbolTable.put("int[][]", intArrayArray);

      ArrayData intArray3 = new ArrayData(intArrayArray, llv, si);
      intArray3.setIsContinuation(false);
      llv.symbolTable.put("int[][][]", intArray3);
      
      assertEquals("Should return 1", 1, intArray.getDimensions());
      assertEquals("Should return 2", 2, intArrayArray.getDimensions());
      assertEquals("Should return 3", 3, intArray3.getDimensions());
    }
    
    public void testGetPackage() {
      SymbolData sd = _ad.getElementType();
      sd.setPackage("a.b");
      assertEquals("Should return a.b", "a.b", _ad.getPackage());
      
      sd.setPackage("");
      assertEquals("Should return empty string", "", _ad.getPackage());
      
      sd.setPackage("who.let");
      assertEquals("Should return who.let", "who.let", _ad.getPackage());
    }
    
    public void testSetPackage() {
      SymbolData sd = _ad.getElementType();
      _ad.setPackage("a.b");
      assertEquals("Should return a.b", "a.b", sd.getPackage());
      
      _ad.setPackage("");
      assertEquals("Should return empty string", "", sd.getPackage());
      
      _ad.setPackage("who.let");
      assertEquals("Should return who.let", "who.let", sd.getPackage());
      
    }

    public void testGetMav() {
      SymbolData sd = _ad.getElementType();

      sd.setMav(_publicMav);
      assertEquals("Should return _publicFinal mav", _publicFinalMav, _ad.getMav());
      
      sd.setMav(_privateMav);
      assertEquals("Should return _privateFinal mav", _privateFinalMav, _ad.getMav());
      
      sd.setMav(_packageMav);
      assertEquals("Should return _finalMav", _finalMav, _ad.getMav());
      
      sd.setMav(_publicFinalMav);
      assertEquals("Should return _publicFinalMav", _publicFinalMav, _ad.getMav());
    }

    public void testSetMav() {
      SymbolData sd = _ad.getElementType();
      
      _ad.setMav(_publicMav);
      assertEquals("Should return _publicMav", _publicMav, sd.getMav());
      
      _ad.setMav(_privateMav);
      assertEquals("Should return _privateMav", _privateMav, sd.getMav());
      
      _ad.setMav(_publicFinalMav);
      assertEquals("Should return _publicFinalMav", _publicFinalMav, _ad.getMav());
      
    }
    
    
    public void testIsAssignableTo() {
      //if assignTo is a class, it must be java.lang.Object
      SymbolData object = llv.symbolTable.get("java.lang.Object");
      assertTrue(_ad.isAssignableTo(object, JavaVersion.JAVA_5));
      assertTrue(_ad.isAssignableTo(object, JavaVersion.JAVA_1_4));
      
      SymbolData notObject = new SymbolData("somethingRandom");
      assertFalse(_ad.isAssignableTo(notObject, JavaVersion.JAVA_5));
      assertFalse(_ad.isAssignableTo(notObject, JavaVersion.JAVA_1_4));
      
      //if assignTo is an interface, then it must be Serializable or Clonable
      SymbolData serializable = _ad.getInterfaces().get(0);
      SymbolData clonable = _ad.getInterfaces().get(1);
      notObject.setInterface(true);
      
      assertTrue(_ad.isAssignableTo(serializable, JavaVersion.JAVA_5));
      assertTrue(_ad.isAssignableTo(serializable, JavaVersion.JAVA_1_4));
      assertTrue(_ad.isAssignableTo(clonable, JavaVersion.JAVA_5));
      assertTrue(_ad.isAssignableTo(clonable, JavaVersion.JAVA_1_4));
      assertFalse(_ad.isAssignableTo(notObject, JavaVersion.JAVA_5));
      assertFalse(_ad.isAssignableTo(notObject, JavaVersion.JAVA_1_4));

      //if array is an array of primatives, then assign to must have primitive types that must match exactly
      _ad = new ArrayData(SymbolData.INT_TYPE, llv, si);
      ArrayData intArray = new ArrayData(SymbolData.INT_TYPE, llv, si);
      ArrayData doubleArray = new ArrayData(SymbolData.DOUBLE_TYPE, llv, si);
      ArrayData charArray = new ArrayData(SymbolData.CHAR_TYPE, llv, si);
      ArrayData objArray = new ArrayData(object, llv, si);
      
      assertTrue(_ad.isAssignableTo(intArray, JavaVersion.JAVA_5));
      assertTrue(_ad.isAssignableTo(intArray, JavaVersion.JAVA_1_4));
      assertFalse(_ad.isAssignableTo(charArray, JavaVersion.JAVA_5));
      assertFalse(_ad.isAssignableTo(charArray, JavaVersion.JAVA_1_4));
      assertFalse(_ad.isAssignableTo(doubleArray, JavaVersion.JAVA_5));
      assertFalse(_ad.isAssignableTo(doubleArray, JavaVersion.JAVA_1_4));
      assertFalse(_ad.isAssignableTo(objArray, JavaVersion.JAVA_5));
      assertFalse(_ad.isAssignableTo(objArray, JavaVersion.JAVA_1_4));

      
      //if array is an array of reference types, then reference types must be assignable to element type
      SymbolData integerSd = new SymbolData("java.lang.Integer");
      integerSd.setSuperClass(object);
      _ad = new ArrayData(integerSd, llv, si);
      notObject.setInterface(false);
      ArrayData randomArray = new ArrayData(notObject, llv, si);

      assertTrue(_ad.isAssignableTo(objArray, JavaVersion.JAVA_5));
      assertTrue(_ad.isAssignableTo(objArray, JavaVersion.JAVA_1_4));
      assertTrue(_ad.isAssignableTo(_ad, JavaVersion.JAVA_5));
      assertTrue(_ad.isAssignableTo(_ad, JavaVersion.JAVA_1_4));
      assertFalse(_ad.isAssignableTo(randomArray, JavaVersion.JAVA_5));
      assertFalse(_ad.isAssignableTo(randomArray, JavaVersion.JAVA_1_4));
      assertFalse(_ad.isAssignableTo(intArray, JavaVersion.JAVA_5));
      assertFalse(_ad.isAssignableTo(intArray, JavaVersion.JAVA_1_4));
    }
   
    
    public void testIsCastableTo() {
      //if castTo is a class type and Object, should work
      SymbolData object = llv.symbolTable.get("java.lang.Object");
      assertTrue(_ad.isCastableTo(object, JavaVersion.JAVA_5));
      assertTrue(_ad.isCastableTo(object, JavaVersion.JAVA_1_4));
      
      //if castTo is an interface, then it must be Serializable or Clonable
      SymbolData serializable = _ad.getInterfaces().get(0);
      SymbolData clonable = _ad.getInterfaces().get(1);
      
      assertTrue(_ad.isAssignableTo(serializable, JavaVersion.JAVA_5));
      assertTrue(_ad.isAssignableTo(serializable, JavaVersion.JAVA_1_4));
      assertTrue(_ad.isAssignableTo(clonable, JavaVersion.JAVA_5));
      assertTrue(_ad.isAssignableTo(clonable, JavaVersion.JAVA_1_4));

      //anything non-array type should break
      SymbolData notObject = new SymbolData("somethingRandom");
      assertFalse(_ad.isCastableTo(notObject, JavaVersion.JAVA_5));
      assertFalse(_ad.isCastableTo(notObject, JavaVersion.JAVA_1_4));

      
     
      //if castTo is an array and the array elements can be cast to its elements, should work
      
      //if array is an array of primatives, then assign to must have primitive types that must match exactly
      _ad = new ArrayData(SymbolData.INT_TYPE, llv, si);
      ArrayData intArray = new ArrayData(SymbolData.INT_TYPE, llv, si);
      ArrayData doubleArray = new ArrayData(SymbolData.DOUBLE_TYPE, llv, si);
      ArrayData charArray = new ArrayData(SymbolData.CHAR_TYPE, llv, si);
      ArrayData objArray = new ArrayData(object, llv, si);
      
      assertTrue(_ad.isCastableTo(intArray, JavaVersion.JAVA_5));
      assertTrue(_ad.isCastableTo(intArray, JavaVersion.JAVA_1_4));
      assertFalse(_ad.isCastableTo(charArray, JavaVersion.JAVA_5));
      assertFalse(_ad.isCastableTo(charArray, JavaVersion.JAVA_1_4));
      assertFalse(_ad.isCastableTo(doubleArray, JavaVersion.JAVA_5));
      assertFalse(_ad.isCastableTo(doubleArray, JavaVersion.JAVA_1_4));
      assertFalse(_ad.isCastableTo(objArray, JavaVersion.JAVA_5));
      assertFalse(_ad.isCastableTo(objArray, JavaVersion.JAVA_1_4));

      
      //if array is an array of reference types, then reference types must be castable to element type
      SymbolData integerSd = new SymbolData("java.lang.Integer");
      integerSd.setSuperClass(object);
      _ad = new ArrayData(integerSd, llv, si);
      notObject.setInterface(false);
      ArrayData randomArray = new ArrayData(notObject, llv, si);

      assertTrue(_ad.isCastableTo(objArray, JavaVersion.JAVA_5));
      assertTrue(_ad.isCastableTo(objArray, JavaVersion.JAVA_1_4));
      assertTrue(_ad.isCastableTo(_ad, JavaVersion.JAVA_5));
      assertTrue(_ad.isCastableTo(_ad, JavaVersion.JAVA_1_4));
      assertFalse(_ad.isCastableTo(randomArray, JavaVersion.JAVA_5));
      assertFalse(_ad.isCastableTo(randomArray, JavaVersion.JAVA_1_4));
      assertFalse(_ad.isCastableTo(intArray, JavaVersion.JAVA_5));
      assertFalse(_ad.isCastableTo(intArray, JavaVersion.JAVA_1_4));

      _ad = new ArrayData(object, llv, si);
      assertTrue(_ad.isCastableTo(new ArrayData(integerSd, llv, si), JavaVersion.JAVA_5));
      assertTrue(_ad.isCastableTo(new ArrayData(integerSd, llv, si), JavaVersion.JAVA_1_4));
      assertFalse(_ad.isCastableTo(new ArrayData(SymbolData.INT_TYPE, llv, si), JavaVersion.JAVA_5));
      assertFalse(_ad.isCastableTo(new ArrayData(SymbolData.INT_TYPE, llv, si), JavaVersion.JAVA_1_4));
    }
  }
}



See more files for this project here

DrJava

DrJava is a lightweight programming environment for Java designed to foster test-driven software development. It includes an intelligent program editor, an interactions pane for evaluating program text, a source level debugger, and a unit testing tool.

Project homepage: http://sourceforge.net/projects/drjava
Programming language(s): Java
License: other

  AdvancedLevelTest.java
  AdvancedVisitor.java
  ArrayData.java
  Augmentor.java
  BlockData.java
  Bob.java
  BodyBodyAdvancedVisitor.java
  BodyBodyElementaryVisitor.java
  BodyBodyIntermediateVisitor.java
  BodyData.java
  BodyTypeChecker.java
  CharConverter.java
  ClassBodyAdvancedVisitor.java
  ClassBodyElementaryVisitor.java
  ClassBodyIntermediateVisitor.java
  ClassBodyTypeChecker.java
  ConstructorBodyTypeChecker.java
  Data.java
  ElementaryLevelTest.java
  ElementaryVisitor.java
  ExpressionTypeChecker.java
  InstanceData.java
  InterfaceBodyAdvancedVisitor.java
  InterfaceBodyIntermediateVisitor.java
  InterfaceBodyTypeChecker.java
  IntermediateLevelTest.java
  IntermediateVisitor.java
  JExprParseException.java
  JExprParserTest.java
  JExpressionIFPrunableDepthFirstVisitor_void.java
  LValueTypeChecker.java
  LValueWithValueTypeChecker.java
  LanguageLevelConverter.java
  LanguageLevelVisitor.java
  MethodData.java
  PackageData.java
  Pair.java
  PrimitiveData.java
  SourceInfo.java
  SymbolData.java
  Symboltable.java
  TryCatchBodyTypeChecker.java
  TypeChecker.java
  TypeData.java
  VariableData.java
  VoidMethodsNotAllowedClassBodyTypeChecker.java
  jexpr.ast
  jexpr.jj