001/*
002 * Created on May 3, 2005
003 *
004 */
005package daikon.chicory;
006
007import java.lang.reflect.InvocationTargetException;
008import java.lang.reflect.Method;
009import java.util.List;
010
011/**
012 * The ListInfo class is a subtype of DaikonVariableInfo used for variable types that implement
013 * {@code java.util.List}.
014 */
015public class ListInfo extends DaikonVariableInfo {
016
017  private Class<? extends List<?>> listType;
018
019  public ListInfo(String theName, Class<? extends List<?>> theType) {
020    super(theName, theType.getName(), "hashcode[]", true);
021    listType = theType;
022  }
023
024  // use the "toArray" method to get an array
025  // convert the array to a List
026  @Override
027  public Object getMyValFromParentVal(Object value) {
028
029    Method arrayMethod;
030    try {
031      arrayMethod = listType.getMethod("toArray", new Class<?>[0]);
032    } catch (NoSuchMethodException e) {
033      throw new Error(
034          listType.getName()
035              + " seems to implement java.util.List, but method toArray() not found");
036    }
037
038    Object arrayVal;
039
040    if (value != null && !(value instanceof NonsensicalObject)) {
041
042      // TODO why can't we just cast to List and call toArray directly?
043
044      try {
045        arrayVal = arrayMethod.invoke(value, new Object[0]);
046      } catch (IllegalArgumentException e1) {
047        throw new Error(e1);
048      } catch (IllegalAccessException e1) {
049        throw new Error(e1);
050      } catch (InvocationTargetException e1) {
051        // We used to check for java.util.ConcurrentModificationException, but
052        // now beleive than any InvocationTargetException should not fail and
053        // thus should return Nonsensical.
054        // Possibly, this should be extended to all exceptions.
055        System.err.println(
056            "Detected a InvocationTargetException in: " + listType.getName() + " " + getName());
057        arrayVal = NonsensicalObject.getInstance();
058      }
059    } else {
060      arrayVal = NonsensicalObject.getInstance();
061    }
062
063    @SuppressWarnings("nullness") // We just verified (or set) arrayVal in code above.
064    Object tmp = DTraceWriter.getListFromArray(arrayVal);
065    return tmp;
066  }
067
068  /** Lists are arrays from Daikon's point of view. */
069  @Override
070  public VarKind get_var_kind() {
071    return VarKind.ARRAY;
072  }
073}