public void init(Map attributes) throws InvalidKeyException {
      if (wired != null) {
         throw new IllegalStateException();
      }
      Direction flow = (Direction) attributes.get(DIRECTION);
      if (flow == null) {
         flow = Direction.FORWARD;
      }

      int optimalSize = 0;
      for (Iterator it = stageKeys.listIterator(); it.hasNext(); ) {
         Object id = it.next();
         Map attr = (Map) attributes.get(id);
         attr.put(Stage.DIRECTION, flow);
         Stage stage = (Stage) stages.get(id);
         stage.init(attr);
         optimalSize = optimalSize == 0
               ? stage.currentBlockSize()
               : lcm(optimalSize, stage.currentBlockSize());
      }

      if (flow == Direction.REVERSED) { // reverse order
         Collections.reverse(stageKeys);
      }
      wired = flow;
      blockSize = optimalSize;
   }