/**
   * Updates the structure of any subsidiary element variables (if any) for the given
   * ConstraintVariable2 (if it is in fact a container).
   */
  private void updateElementVarStructureFromParent(ConstraintVariable2 v) {
    // Propagate structure from container variable to any subsidiary element variables
    if (elemStructure(v) != ParametricStructure.NONE
        && fTCModel.getElementVariables(v).size() > 0) {
      ParametricStructure t = elemStructure(v);
      for (Iterator iterator = fTCModel.getElementVariables(v).values().iterator();
          iterator.hasNext(); ) {
        CollectionElementVariable2 typeVar = (CollectionElementVariable2) iterator.next();
        int declarationTypeVariableIndex = typeVar.getDeclarationTypeVariableIndex();

        if (declarationTypeVariableIndex
            != CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX)
          updateStructureOfVar(
              typeVar, t.getParameters()[declarationTypeVariableIndex], TypeOperator.Equals);
      }
    }
  }
  /**
   * Updates the structure of the parent container variable of the given CollectionElementVariable2
   * from the structure of 'v1'.
   *
   * @param elemVar
   * @param v1
   */
  private void updateParentContainerStructureFrom(
      CollectionElementVariable2 elemVar, ConstraintVariable2 v1) {
    ConstraintVariable2 elemContainer = elemVar.getParentConstraintVariable();

    // This could be something that appears like it should have container
    // structure, but doesn't, e.g., an array access for an array of containers
    // (JDK 1.5 disallows arrays of parametric types). So if it doesn't have
    // container structure, ignore it.
    ParametricStructure elemContainerStructure = elemStructure(elemContainer);
    if (elemContainerStructure == ParametricStructure.NONE) return;

    if (elemContainerStructure == null) { // handle clone()
      elemContainerStructure = newParametricType(elemContainer.getType());
      setStructureAndPush(elemContainer, elemContainerStructure);
    }
    ParametricStructure v1Structure = elemStructure(v1);
    int parmIdx =
        elemVar
            .getDeclarationTypeVariableIndex(); // TODO: index is NOT_DECLARED_TYPE_VARIABLE_INDEX
    // if the type variable comes from a supertype!!!
    if (parmIdx == CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX)
      return; // TODO: ParametricStructure should use type variable keys instead of index

    if (elemContainerStructure == v1Structure
        || containsSubStructure(
            v1Structure, elemContainerStructure)) { // avoid creating cyclic structure
      if (!(elemStructure(elemVar) == ParametricStructure.NONE))
        setStructureAndPush(elemVar, ParametricStructure.NONE);
      if (elemContainerStructure.getParameters()[parmIdx] == null) {
        elemContainerStructure.getParameters()[parmIdx] = ParametricStructure.NONE;
        fWorkList2.push(elemContainer);
      }
    } else if (updateStructureOfIthParamFrom(elemContainerStructure, parmIdx, v1Structure)) {
      setStructureAndPush(elemVar, elemContainerStructure.getParameters()[parmIdx]);
      fWorkList2.push(elemContainer);
      if (DEBUG_INITIALIZATION)
        System.out.println(
            "  updated structure of "
                + elemContainer
                + " to "
                + elemContainerStructure); //$NON-NLS-1$ //$NON-NLS-2$
    }
  }
  private Collection /*ConstraintVariable2*/ createVars(
      Collection /*ConstraintVariable2>*/ cvs, ParametricStructure[] parms) {
    if (parms.length > 0) { // happens, e.g., for Properties (non-parametric)
      //			Assert.isTrue(cvs.size() == parms.length, "cvs.length==" + cvs.size() + " parms.length="
      // + parms.length); //assumption is wrong in presence of NOT_DECLARED_TYPE_VARIABLE_INDEX
      for (Iterator iter = cvs.iterator(); iter.hasNext(); ) {
        CollectionElementVariable2 childVar = (CollectionElementVariable2) iter.next();
        int declarationTypeVariableIndex = childVar.getDeclarationTypeVariableIndex();

        if (declarationTypeVariableIndex
            != CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX)
          setElemStructure(childVar, parms[declarationTypeVariableIndex]);
      }
    } else {
      for (Iterator iter = cvs.iterator(); iter.hasNext(); ) {
        CollectionElementVariable2 childVar = (CollectionElementVariable2) iter.next();
        int declarationTypeVariableIndex = childVar.getDeclarationTypeVariableIndex();

        if (declarationTypeVariableIndex
            != CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX)
          setElemStructure(childVar, ParametricStructure.NONE);
      }
    }
    List result = new ArrayList(cvs.size() * 2); // roughly
    for (Iterator iter = cvs.iterator(); iter.hasNext(); ) {
      CollectionElementVariable2 childVar = (CollectionElementVariable2) iter.next();
      int declarationTypeVariableIndex = childVar.getDeclarationTypeVariableIndex();

      if (declarationTypeVariableIndex
          != CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX) {
        result.add(childVar);
        result.addAll(createVariablesFor(childVar));
      }
    }
    return result;
  }