private void computeContainerStructure() {
    if (DEBUG_INITIALIZATION)
      System.out.println("\n*** Computing Container Structure ***\n"); // $NON-NLS-1$

    initializeContainerStructure();

    if (DEBUG_INITIALIZATION) dumpContainerStructure();

    while (!fWorkList2.isEmpty()) {
      ConstraintVariable2 v = (ConstraintVariable2) fWorkList2.pop();
      List /*<ITypeConstraint>*/ usedIn = fTCModel.getUsedIn(v);

      for (Iterator /*<ITypeConstraint>*/ iter = usedIn.iterator(); iter.hasNext(); ) {
        SubTypeConstraint2 stc = (SubTypeConstraint2) iter.next();

        ConstraintVariable2 lhs = stc.getLeft();
        ConstraintVariable2 rhs = stc.getRight();

        unifyContainerStructure(lhs, rhs);
      }

      TypeEquivalenceSet typeEquivalenceSet = v.getTypeEquivalenceSet();
      if (typeEquivalenceSet != null) {
        ConstraintVariable2[] contributingVariables = typeEquivalenceSet.getContributingVariables();
        for (int i = 0; i + 1 < contributingVariables.length; i++) {
          ConstraintVariable2 first = contributingVariables[i];
          ConstraintVariable2 second = contributingVariables[i + 1];

          unifyContainerStructure(first, second);
        }
      }
    }
    if (DEBUG_INITIALIZATION) dumpContainerStructure();
  }
 private void dumpContainerStructure() {
   System.out.println("\n*** Container Structure: ***\n"); // $NON-NLS-1$
   for (int i = 0; i < fAllConstraintVariables.length; i++) {
     ConstraintVariable2 v = fAllConstraintVariables[i];
     if (elemStructure(v) != null && !(elemStructure(v) == ParametricStructure.NONE))
       System.out.println(
           "elemStructure("
               + v.toString()
               + ") = "
               + elemStructure(v)); // $NON-NLS-1$ //$NON-NLS-2$
   }
   System.out.println();
 }
  /**
   * 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$
    }
  }
  protected static TType declaredTypeOf(ConstraintVariable2 cv) {
    // TODO: record original type of CollectionElementVariable2 iff source already had type
    // parameter
    return cv.getType();

    //		if (v instanceof ContextualExpressionVariable) {
    //			ContextualExpressionVariable ev= (ContextualExpressionVariable) v;
    //
    //			return ev.getBinding();
    //		} else if (v instanceof ReturnTypeVariable) {
    //			ReturnTypeVariable rv= (ReturnTypeVariable) v;
    //
    //			return rv.getBinding();
    //		} else if (v instanceof RawBindingVariable) {
    //			RawBindingVariable rv= (RawBindingVariable) v;
    //
    //			return rv.getBinding();
    //		} else if (v instanceof ParameterTypeVariable) {
    //			ParameterTypeVariable pv= (ParameterTypeVariable) v;
    //
    //			return pv.getBinding();
    //		} else
    //			return null;
  }
 /*
  * @see java.lang.Object#toString()
  */
 @Override
 public final String toString() {
   return fThenVariable.toString() + " <?= " + fElseVariable.toString(); // $NON-NLS-1$
 }
 /*
  * @see java.lang.Object#hashCode()
  */
 @Override
 public final int hashCode() {
   return fThenVariable.hashCode() ^ 33 * fElseVariable.hashCode();
 }