protected void inheritMerged(HierNode<T> x) {
   BitSet mask = new BitSet(x.getBitMask() != null ? x.getBitMask().length() : 1);
   for (HierNode<T> p : x.getParents()) {
     mask.or(p.getBitMask());
   }
   updateMask(x, mask);
 }
  protected void encode(HierNode<T> node) {
    Collection<HierNode<T>> parents = node.getParents();
    // System.out.println( "Trying to encode " + node );
    switch (parents.size()) {
      case 0:
        BitSet zero = new BitSet();

        if (hasKey(zero)) {
          HierNode root = getNodeByKey(zero);

          if (root.getValue() != null) {
            fixedRoot = true;
            HierNode previousRoot = root;
            root = new HierNode((Object) null);
            root.addChild(previousRoot);
            previousRoot.addParent(root);

            root.setBitMask(zero);

            propagate(previousRoot, freeBit(root));
            add(root);
          }

          node.addParent(root);
          updateMask(node, increment(root.getBitMask(), freeBit(root)));

        } else {
          updateMask(node, new BitSet());
        }
        break;
      case 1:
        HierNode<T> parent = parents.iterator().next();
        updateMask(node, increment(parent.getBitMask(), freeBit(parent)));
        break;
      default:
        inheritMerged(node);
        // System.out.println( "
        // -----------------------------------------------------------------------------------------
        // " );
        resolveConflicts(node);
        break;
    }
  }
  protected void modify(HierNode<T> x, HierNode<T> y) {
    // System.out.println( "Modifying on a inc between " + x + " and " + y );

    int i = freeBit(x, y);
    // System.out.println( "I " + i );

    // System.out.println( "Getting parents of " + y + " >> " + y.getParents() );
    Collection<HierNode<T>> py = y.getParents();
    BitSet t = new BitSet(y.getBitMask().length());
    for (HierNode<T> parent : py) {
      t.or(parent.getBitMask());
    }

    BitSet d = singleBitDiff(t, y.getBitMask());
    int inDex = d.nextSetBit(0);

    if (inDex < 0) {
      propagate(y, i);
    } else {

      // System.out.println( "D " + toBinaryString( d ) );

      Set<HierNode<T>> ancestors = ancestorNodes(x);
      Set<HierNode<T>> affectedAncestors = new HashSet<HierNode<T>>();

      for (HierNode<T> anc : ancestors) {
        if (anc.getBitMask().get(inDex)) {
          affectedAncestors.add(anc);
        }
      }
      // System.out.println( "Ancestors of " + x + " >> " + ancestors );
      // System.out.println( "Affected " + x + " >> " + affectedAncestors );

      if (affectedAncestors.size() == 0) {
        return;
      }

      Set<HierNode<T>> gcs = gcs(affectedAncestors);
      // System.out.println( "GCS of Affected " + gcs );

      Set<HierNode<T>> affectedDescendants = new HashSet<HierNode<T>>();
      for (HierNode<T> g : gcs) {
        affectedDescendants.addAll(descendantNodes(g));
      }
      affectedDescendants.remove(x); // take x out it's not yet in the set

      int dx = firstOne(d);

      if (bottom.get(i)) {
        i = freeBit(new HierNode<T>(bottom));
      }

      for (HierNode<T> sub : affectedDescendants) {

        boolean keepsBit = false;
        for (HierNode<T> sup : sub.getParents()) {
          if (!keepsBit && !affectedDescendants.contains(sup) && sup.getBitMask().get(inDex)) {
            keepsBit = true;
          }
        }
        BitSet subMask = sub.getBitMask();
        if (!keepsBit) {
          subMask = decrement(subMask, dx);
        }
        subMask = increment(subMask, i);

        updateMask(sub, subMask);

        // System.out.println( "\tModified Desc" + sub );
      }

      inDex = d.nextSetBit(inDex + 1);
    }
  }